| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <assert.h> // For assert | 5 #include <assert.h> // For assert |
| 6 #include <limits.h> // For LONG_MIN, LONG_MAX. | 6 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 7 | 7 |
| 8 #if V8_TARGET_ARCH_PPC | 8 #if V8_TARGET_ARCH_PPC |
| 9 | 9 |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 1961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1972 JumpIfSmi(result, &done); | 1972 JumpIfSmi(result, &done); |
| 1973 CompareObjectType(result, temp, temp2, MAP_TYPE); | 1973 CompareObjectType(result, temp, temp2, MAP_TYPE); |
| 1974 bne(&done); | 1974 bne(&done); |
| 1975 LoadP(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset)); | 1975 LoadP(result, FieldMemOperand(result, Map::kConstructorOrBackPointerOffset)); |
| 1976 b(&loop); | 1976 b(&loop); |
| 1977 bind(&done); | 1977 bind(&done); |
| 1978 } | 1978 } |
| 1979 | 1979 |
| 1980 | 1980 |
| 1981 void MacroAssembler::TryGetFunctionPrototype(Register function, Register result, | 1981 void MacroAssembler::TryGetFunctionPrototype(Register function, Register result, |
| 1982 Register scratch, Label* miss, | 1982 Register scratch, Label* miss) { |
| 1983 bool miss_on_bound_function) { | |
| 1984 Label non_instance; | |
| 1985 if (miss_on_bound_function) { | |
| 1986 // Check that the receiver isn't a smi. | |
| 1987 JumpIfSmi(function, miss); | |
| 1988 | |
| 1989 // Check that the function really is a function. Load map into result reg. | |
| 1990 CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE); | |
| 1991 bne(miss); | |
| 1992 | |
| 1993 LoadP(scratch, | |
| 1994 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | |
| 1995 lwz(scratch, | |
| 1996 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); | |
| 1997 TestBit(scratch, | |
| 1998 #if V8_TARGET_ARCH_PPC64 | |
| 1999 SharedFunctionInfo::kBoundFunction, | |
| 2000 #else | |
| 2001 SharedFunctionInfo::kBoundFunction + kSmiTagSize, | |
| 2002 #endif | |
| 2003 r0); | |
| 2004 bne(miss, cr0); | |
| 2005 | |
| 2006 // Make sure that the function has an instance prototype. | |
| 2007 lbz(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); | |
| 2008 andi(r0, scratch, Operand(1 << Map::kHasNonInstancePrototype)); | |
| 2009 bne(&non_instance, cr0); | |
| 2010 } | |
| 2011 | |
| 2012 // Get the prototype or initial map from the function. | 1983 // Get the prototype or initial map from the function. |
| 2013 LoadP(result, | 1984 LoadP(result, |
| 2014 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 1985 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2015 | 1986 |
| 2016 // If the prototype or initial map is the hole, don't return it and | 1987 // If the prototype or initial map is the hole, don't return it and |
| 2017 // simply miss the cache instead. This will allow us to allocate a | 1988 // simply miss the cache instead. This will allow us to allocate a |
| 2018 // prototype object on-demand in the runtime system. | 1989 // prototype object on-demand in the runtime system. |
| 2019 LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 1990 LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 2020 cmp(result, r0); | 1991 cmp(result, r0); |
| 2021 beq(miss); | 1992 beq(miss); |
| 2022 | 1993 |
| 2023 // If the function does not have an initial map, we're done. | 1994 // If the function does not have an initial map, we're done. |
| 2024 Label done; | 1995 Label done; |
| 2025 CompareObjectType(result, scratch, scratch, MAP_TYPE); | 1996 CompareObjectType(result, scratch, scratch, MAP_TYPE); |
| 2026 bne(&done); | 1997 bne(&done); |
| 2027 | 1998 |
| 2028 // Get the prototype from the initial map. | 1999 // Get the prototype from the initial map. |
| 2029 LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 2000 LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 2030 | 2001 |
| 2031 if (miss_on_bound_function) { | |
| 2032 b(&done); | |
| 2033 | |
| 2034 // Non-instance prototype: Fetch prototype from constructor field | |
| 2035 // in initial map. | |
| 2036 bind(&non_instance); | |
| 2037 GetMapConstructor(result, result, scratch, ip); | |
| 2038 } | |
| 2039 | |
| 2040 // All done. | 2002 // All done. |
| 2041 bind(&done); | 2003 bind(&done); |
| 2042 } | 2004 } |
| 2043 | 2005 |
| 2044 | 2006 |
| 2045 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id, | 2007 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id, |
| 2046 Condition cond) { | 2008 Condition cond) { |
| 2047 DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. | 2009 DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. |
| 2048 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond); | 2010 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, cond); |
| 2049 } | 2011 } |
| (...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3236 slwi(r0, result, Operand(16)); | 3198 slwi(r0, result, Operand(16)); |
| 3237 // sign-extend and add the load offset | 3199 // sign-extend and add the load offset |
| 3238 lwz(result, MemOperand(location, kInstrSize)); | 3200 lwz(result, MemOperand(location, kInstrSize)); |
| 3239 extsh(result, result); | 3201 extsh(result, result); |
| 3240 add(result, r0, result); | 3202 add(result, r0, result); |
| 3241 | 3203 |
| 3242 bind(&done); | 3204 bind(&done); |
| 3243 } | 3205 } |
| 3244 | 3206 |
| 3245 | 3207 |
| 3246 void MacroAssembler::SetRelocatedValue(Register location, Register scratch, | |
| 3247 Register new_value) { | |
| 3248 lwz(scratch, MemOperand(location)); | |
| 3249 | |
| 3250 if (FLAG_enable_embedded_constant_pool) { | |
| 3251 if (emit_debug_code()) { | |
| 3252 // Check that the instruction sequence is a load from the constant pool | |
| 3253 ExtractBitMask(scratch, scratch, 0x1f * B16); | |
| 3254 cmpi(scratch, Operand(kConstantPoolRegister.code())); | |
| 3255 Check(eq, kTheInstructionToPatchShouldBeALoadFromConstantPool); | |
| 3256 // Scratch was clobbered. Restore it. | |
| 3257 lwz(scratch, MemOperand(location)); | |
| 3258 } | |
| 3259 DecodeConstantPoolOffset(scratch, location); | |
| 3260 StorePX(new_value, MemOperand(kConstantPoolRegister, scratch)); | |
| 3261 return; | |
| 3262 } | |
| 3263 | |
| 3264 // This code assumes a FIXED_SEQUENCE for lis/ori | |
| 3265 | |
| 3266 // At this point scratch is a lis instruction. | |
| 3267 if (emit_debug_code()) { | |
| 3268 And(scratch, scratch, Operand(kOpcodeMask | (0x1f * B16))); | |
| 3269 Cmpi(scratch, Operand(ADDIS), r0); | |
| 3270 Check(eq, kTheInstructionToPatchShouldBeALis); | |
| 3271 lwz(scratch, MemOperand(location)); | |
| 3272 } | |
| 3273 | |
| 3274 // insert new high word into lis instruction | |
| 3275 #if V8_TARGET_ARCH_PPC64 | |
| 3276 srdi(ip, new_value, Operand(32)); | |
| 3277 rlwimi(scratch, ip, 16, 16, 31); | |
| 3278 #else | |
| 3279 rlwimi(scratch, new_value, 16, 16, 31); | |
| 3280 #endif | |
| 3281 | |
| 3282 stw(scratch, MemOperand(location)); | |
| 3283 | |
| 3284 lwz(scratch, MemOperand(location, kInstrSize)); | |
| 3285 // scratch is now ori. | |
| 3286 if (emit_debug_code()) { | |
| 3287 And(scratch, scratch, Operand(kOpcodeMask)); | |
| 3288 Cmpi(scratch, Operand(ORI), r0); | |
| 3289 Check(eq, kTheInstructionShouldBeAnOri); | |
| 3290 lwz(scratch, MemOperand(location, kInstrSize)); | |
| 3291 } | |
| 3292 | |
| 3293 // insert new low word into ori instruction | |
| 3294 #if V8_TARGET_ARCH_PPC64 | |
| 3295 rlwimi(scratch, ip, 0, 16, 31); | |
| 3296 #else | |
| 3297 rlwimi(scratch, new_value, 0, 16, 31); | |
| 3298 #endif | |
| 3299 stw(scratch, MemOperand(location, kInstrSize)); | |
| 3300 | |
| 3301 #if V8_TARGET_ARCH_PPC64 | |
| 3302 if (emit_debug_code()) { | |
| 3303 lwz(scratch, MemOperand(location, 2 * kInstrSize)); | |
| 3304 // scratch is now sldi. | |
| 3305 And(scratch, scratch, Operand(kOpcodeMask | kExt5OpcodeMask)); | |
| 3306 Cmpi(scratch, Operand(EXT5 | RLDICR), r0); | |
| 3307 Check(eq, kTheInstructionShouldBeASldi); | |
| 3308 } | |
| 3309 | |
| 3310 lwz(scratch, MemOperand(location, 3 * kInstrSize)); | |
| 3311 // scratch is now ori. | |
| 3312 if (emit_debug_code()) { | |
| 3313 And(scratch, scratch, Operand(kOpcodeMask)); | |
| 3314 Cmpi(scratch, Operand(ORIS), r0); | |
| 3315 Check(eq, kTheInstructionShouldBeAnOris); | |
| 3316 lwz(scratch, MemOperand(location, 3 * kInstrSize)); | |
| 3317 } | |
| 3318 | |
| 3319 rlwimi(scratch, new_value, 16, 16, 31); | |
| 3320 stw(scratch, MemOperand(location, 3 * kInstrSize)); | |
| 3321 | |
| 3322 lwz(scratch, MemOperand(location, 4 * kInstrSize)); | |
| 3323 // scratch is now ori. | |
| 3324 if (emit_debug_code()) { | |
| 3325 And(scratch, scratch, Operand(kOpcodeMask)); | |
| 3326 Cmpi(scratch, Operand(ORI), r0); | |
| 3327 Check(eq, kTheInstructionShouldBeAnOri); | |
| 3328 lwz(scratch, MemOperand(location, 4 * kInstrSize)); | |
| 3329 } | |
| 3330 rlwimi(scratch, new_value, 0, 16, 31); | |
| 3331 stw(scratch, MemOperand(location, 4 * kInstrSize)); | |
| 3332 #endif | |
| 3333 | |
| 3334 // Update the I-cache so the new lis and addic can be executed. | |
| 3335 #if V8_TARGET_ARCH_PPC64 | |
| 3336 FlushICache(location, 5 * kInstrSize, scratch); | |
| 3337 #else | |
| 3338 FlushICache(location, 2 * kInstrSize, scratch); | |
| 3339 #endif | |
| 3340 } | |
| 3341 | |
| 3342 | |
| 3343 void MacroAssembler::GetRelocatedValue(Register location, Register result, | |
| 3344 Register scratch) { | |
| 3345 lwz(result, MemOperand(location)); | |
| 3346 | |
| 3347 if (FLAG_enable_embedded_constant_pool) { | |
| 3348 if (emit_debug_code()) { | |
| 3349 // Check that the instruction sequence is a load from the constant pool | |
| 3350 ExtractBitMask(result, result, 0x1f * B16); | |
| 3351 cmpi(result, Operand(kConstantPoolRegister.code())); | |
| 3352 Check(eq, kTheInstructionToPatchShouldBeALoadFromConstantPool); | |
| 3353 lwz(result, MemOperand(location)); | |
| 3354 } | |
| 3355 DecodeConstantPoolOffset(result, location); | |
| 3356 LoadPX(result, MemOperand(kConstantPoolRegister, result)); | |
| 3357 return; | |
| 3358 } | |
| 3359 | |
| 3360 // This code assumes a FIXED_SEQUENCE for lis/ori | |
| 3361 if (emit_debug_code()) { | |
| 3362 And(result, result, Operand(kOpcodeMask | (0x1f * B16))); | |
| 3363 Cmpi(result, Operand(ADDIS), r0); | |
| 3364 Check(eq, kTheInstructionShouldBeALis); | |
| 3365 lwz(result, MemOperand(location)); | |
| 3366 } | |
| 3367 | |
| 3368 // result now holds a lis instruction. Extract the immediate. | |
| 3369 slwi(result, result, Operand(16)); | |
| 3370 | |
| 3371 lwz(scratch, MemOperand(location, kInstrSize)); | |
| 3372 if (emit_debug_code()) { | |
| 3373 And(scratch, scratch, Operand(kOpcodeMask)); | |
| 3374 Cmpi(scratch, Operand(ORI), r0); | |
| 3375 Check(eq, kTheInstructionShouldBeAnOri); | |
| 3376 lwz(scratch, MemOperand(location, kInstrSize)); | |
| 3377 } | |
| 3378 // Copy the low 16bits from ori instruction into result | |
| 3379 rlwimi(result, scratch, 0, 16, 31); | |
| 3380 | |
| 3381 #if V8_TARGET_ARCH_PPC64 | |
| 3382 if (emit_debug_code()) { | |
| 3383 lwz(scratch, MemOperand(location, 2 * kInstrSize)); | |
| 3384 // scratch is now sldi. | |
| 3385 And(scratch, scratch, Operand(kOpcodeMask | kExt5OpcodeMask)); | |
| 3386 Cmpi(scratch, Operand(EXT5 | RLDICR), r0); | |
| 3387 Check(eq, kTheInstructionShouldBeASldi); | |
| 3388 } | |
| 3389 | |
| 3390 lwz(scratch, MemOperand(location, 3 * kInstrSize)); | |
| 3391 // scratch is now ori. | |
| 3392 if (emit_debug_code()) { | |
| 3393 And(scratch, scratch, Operand(kOpcodeMask)); | |
| 3394 Cmpi(scratch, Operand(ORIS), r0); | |
| 3395 Check(eq, kTheInstructionShouldBeAnOris); | |
| 3396 lwz(scratch, MemOperand(location, 3 * kInstrSize)); | |
| 3397 } | |
| 3398 sldi(result, result, Operand(16)); | |
| 3399 rldimi(result, scratch, 0, 48); | |
| 3400 | |
| 3401 lwz(scratch, MemOperand(location, 4 * kInstrSize)); | |
| 3402 // scratch is now ori. | |
| 3403 if (emit_debug_code()) { | |
| 3404 And(scratch, scratch, Operand(kOpcodeMask)); | |
| 3405 Cmpi(scratch, Operand(ORI), r0); | |
| 3406 Check(eq, kTheInstructionShouldBeAnOri); | |
| 3407 lwz(scratch, MemOperand(location, 4 * kInstrSize)); | |
| 3408 } | |
| 3409 sldi(result, result, Operand(16)); | |
| 3410 rldimi(result, scratch, 0, 48); | |
| 3411 #endif | |
| 3412 } | |
| 3413 | |
| 3414 | |
| 3415 void MacroAssembler::CheckPageFlag( | 3208 void MacroAssembler::CheckPageFlag( |
| 3416 Register object, | 3209 Register object, |
| 3417 Register scratch, // scratch may be same register as object | 3210 Register scratch, // scratch may be same register as object |
| 3418 int mask, Condition cc, Label* condition_met) { | 3211 int mask, Condition cc, Label* condition_met) { |
| 3419 DCHECK(cc == ne || cc == eq); | 3212 DCHECK(cc == ne || cc == eq); |
| 3420 ClearRightImm(scratch, object, Operand(kPageSizeBits)); | 3213 ClearRightImm(scratch, object, Operand(kPageSizeBits)); |
| 3421 LoadP(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); | 3214 LoadP(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); |
| 3422 | 3215 |
| 3423 And(r0, scratch, Operand(mask), SetRC); | 3216 And(r0, scratch, Operand(mask), SetRC); |
| 3424 | 3217 |
| (...skipping 1221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4646 } | 4439 } |
| 4647 if (mag.shift > 0) srawi(result, result, mag.shift); | 4440 if (mag.shift > 0) srawi(result, result, mag.shift); |
| 4648 ExtractBit(r0, dividend, 31); | 4441 ExtractBit(r0, dividend, 31); |
| 4649 add(result, result, r0); | 4442 add(result, result, r0); |
| 4650 } | 4443 } |
| 4651 | 4444 |
| 4652 } // namespace internal | 4445 } // namespace internal |
| 4653 } // namespace v8 | 4446 } // namespace v8 |
| 4654 | 4447 |
| 4655 #endif // V8_TARGET_ARCH_PPC | 4448 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |