| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 297     vmov(dst, src); | 297     vmov(dst, src); | 
| 298   } | 298   } | 
| 299 } | 299 } | 
| 300 | 300 | 
| 301 | 301 | 
| 302 void MacroAssembler::And(Register dst, Register src1, const Operand& src2, | 302 void MacroAssembler::And(Register dst, Register src1, const Operand& src2, | 
| 303                          Condition cond) { | 303                          Condition cond) { | 
| 304   if (!src2.is_reg() && | 304   if (!src2.is_reg() && | 
| 305       !src2.must_output_reloc_info(this) && | 305       !src2.must_output_reloc_info(this) && | 
| 306       src2.immediate() == 0) { | 306       src2.immediate() == 0) { | 
| 307     mov(dst, Operand(0, RelocInfo::NONE32), LeaveCC, cond); | 307     mov(dst, Operand::Zero(), LeaveCC, cond); | 
| 308   } else if (!src2.is_single_instruction(this) && | 308   } else if (!src2.is_single_instruction(this) && | 
| 309              !src2.must_output_reloc_info(this) && | 309              !src2.must_output_reloc_info(this) && | 
| 310              CpuFeatures::IsSupported(ARMv7) && | 310              CpuFeatures::IsSupported(ARMv7) && | 
| 311              IsPowerOf2(src2.immediate() + 1)) { | 311              IsPowerOf2(src2.immediate() + 1)) { | 
| 312     ubfx(dst, src1, 0, | 312     ubfx(dst, src1, 0, | 
| 313         WhichPowerOf2(static_cast<uint32_t>(src2.immediate()) + 1), cond); | 313         WhichPowerOf2(static_cast<uint32_t>(src2.immediate()) + 1), cond); | 
| 314   } else { | 314   } else { | 
| 315     and_(dst, src1, src2, LeaveCC, cond); | 315     and_(dst, src1, src2, LeaveCC, cond); | 
| 316   } | 316   } | 
| 317 } | 317 } | 
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 403     int satval = (1 << satpos) - 1; | 403     int satval = (1 << satpos) - 1; | 
| 404 | 404 | 
| 405     if (cond != al) { | 405     if (cond != al) { | 
| 406       b(NegateCondition(cond), &done);  // Skip saturate if !condition. | 406       b(NegateCondition(cond), &done);  // Skip saturate if !condition. | 
| 407     } | 407     } | 
| 408     if (!(src.is_reg() && dst.is(src.rm()))) { | 408     if (!(src.is_reg() && dst.is(src.rm()))) { | 
| 409       mov(dst, src); | 409       mov(dst, src); | 
| 410     } | 410     } | 
| 411     tst(dst, Operand(~satval)); | 411     tst(dst, Operand(~satval)); | 
| 412     b(eq, &done); | 412     b(eq, &done); | 
| 413     mov(dst, Operand(0, RelocInfo::NONE32), LeaveCC, mi);  // 0 if negative. | 413     mov(dst, Operand::Zero(), LeaveCC, mi);  // 0 if negative. | 
| 414     mov(dst, Operand(satval), LeaveCC, pl);  // satval if positive. | 414     mov(dst, Operand(satval), LeaveCC, pl);  // satval if positive. | 
| 415     bind(&done); | 415     bind(&done); | 
| 416   } else { | 416   } else { | 
| 417     usat(dst, satpos, src, cond); | 417     usat(dst, satpos, src, cond); | 
| 418   } | 418   } | 
| 419 } | 419 } | 
| 420 | 420 | 
| 421 | 421 | 
| 422 void MacroAssembler::LoadRoot(Register destination, | 422 void MacroAssembler::LoadRoot(Register destination, | 
| 423                               Heap::RootListIndex index, | 423                               Heap::RootListIndex index, | 
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 857 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { | 857 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { | 
| 858   // Set up the frame structure on the stack. | 858   // Set up the frame structure on the stack. | 
| 859   ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); | 859   ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); | 
| 860   ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); | 860   ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); | 
| 861   ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); | 861   ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); | 
| 862   Push(lr, fp); | 862   Push(lr, fp); | 
| 863   mov(fp, Operand(sp));  // Set up new frame pointer. | 863   mov(fp, Operand(sp));  // Set up new frame pointer. | 
| 864   // Reserve room for saved entry sp and code object. | 864   // Reserve room for saved entry sp and code object. | 
| 865   sub(sp, sp, Operand(2 * kPointerSize)); | 865   sub(sp, sp, Operand(2 * kPointerSize)); | 
| 866   if (emit_debug_code()) { | 866   if (emit_debug_code()) { | 
| 867     mov(ip, Operand(0)); | 867     mov(ip, Operand::Zero()); | 
| 868     str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 868     str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 
| 869   } | 869   } | 
| 870   mov(ip, Operand(CodeObject())); | 870   mov(ip, Operand(CodeObject())); | 
| 871   str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 871   str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 
| 872 | 872 | 
| 873   // Save the frame pointer and the context in top. | 873   // Save the frame pointer and the context in top. | 
| 874   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 874   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 
| 875   str(fp, MemOperand(ip)); | 875   str(fp, MemOperand(ip)); | 
| 876   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 876   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 
| 877   str(cp, MemOperand(ip)); | 877   str(cp, MemOperand(ip)); | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 941     // Calculate the stack location of the saved doubles and restore them. | 941     // Calculate the stack location of the saved doubles and restore them. | 
| 942     const int offset = 2 * kPointerSize; | 942     const int offset = 2 * kPointerSize; | 
| 943     sub(r3, fp, Operand(offset + DwVfpRegister::kNumRegisters * kDoubleSize)); | 943     sub(r3, fp, Operand(offset + DwVfpRegister::kNumRegisters * kDoubleSize)); | 
| 944     DwVfpRegister first = d0; | 944     DwVfpRegister first = d0; | 
| 945     DwVfpRegister last = | 945     DwVfpRegister last = | 
| 946         DwVfpRegister::from_code(DwVfpRegister::kNumRegisters - 1); | 946         DwVfpRegister::from_code(DwVfpRegister::kNumRegisters - 1); | 
| 947     vldm(ia, r3, first, last); | 947     vldm(ia, r3, first, last); | 
| 948   } | 948   } | 
| 949 | 949 | 
| 950   // Clear top frame. | 950   // Clear top frame. | 
| 951   mov(r3, Operand(0, RelocInfo::NONE32)); | 951   mov(r3, Operand::Zero()); | 
| 952   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 952   mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 
| 953   str(r3, MemOperand(ip)); | 953   str(r3, MemOperand(ip)); | 
| 954 | 954 | 
| 955   // Restore current context from top and clear it in debug mode. | 955   // Restore current context from top and clear it in debug mode. | 
| 956   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 956   mov(ip, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 
| 957   ldr(cp, MemOperand(ip)); | 957   ldr(cp, MemOperand(ip)); | 
| 958 #ifdef DEBUG | 958 #ifdef DEBUG | 
| 959   str(r3, MemOperand(ip)); | 959   str(r3, MemOperand(ip)); | 
| 960 #endif | 960 #endif | 
| 961 | 961 | 
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1211 | 1211 | 
| 1212   ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 1212   ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 
| 1213   ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 1213   ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 
| 1214   tst(scratch, Operand(kIsNotStringMask)); | 1214   tst(scratch, Operand(kIsNotStringMask)); | 
| 1215   b(ne, fail); | 1215   b(ne, fail); | 
| 1216 } | 1216 } | 
| 1217 | 1217 | 
| 1218 | 1218 | 
| 1219 #ifdef ENABLE_DEBUGGER_SUPPORT | 1219 #ifdef ENABLE_DEBUGGER_SUPPORT | 
| 1220 void MacroAssembler::DebugBreak() { | 1220 void MacroAssembler::DebugBreak() { | 
| 1221   mov(r0, Operand(0, RelocInfo::NONE32)); | 1221   mov(r0, Operand::Zero()); | 
| 1222   mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); | 1222   mov(r1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); | 
| 1223   CEntryStub ces(1); | 1223   CEntryStub ces(1); | 
| 1224   ASSERT(AllowThisStubCall(&ces)); | 1224   ASSERT(AllowThisStubCall(&ces)); | 
| 1225   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 1225   Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 
| 1226 } | 1226 } | 
| 1227 #endif | 1227 #endif | 
| 1228 | 1228 | 
| 1229 | 1229 | 
| 1230 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, | 1230 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, | 
| 1231                                     int handler_index) { | 1231                                     int handler_index) { | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 1242   // Set up the code object (r5) and the state (r6) for pushing. | 1242   // Set up the code object (r5) and the state (r6) for pushing. | 
| 1243   unsigned state = | 1243   unsigned state = | 
| 1244       StackHandler::IndexField::encode(handler_index) | | 1244       StackHandler::IndexField::encode(handler_index) | | 
| 1245       StackHandler::KindField::encode(kind); | 1245       StackHandler::KindField::encode(kind); | 
| 1246   mov(r5, Operand(CodeObject())); | 1246   mov(r5, Operand(CodeObject())); | 
| 1247   mov(r6, Operand(state)); | 1247   mov(r6, Operand(state)); | 
| 1248 | 1248 | 
| 1249   // Push the frame pointer, context, state, and code object. | 1249   // Push the frame pointer, context, state, and code object. | 
| 1250   if (kind == StackHandler::JS_ENTRY) { | 1250   if (kind == StackHandler::JS_ENTRY) { | 
| 1251     mov(r7, Operand(Smi::FromInt(0)));  // Indicates no context. | 1251     mov(r7, Operand(Smi::FromInt(0)));  // Indicates no context. | 
| 1252     mov(ip, Operand(0, RelocInfo::NONE32));  // NULL frame pointer. | 1252     mov(ip, Operand::Zero());  // NULL frame pointer. | 
| 1253     stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | ip.bit()); | 1253     stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | ip.bit()); | 
| 1254   } else { | 1254   } else { | 
| 1255     stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit()); | 1255     stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit()); | 
| 1256   } | 1256   } | 
| 1257 | 1257 | 
| 1258   // Link the current handler as the next handler. | 1258   // Link the current handler as the next handler. | 
| 1259   mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 1259   mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 
| 1260   ldr(r5, MemOperand(r6)); | 1260   ldr(r5, MemOperand(r6)); | 
| 1261   push(r5); | 1261   push(r5); | 
| 1262   // Set this new handler as the current one. | 1262   // Set this new handler as the current one. | 
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1366   Label same_contexts; | 1366   Label same_contexts; | 
| 1367 | 1367 | 
| 1368   ASSERT(!holder_reg.is(scratch)); | 1368   ASSERT(!holder_reg.is(scratch)); | 
| 1369   ASSERT(!holder_reg.is(ip)); | 1369   ASSERT(!holder_reg.is(ip)); | 
| 1370   ASSERT(!scratch.is(ip)); | 1370   ASSERT(!scratch.is(ip)); | 
| 1371 | 1371 | 
| 1372   // Load current lexical context from the stack frame. | 1372   // Load current lexical context from the stack frame. | 
| 1373   ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1373   ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 
| 1374   // In debug mode, make sure the lexical context is set. | 1374   // In debug mode, make sure the lexical context is set. | 
| 1375 #ifdef DEBUG | 1375 #ifdef DEBUG | 
| 1376   cmp(scratch, Operand(0, RelocInfo::NONE32)); | 1376   cmp(scratch, Operand::Zero()); | 
| 1377   Check(ne, "we should not have an empty lexical context"); | 1377   Check(ne, "we should not have an empty lexical context"); | 
| 1378 #endif | 1378 #endif | 
| 1379 | 1379 | 
| 1380   // Load the native context of the current context. | 1380   // Load the native context of the current context. | 
| 1381   int offset = | 1381   int offset = | 
| 1382       Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; | 1382       Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; | 
| 1383   ldr(scratch, FieldMemOperand(scratch, offset)); | 1383   ldr(scratch, FieldMemOperand(scratch, offset)); | 
| 1384   ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 1384   ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 
| 1385 | 1385 | 
| 1386   // Check the context is a native context. | 1386   // Check the context is a native context. | 
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2018   uint32_t offset = FixedDoubleArray::kHeaderSize - elements_offset + | 2018   uint32_t offset = FixedDoubleArray::kHeaderSize - elements_offset + | 
| 2019       sizeof(kHoleNanLower32); | 2019       sizeof(kHoleNanLower32); | 
| 2020   str(exponent_reg, FieldMemOperand(scratch1, offset)); | 2020   str(exponent_reg, FieldMemOperand(scratch1, offset)); | 
| 2021   jmp(&done); | 2021   jmp(&done); | 
| 2022 | 2022 | 
| 2023   bind(&maybe_nan); | 2023   bind(&maybe_nan); | 
| 2024   // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise | 2024   // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise | 
| 2025   // it's an Infinity, and the non-NaN code path applies. | 2025   // it's an Infinity, and the non-NaN code path applies. | 
| 2026   b(gt, &is_nan); | 2026   b(gt, &is_nan); | 
| 2027   ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); | 2027   ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); | 
| 2028   cmp(mantissa_reg, Operand(0)); | 2028   cmp(mantissa_reg, Operand::Zero()); | 
| 2029   b(eq, &have_double_value); | 2029   b(eq, &have_double_value); | 
| 2030   bind(&is_nan); | 2030   bind(&is_nan); | 
| 2031   // Load canonical NaN for storing into the double array. | 2031   // Load canonical NaN for storing into the double array. | 
| 2032   uint64_t nan_int64 = BitCast<uint64_t>( | 2032   uint64_t nan_int64 = BitCast<uint64_t>( | 
| 2033       FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | 2033       FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | 
| 2034   mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64))); | 2034   mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64))); | 
| 2035   mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32))); | 2035   mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32))); | 
| 2036   jmp(&have_double_value); | 2036   jmp(&have_double_value); | 
| 2037 | 2037 | 
| 2038   bind(&smi_value); | 2038   bind(&smi_value); | 
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2270     CallCFunction(ExternalReference::log_leave_external_function(isolate()), 0); | 2270     CallCFunction(ExternalReference::log_leave_external_function(isolate()), 0); | 
| 2271     PopSafepointRegisters(); | 2271     PopSafepointRegisters(); | 
| 2272   } | 2272   } | 
| 2273 | 2273 | 
| 2274   Label promote_scheduled_exception; | 2274   Label promote_scheduled_exception; | 
| 2275   Label delete_allocated_handles; | 2275   Label delete_allocated_handles; | 
| 2276   Label leave_exit_frame; | 2276   Label leave_exit_frame; | 
| 2277 | 2277 | 
| 2278   // If result is non-zero, dereference to get the result value | 2278   // If result is non-zero, dereference to get the result value | 
| 2279   // otherwise set it to undefined. | 2279   // otherwise set it to undefined. | 
| 2280   cmp(r0, Operand(0)); | 2280   cmp(r0, Operand::Zero()); | 
| 2281   LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 2281   LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 
| 2282   ldr(r0, MemOperand(r0), ne); | 2282   ldr(r0, MemOperand(r0), ne); | 
| 2283 | 2283 | 
| 2284   // No more valid handles (the result handle was the last one). Restore | 2284   // No more valid handles (the result handle was the last one). Restore | 
| 2285   // previous handle scope. | 2285   // previous handle scope. | 
| 2286   str(r4, MemOperand(r7, kNextOffset)); | 2286   str(r4, MemOperand(r7, kNextOffset)); | 
| 2287   if (emit_debug_code()) { | 2287   if (emit_debug_code()) { | 
| 2288     ldr(r1, MemOperand(r7, kLevelOffset)); | 2288     ldr(r1, MemOperand(r7, kLevelOffset)); | 
| 2289     cmp(r1, r6); | 2289     cmp(r1, r6); | 
| 2290     Check(eq, "Unexpected level after return from api call"); | 2290     Check(eq, "Unexpected level after return from api call"); | 
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2449     Label right_exponent, done; | 2449     Label right_exponent, done; | 
| 2450     // Get exponent word. | 2450     // Get exponent word. | 
| 2451     ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset)); | 2451     ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset)); | 
| 2452     // Get exponent alone in scratch2. | 2452     // Get exponent alone in scratch2. | 
| 2453     Ubfx(scratch2, | 2453     Ubfx(scratch2, | 
| 2454          scratch, | 2454          scratch, | 
| 2455          HeapNumber::kExponentShift, | 2455          HeapNumber::kExponentShift, | 
| 2456          HeapNumber::kExponentBits); | 2456          HeapNumber::kExponentBits); | 
| 2457     // Load dest with zero.  We use this either for the final shift or | 2457     // Load dest with zero.  We use this either for the final shift or | 
| 2458     // for the answer. | 2458     // for the answer. | 
| 2459     mov(dest, Operand(0, RelocInfo::NONE32)); | 2459     mov(dest, Operand::Zero()); | 
| 2460     // Check whether the exponent matches a 32 bit signed int that is not a Smi. | 2460     // Check whether the exponent matches a 32 bit signed int that is not a Smi. | 
| 2461     // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is | 2461     // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). This is | 
| 2462     // the exponent that we are fastest at and also the highest exponent we can | 2462     // the exponent that we are fastest at and also the highest exponent we can | 
| 2463     // handle here. | 2463     // handle here. | 
| 2464     const uint32_t non_smi_exponent = HeapNumber::kExponentBias + 30; | 2464     const uint32_t non_smi_exponent = HeapNumber::kExponentBias + 30; | 
| 2465     // The non_smi_exponent, 0x41d, is too big for ARM's immediate field so we | 2465     // The non_smi_exponent, 0x41d, is too big for ARM's immediate field so we | 
| 2466     // split it up to avoid a constant pool entry.  You can't do that in general | 2466     // split it up to avoid a constant pool entry.  You can't do that in general | 
| 2467     // for cmp because of the overflow flag, but we know the exponent is in the | 2467     // for cmp because of the overflow flag, but we know the exponent is in the | 
| 2468     // range 0-2047 so there is no overflow. | 2468     // range 0-2047 so there is no overflow. | 
| 2469     int fudge_factor = 0x400; | 2469     int fudge_factor = 0x400; | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2503     tst(scratch, Operand(HeapNumber::kSignMask)); | 2503     tst(scratch, Operand(HeapNumber::kSignMask)); | 
| 2504     // Get the second half of the double. For some exponents we don't | 2504     // Get the second half of the double. For some exponents we don't | 
| 2505     // actually need this because the bits get shifted out again, but | 2505     // actually need this because the bits get shifted out again, but | 
| 2506     // it's probably slower to test than just to do it. | 2506     // it's probably slower to test than just to do it. | 
| 2507     ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset)); | 2507     ldr(scratch, FieldMemOperand(source, HeapNumber::kMantissaOffset)); | 
| 2508     // Shift down 22 bits to get the last 10 bits. | 2508     // Shift down 22 bits to get the last 10 bits. | 
| 2509     orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance)); | 2509     orr(scratch, scratch2, Operand(scratch, LSR, 32 - shift_distance)); | 
| 2510     // Move down according to the exponent. | 2510     // Move down according to the exponent. | 
| 2511     mov(dest, Operand(scratch, LSR, dest)); | 2511     mov(dest, Operand(scratch, LSR, dest)); | 
| 2512     // Fix sign if sign bit was set. | 2512     // Fix sign if sign bit was set. | 
| 2513     rsb(dest, dest, Operand(0, RelocInfo::NONE32), LeaveCC, ne); | 2513     rsb(dest, dest, Operand::Zero(), LeaveCC, ne); | 
| 2514     bind(&done); | 2514     bind(&done); | 
| 2515   } | 2515   } | 
| 2516 } | 2516 } | 
| 2517 | 2517 | 
| 2518 | 2518 | 
| 2519 void MacroAssembler::TryFastDoubleToInt32(Register result, | 2519 void MacroAssembler::TryFastDoubleToInt32(Register result, | 
| 2520                                           DwVfpRegister double_input, | 2520                                           DwVfpRegister double_input, | 
| 2521                                           DwVfpRegister double_scratch, | 2521                                           DwVfpRegister double_scratch, | 
| 2522                                           Label* done) { | 2522                                           Label* done) { | 
| 2523   ASSERT(!double_input.is(double_scratch)); | 2523   ASSERT(!double_input.is(double_scratch)); | 
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2594   Label done, normal_exponent, restore_sign; | 2594   Label done, normal_exponent, restore_sign; | 
| 2595 | 2595 | 
| 2596   // Extract the biased exponent in result. | 2596   // Extract the biased exponent in result. | 
| 2597   Ubfx(result, | 2597   Ubfx(result, | 
| 2598        input_high, | 2598        input_high, | 
| 2599        HeapNumber::kExponentShift, | 2599        HeapNumber::kExponentShift, | 
| 2600        HeapNumber::kExponentBits); | 2600        HeapNumber::kExponentBits); | 
| 2601 | 2601 | 
| 2602   // Check for Infinity and NaNs, which should return 0. | 2602   // Check for Infinity and NaNs, which should return 0. | 
| 2603   cmp(result, Operand(HeapNumber::kExponentMask)); | 2603   cmp(result, Operand(HeapNumber::kExponentMask)); | 
| 2604   mov(result, Operand(0), LeaveCC, eq); | 2604   mov(result, Operand::Zero(), LeaveCC, eq); | 
| 2605   b(eq, &done); | 2605   b(eq, &done); | 
| 2606 | 2606 | 
| 2607   // Express exponent as delta to (number of mantissa bits + 31). | 2607   // Express exponent as delta to (number of mantissa bits + 31). | 
| 2608   sub(result, | 2608   sub(result, | 
| 2609       result, | 2609       result, | 
| 2610       Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31), | 2610       Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits + 31), | 
| 2611       SetCC); | 2611       SetCC); | 
| 2612 | 2612 | 
| 2613   // If the delta is strictly positive, all bits would be shifted away, | 2613   // If the delta is strictly positive, all bits would be shifted away, | 
| 2614   // which means that we can return 0. | 2614   // which means that we can return 0. | 
| 2615   b(le, &normal_exponent); | 2615   b(le, &normal_exponent); | 
| 2616   mov(result, Operand(0)); | 2616   mov(result, Operand::Zero()); | 
| 2617   b(&done); | 2617   b(&done); | 
| 2618 | 2618 | 
| 2619   bind(&normal_exponent); | 2619   bind(&normal_exponent); | 
| 2620   const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1; | 2620   const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1; | 
| 2621   // Calculate shift. | 2621   // Calculate shift. | 
| 2622   add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits), SetCC); | 2622   add(scratch, result, Operand(kShiftBase + HeapNumber::kMantissaBits), SetCC); | 
| 2623 | 2623 | 
| 2624   // Save the sign. | 2624   // Save the sign. | 
| 2625   Register sign = result; | 2625   Register sign = result; | 
| 2626   result = no_reg; | 2626   result = no_reg; | 
| 2627   and_(sign, input_high, Operand(HeapNumber::kSignMask)); | 2627   and_(sign, input_high, Operand(HeapNumber::kSignMask)); | 
| 2628 | 2628 | 
| 2629   // Set the implicit 1 before the mantissa part in input_high. | 2629   // Set the implicit 1 before the mantissa part in input_high. | 
| 2630   orr(input_high, | 2630   orr(input_high, | 
| 2631       input_high, | 2631       input_high, | 
| 2632       Operand(1 << HeapNumber::kMantissaBitsInTopWord)); | 2632       Operand(1 << HeapNumber::kMantissaBitsInTopWord)); | 
| 2633   // Shift the mantissa bits to the correct position. | 2633   // Shift the mantissa bits to the correct position. | 
| 2634   // We don't need to clear non-mantissa bits as they will be shifted away. | 2634   // We don't need to clear non-mantissa bits as they will be shifted away. | 
| 2635   // If they weren't, it would mean that the answer is in the 32bit range. | 2635   // If they weren't, it would mean that the answer is in the 32bit range. | 
| 2636   mov(input_high, Operand(input_high, LSL, scratch)); | 2636   mov(input_high, Operand(input_high, LSL, scratch)); | 
| 2637 | 2637 | 
| 2638   // Replace the shifted bits with bits from the lower mantissa word. | 2638   // Replace the shifted bits with bits from the lower mantissa word. | 
| 2639   Label pos_shift, shift_done; | 2639   Label pos_shift, shift_done; | 
| 2640   rsb(scratch, scratch, Operand(32), SetCC); | 2640   rsb(scratch, scratch, Operand(32), SetCC); | 
| 2641   b(&pos_shift, ge); | 2641   b(&pos_shift, ge); | 
| 2642 | 2642 | 
| 2643   // Negate scratch. | 2643   // Negate scratch. | 
| 2644   rsb(scratch, scratch, Operand(0)); | 2644   rsb(scratch, scratch, Operand::Zero()); | 
| 2645   mov(input_low, Operand(input_low, LSL, scratch)); | 2645   mov(input_low, Operand(input_low, LSL, scratch)); | 
| 2646   b(&shift_done); | 2646   b(&shift_done); | 
| 2647 | 2647 | 
| 2648   bind(&pos_shift); | 2648   bind(&pos_shift); | 
| 2649   mov(input_low, Operand(input_low, LSR, scratch)); | 2649   mov(input_low, Operand(input_low, LSR, scratch)); | 
| 2650 | 2650 | 
| 2651   bind(&shift_done); | 2651   bind(&shift_done); | 
| 2652   orr(input_high, input_high, Operand(input_low)); | 2652   orr(input_high, input_high, Operand(input_low)); | 
| 2653   // Restore sign if necessary. | 2653   // Restore sign if necessary. | 
| 2654   cmp(sign, Operand(0)); | 2654   cmp(sign, Operand::Zero()); | 
| 2655   result = sign; | 2655   result = sign; | 
| 2656   sign = no_reg; | 2656   sign = no_reg; | 
| 2657   rsb(result, input_high, Operand(0), LeaveCC, ne); | 2657   rsb(result, input_high, Operand::Zero(), LeaveCC, ne); | 
| 2658   mov(result, input_high, LeaveCC, eq); | 2658   mov(result, input_high, LeaveCC, eq); | 
| 2659   bind(&done); | 2659   bind(&done); | 
| 2660 } | 2660 } | 
| 2661 | 2661 | 
| 2662 | 2662 | 
| 2663 void MacroAssembler::EmitECMATruncate(Register result, | 2663 void MacroAssembler::EmitECMATruncate(Register result, | 
| 2664                                       DwVfpRegister double_input, | 2664                                       DwVfpRegister double_input, | 
| 2665                                       DwVfpRegister double_scratch, | 2665                                       DwVfpRegister double_scratch, | 
| 2666                                       Register scratch, | 2666                                       Register scratch, | 
| 2667                                       Register input_high, | 2667                                       Register input_high, | 
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3288 | 3288 | 
| 3289 | 3289 | 
| 3290 void MacroAssembler::CopyBytes(Register src, | 3290 void MacroAssembler::CopyBytes(Register src, | 
| 3291                                Register dst, | 3291                                Register dst, | 
| 3292                                Register length, | 3292                                Register length, | 
| 3293                                Register scratch) { | 3293                                Register scratch) { | 
| 3294   Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done; | 3294   Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done; | 
| 3295 | 3295 | 
| 3296   // Align src before copying in word size chunks. | 3296   // Align src before copying in word size chunks. | 
| 3297   bind(&align_loop); | 3297   bind(&align_loop); | 
| 3298   cmp(length, Operand(0)); | 3298   cmp(length, Operand::Zero()); | 
| 3299   b(eq, &done); | 3299   b(eq, &done); | 
| 3300   bind(&align_loop_1); | 3300   bind(&align_loop_1); | 
| 3301   tst(src, Operand(kPointerSize - 1)); | 3301   tst(src, Operand(kPointerSize - 1)); | 
| 3302   b(eq, &word_loop); | 3302   b(eq, &word_loop); | 
| 3303   ldrb(scratch, MemOperand(src, 1, PostIndex)); | 3303   ldrb(scratch, MemOperand(src, 1, PostIndex)); | 
| 3304   strb(scratch, MemOperand(dst, 1, PostIndex)); | 3304   strb(scratch, MemOperand(dst, 1, PostIndex)); | 
| 3305   sub(length, length, Operand(1), SetCC); | 3305   sub(length, length, Operand(1), SetCC); | 
| 3306   b(ne, &byte_loop_1); | 3306   b(ne, &byte_loop_1); | 
| 3307 | 3307 | 
| 3308   // Copy bytes in word size chunks. | 3308   // Copy bytes in word size chunks. | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 3323     mov(scratch, Operand(scratch, LSR, 8)); | 3323     mov(scratch, Operand(scratch, LSR, 8)); | 
| 3324     strb(scratch, MemOperand(dst, 1, PostIndex)); | 3324     strb(scratch, MemOperand(dst, 1, PostIndex)); | 
| 3325     mov(scratch, Operand(scratch, LSR, 8)); | 3325     mov(scratch, Operand(scratch, LSR, 8)); | 
| 3326     strb(scratch, MemOperand(dst, 1, PostIndex)); | 3326     strb(scratch, MemOperand(dst, 1, PostIndex)); | 
| 3327   } | 3327   } | 
| 3328   sub(length, length, Operand(kPointerSize)); | 3328   sub(length, length, Operand(kPointerSize)); | 
| 3329   b(&word_loop); | 3329   b(&word_loop); | 
| 3330 | 3330 | 
| 3331   // Copy the last bytes if any left. | 3331   // Copy the last bytes if any left. | 
| 3332   bind(&byte_loop); | 3332   bind(&byte_loop); | 
| 3333   cmp(length, Operand(0)); | 3333   cmp(length, Operand::Zero()); | 
| 3334   b(eq, &done); | 3334   b(eq, &done); | 
| 3335   bind(&byte_loop_1); | 3335   bind(&byte_loop_1); | 
| 3336   ldrb(scratch, MemOperand(src, 1, PostIndex)); | 3336   ldrb(scratch, MemOperand(src, 1, PostIndex)); | 
| 3337   strb(scratch, MemOperand(dst, 1, PostIndex)); | 3337   strb(scratch, MemOperand(dst, 1, PostIndex)); | 
| 3338   sub(length, length, Operand(1), SetCC); | 3338   sub(length, length, Operand(1), SetCC); | 
| 3339   b(ne, &byte_loop_1); | 3339   b(ne, &byte_loop_1); | 
| 3340   bind(&done); | 3340   bind(&done); | 
| 3341 } | 3341 } | 
| 3342 | 3342 | 
| 3343 | 3343 | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 3361   ASSERT(!zeros.is(scratch)); | 3361   ASSERT(!zeros.is(scratch)); | 
| 3362   ASSERT(!scratch.is(ip)); | 3362   ASSERT(!scratch.is(ip)); | 
| 3363   ASSERT(!source.is(ip)); | 3363   ASSERT(!source.is(ip)); | 
| 3364   ASSERT(!zeros.is(ip)); | 3364   ASSERT(!zeros.is(ip)); | 
| 3365 #ifdef CAN_USE_ARMV5_INSTRUCTIONS | 3365 #ifdef CAN_USE_ARMV5_INSTRUCTIONS | 
| 3366   clz(zeros, source);  // This instruction is only supported after ARM5. | 3366   clz(zeros, source);  // This instruction is only supported after ARM5. | 
| 3367 #else | 3367 #else | 
| 3368   // Order of the next two lines is important: zeros register | 3368   // Order of the next two lines is important: zeros register | 
| 3369   // can be the same as source register. | 3369   // can be the same as source register. | 
| 3370   Move(scratch, source); | 3370   Move(scratch, source); | 
| 3371   mov(zeros, Operand(0, RelocInfo::NONE32)); | 3371   mov(zeros, Operand::Zero()); | 
| 3372   // Top 16. | 3372   // Top 16. | 
| 3373   tst(scratch, Operand(0xffff0000)); | 3373   tst(scratch, Operand(0xffff0000)); | 
| 3374   add(zeros, zeros, Operand(16), LeaveCC, eq); | 3374   add(zeros, zeros, Operand(16), LeaveCC, eq); | 
| 3375   mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq); | 3375   mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq); | 
| 3376   // Top 8. | 3376   // Top 8. | 
| 3377   tst(scratch, Operand(0xff000000)); | 3377   tst(scratch, Operand(0xff000000)); | 
| 3378   add(zeros, zeros, Operand(8), LeaveCC, eq); | 3378   add(zeros, zeros, Operand(8), LeaveCC, eq); | 
| 3379   mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq); | 3379   mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq); | 
| 3380   // Top 4. | 3380   // Top 4. | 
| 3381   tst(scratch, Operand(0xf0000000)); | 3381   tst(scratch, Operand(0xf0000000)); | 
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3793                                         DwVfpRegister temp_double_reg) { | 3793                                         DwVfpRegister temp_double_reg) { | 
| 3794   Label above_zero; | 3794   Label above_zero; | 
| 3795   Label done; | 3795   Label done; | 
| 3796   Label in_bounds; | 3796   Label in_bounds; | 
| 3797 | 3797 | 
| 3798   Vmov(temp_double_reg, 0.0); | 3798   Vmov(temp_double_reg, 0.0); | 
| 3799   VFPCompareAndSetFlags(input_reg, temp_double_reg); | 3799   VFPCompareAndSetFlags(input_reg, temp_double_reg); | 
| 3800   b(gt, &above_zero); | 3800   b(gt, &above_zero); | 
| 3801 | 3801 | 
| 3802   // Double value is less than zero, NaN or Inf, return 0. | 3802   // Double value is less than zero, NaN or Inf, return 0. | 
| 3803   mov(result_reg, Operand(0)); | 3803   mov(result_reg, Operand::Zero()); | 
| 3804   b(al, &done); | 3804   b(al, &done); | 
| 3805 | 3805 | 
| 3806   // Double value is >= 255, return 255. | 3806   // Double value is >= 255, return 255. | 
| 3807   bind(&above_zero); | 3807   bind(&above_zero); | 
| 3808   Vmov(temp_double_reg, 255.0, result_reg); | 3808   Vmov(temp_double_reg, 255.0, result_reg); | 
| 3809   VFPCompareAndSetFlags(input_reg, temp_double_reg); | 3809   VFPCompareAndSetFlags(input_reg, temp_double_reg); | 
| 3810   b(le, &in_bounds); | 3810   b(le, &in_bounds); | 
| 3811   mov(result_reg, Operand(255)); | 3811   mov(result_reg, Operand(255)); | 
| 3812   b(al, &done); | 3812   b(al, &done); | 
| 3813 | 3813 | 
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3942 void CodePatcher::EmitCondition(Condition cond) { | 3942 void CodePatcher::EmitCondition(Condition cond) { | 
| 3943   Instr instr = Assembler::instr_at(masm_.pc_); | 3943   Instr instr = Assembler::instr_at(masm_.pc_); | 
| 3944   instr = (instr & ~kCondMask) | cond; | 3944   instr = (instr & ~kCondMask) | cond; | 
| 3945   masm_.emit(instr); | 3945   masm_.emit(instr); | 
| 3946 } | 3946 } | 
| 3947 | 3947 | 
| 3948 | 3948 | 
| 3949 } }  // namespace v8::internal | 3949 } }  // namespace v8::internal | 
| 3950 | 3950 | 
| 3951 #endif  // V8_TARGET_ARCH_ARM | 3951 #endif  // V8_TARGET_ARCH_ARM | 
| OLD | NEW | 
|---|