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 |