| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 6 | 6 |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 | 8 |
| 9 #if V8_TARGET_ARCH_MIPS | 9 #if V8_TARGET_ARCH_MIPS64 |
| 10 | 10 |
| 11 #include "src/bootstrapper.h" | 11 #include "src/bootstrapper.h" |
| 12 #include "src/codegen.h" | 12 #include "src/codegen.h" |
| 13 #include "src/cpu-profiler.h" | 13 #include "src/cpu-profiler.h" |
| 14 #include "src/debug.h" | 14 #include "src/debug.h" |
| 15 #include "src/isolate-inl.h" | 15 #include "src/isolate-inl.h" |
| 16 #include "src/runtime.h" | 16 #include "src/runtime.h" |
| 17 | 17 |
| 18 namespace v8 { | 18 namespace v8 { |
| 19 namespace internal { | 19 namespace internal { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 34 Representation r) { | 34 Representation r) { |
| 35 ASSERT(!r.IsDouble()); | 35 ASSERT(!r.IsDouble()); |
| 36 if (r.IsInteger8()) { | 36 if (r.IsInteger8()) { |
| 37 lb(dst, src); | 37 lb(dst, src); |
| 38 } else if (r.IsUInteger8()) { | 38 } else if (r.IsUInteger8()) { |
| 39 lbu(dst, src); | 39 lbu(dst, src); |
| 40 } else if (r.IsInteger16()) { | 40 } else if (r.IsInteger16()) { |
| 41 lh(dst, src); | 41 lh(dst, src); |
| 42 } else if (r.IsUInteger16()) { | 42 } else if (r.IsUInteger16()) { |
| 43 lhu(dst, src); | 43 lhu(dst, src); |
| 44 } else if (r.IsInteger32()) { |
| 45 lw(dst, src); |
| 44 } else { | 46 } else { |
| 45 lw(dst, src); | 47 ld(dst, src); |
| 46 } | 48 } |
| 47 } | 49 } |
| 48 | 50 |
| 49 | 51 |
| 50 void MacroAssembler::Store(Register src, | 52 void MacroAssembler::Store(Register src, |
| 51 const MemOperand& dst, | 53 const MemOperand& dst, |
| 52 Representation r) { | 54 Representation r) { |
| 53 ASSERT(!r.IsDouble()); | 55 ASSERT(!r.IsDouble()); |
| 54 if (r.IsInteger8() || r.IsUInteger8()) { | 56 if (r.IsInteger8() || r.IsUInteger8()) { |
| 55 sb(src, dst); | 57 sb(src, dst); |
| 56 } else if (r.IsInteger16() || r.IsUInteger16()) { | 58 } else if (r.IsInteger16() || r.IsUInteger16()) { |
| 57 sh(src, dst); | 59 sh(src, dst); |
| 60 } else if (r.IsInteger32()) { |
| 61 sw(src, dst); |
| 58 } else { | 62 } else { |
| 59 if (r.IsHeapObject()) { | 63 if (r.IsHeapObject()) { |
| 60 AssertNotSmi(src); | 64 AssertNotSmi(src); |
| 61 } else if (r.IsSmi()) { | 65 } else if (r.IsSmi()) { |
| 62 AssertSmi(src); | 66 AssertSmi(src); |
| 63 } | 67 } |
| 64 sw(src, dst); | 68 sd(src, dst); |
| 65 } | 69 } |
| 66 } | 70 } |
| 67 | 71 |
| 68 | 72 |
| 69 void MacroAssembler::LoadRoot(Register destination, | 73 void MacroAssembler::LoadRoot(Register destination, |
| 70 Heap::RootListIndex index) { | 74 Heap::RootListIndex index) { |
| 71 lw(destination, MemOperand(s6, index << kPointerSizeLog2)); | 75 ld(destination, MemOperand(s6, index << kPointerSizeLog2)); |
| 72 } | 76 } |
| 73 | 77 |
| 74 | 78 |
| 75 void MacroAssembler::LoadRoot(Register destination, | 79 void MacroAssembler::LoadRoot(Register destination, |
| 76 Heap::RootListIndex index, | 80 Heap::RootListIndex index, |
| 77 Condition cond, | 81 Condition cond, |
| 78 Register src1, const Operand& src2) { | 82 Register src1, const Operand& src2) { |
| 79 Branch(2, NegateCondition(cond), src1, src2); | 83 Branch(2, NegateCondition(cond), src1, src2); |
| 80 lw(destination, MemOperand(s6, index << kPointerSizeLog2)); | 84 ld(destination, MemOperand(s6, index << kPointerSizeLog2)); |
| 81 } | 85 } |
| 82 | 86 |
| 83 | 87 |
| 84 void MacroAssembler::StoreRoot(Register source, | 88 void MacroAssembler::StoreRoot(Register source, |
| 85 Heap::RootListIndex index) { | 89 Heap::RootListIndex index) { |
| 86 sw(source, MemOperand(s6, index << kPointerSizeLog2)); | 90 sd(source, MemOperand(s6, index << kPointerSizeLog2)); |
| 87 } | 91 } |
| 88 | 92 |
| 89 | 93 |
| 90 void MacroAssembler::StoreRoot(Register source, | 94 void MacroAssembler::StoreRoot(Register source, |
| 91 Heap::RootListIndex index, | 95 Heap::RootListIndex index, |
| 92 Condition cond, | 96 Condition cond, |
| 93 Register src1, const Operand& src2) { | 97 Register src1, const Operand& src2) { |
| 94 Branch(2, NegateCondition(cond), src1, src2); | 98 Branch(2, NegateCondition(cond), src1, src2); |
| 95 sw(source, MemOperand(s6, index << kPointerSizeLog2)); | 99 sd(source, MemOperand(s6, index << kPointerSizeLog2)); |
| 96 } | 100 } |
| 97 | 101 |
| 98 | 102 |
| 99 // Push and pop all registers that can hold pointers. | 103 // Push and pop all registers that can hold pointers. |
| 100 void MacroAssembler::PushSafepointRegisters() { | 104 void MacroAssembler::PushSafepointRegisters() { |
| 101 // Safepoints expect a block of kNumSafepointRegisters values on the | 105 // Safepoints expect a block of kNumSafepointRegisters values on the |
| 102 // stack, so adjust the stack for unsaved registers. | 106 // stack, so adjust the stack for unsaved registers. |
| 103 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 107 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 104 ASSERT(num_unsaved >= 0); | 108 ASSERT(num_unsaved >= 0); |
| 105 if (num_unsaved > 0) { | 109 if (num_unsaved > 0) { |
| 106 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); | 110 Dsubu(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 107 } | 111 } |
| 108 MultiPush(kSafepointSavedRegisters); | 112 MultiPush(kSafepointSavedRegisters); |
| 109 } | 113 } |
| 110 | 114 |
| 111 | 115 |
| 112 void MacroAssembler::PopSafepointRegisters() { | 116 void MacroAssembler::PopSafepointRegisters() { |
| 113 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 117 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 114 MultiPop(kSafepointSavedRegisters); | 118 MultiPop(kSafepointSavedRegisters); |
| 115 if (num_unsaved > 0) { | 119 if (num_unsaved > 0) { |
| 116 Addu(sp, sp, Operand(num_unsaved * kPointerSize)); | 120 Daddu(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 117 } | 121 } |
| 118 } | 122 } |
| 119 | 123 |
| 120 | 124 |
| 121 void MacroAssembler::PushSafepointRegistersAndDoubles() { | 125 void MacroAssembler::PushSafepointRegistersAndDoubles() { |
| 122 PushSafepointRegisters(); | 126 PushSafepointRegisters(); |
| 123 Subu(sp, sp, Operand(FPURegister::NumAllocatableRegisters() * kDoubleSize)); | 127 Dsubu(sp, sp, Operand(FPURegister::NumAllocatableRegisters() * kDoubleSize)); |
| 124 for (int i = 0; i < FPURegister::NumAllocatableRegisters(); i+=2) { | 128 for (int i = 0; i < FPURegister::NumAllocatableRegisters(); i++) { |
| 125 FPURegister reg = FPURegister::FromAllocationIndex(i); | 129 FPURegister reg = FPURegister::FromAllocationIndex(i); |
| 126 sdc1(reg, MemOperand(sp, i * kDoubleSize)); | 130 sdc1(reg, MemOperand(sp, i * kDoubleSize)); |
| 127 } | 131 } |
| 128 } | 132 } |
| 129 | 133 |
| 130 | 134 |
| 131 void MacroAssembler::PopSafepointRegistersAndDoubles() { | 135 void MacroAssembler::PopSafepointRegistersAndDoubles() { |
| 132 for (int i = 0; i < FPURegister::NumAllocatableRegisters(); i+=2) { | 136 for (int i = 0; i < FPURegister::NumAllocatableRegisters(); i++) { |
| 133 FPURegister reg = FPURegister::FromAllocationIndex(i); | 137 FPURegister reg = FPURegister::FromAllocationIndex(i); |
| 134 ldc1(reg, MemOperand(sp, i * kDoubleSize)); | 138 ldc1(reg, MemOperand(sp, i * kDoubleSize)); |
| 135 } | 139 } |
| 136 Addu(sp, sp, Operand(FPURegister::NumAllocatableRegisters() * kDoubleSize)); | 140 Daddu(sp, sp, Operand(FPURegister::NumAllocatableRegisters() * kDoubleSize)); |
| 137 PopSafepointRegisters(); | 141 PopSafepointRegisters(); |
| 138 } | 142 } |
| 139 | 143 |
| 140 | 144 |
| 141 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src, | 145 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src, |
| 142 Register dst) { | 146 Register dst) { |
| 143 sw(src, SafepointRegistersAndDoublesSlot(dst)); | 147 sd(src, SafepointRegistersAndDoublesSlot(dst)); |
| 144 } | 148 } |
| 145 | 149 |
| 146 | 150 |
| 147 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { | 151 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { |
| 148 sw(src, SafepointRegisterSlot(dst)); | 152 sd(src, SafepointRegisterSlot(dst)); |
| 149 } | 153 } |
| 150 | 154 |
| 151 | 155 |
| 152 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { | 156 void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) { |
| 153 lw(dst, SafepointRegisterSlot(src)); | 157 ld(dst, SafepointRegisterSlot(src)); |
| 154 } | 158 } |
| 155 | 159 |
| 156 | 160 |
| 157 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { | 161 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { |
| 158 // The registers are pushed starting with the highest encoding, | 162 // The registers are pushed starting with the highest encoding, |
| 159 // which means that lowest encodings are closest to the stack pointer. | 163 // which means that lowest encodings are closest to the stack pointer. |
| 160 return kSafepointRegisterStackIndexMap[reg_code]; | 164 return kSafepointRegisterStackIndexMap[reg_code]; |
| 161 } | 165 } |
| 162 | 166 |
| 163 | 167 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 | 207 |
| 204 // Skip barrier if writing a smi. | 208 // Skip barrier if writing a smi. |
| 205 if (smi_check == INLINE_SMI_CHECK) { | 209 if (smi_check == INLINE_SMI_CHECK) { |
| 206 JumpIfSmi(value, &done); | 210 JumpIfSmi(value, &done); |
| 207 } | 211 } |
| 208 | 212 |
| 209 // Although the object register is tagged, the offset is relative to the start | 213 // Although the object register is tagged, the offset is relative to the start |
| 210 // of the object, so so offset must be a multiple of kPointerSize. | 214 // of the object, so so offset must be a multiple of kPointerSize. |
| 211 ASSERT(IsAligned(offset, kPointerSize)); | 215 ASSERT(IsAligned(offset, kPointerSize)); |
| 212 | 216 |
| 213 Addu(dst, object, Operand(offset - kHeapObjectTag)); | 217 Daddu(dst, object, Operand(offset - kHeapObjectTag)); |
| 214 if (emit_debug_code()) { | 218 if (emit_debug_code()) { |
| 215 Label ok; | 219 Label ok; |
| 216 And(t8, dst, Operand((1 << kPointerSizeLog2) - 1)); | 220 And(t8, dst, Operand((1 << kPointerSizeLog2) - 1)); |
| 217 Branch(&ok, eq, t8, Operand(zero_reg)); | 221 Branch(&ok, eq, t8, Operand(zero_reg)); |
| 218 stop("Unaligned cell in write barrier"); | 222 stop("Unaligned cell in write barrier"); |
| 219 bind(&ok); | 223 bind(&ok); |
| 220 } | 224 } |
| 221 | 225 |
| 222 RecordWrite(object, | 226 RecordWrite(object, |
| 223 dst, | 227 dst, |
| 224 value, | 228 value, |
| 225 ra_status, | 229 ra_status, |
| 226 save_fp, | 230 save_fp, |
| 227 remembered_set_action, | 231 remembered_set_action, |
| 228 OMIT_SMI_CHECK, | 232 OMIT_SMI_CHECK, |
| 229 pointers_to_here_check_for_value); | 233 pointers_to_here_check_for_value); |
| 230 | 234 |
| 231 bind(&done); | 235 bind(&done); |
| 232 | 236 |
| 233 // Clobber clobbered input registers when running with the debug-code flag | 237 // Clobber clobbered input registers when running with the debug-code flag |
| 234 // turned on to provoke errors. | 238 // turned on to provoke errors. |
| 235 if (emit_debug_code()) { | 239 if (emit_debug_code()) { |
| 236 li(value, Operand(BitCast<int32_t>(kZapValue + 4))); | 240 li(value, Operand(BitCast<int64_t>(kZapValue + 4))); |
| 237 li(dst, Operand(BitCast<int32_t>(kZapValue + 8))); | 241 li(dst, Operand(BitCast<int64_t>(kZapValue + 8))); |
| 238 } | 242 } |
| 239 } | 243 } |
| 240 | 244 |
| 241 | 245 |
| 242 // Will clobber 4 registers: object, map, dst, ip. The | 246 // Will clobber 4 registers: object, map, dst, ip. The |
| 243 // register 'object' contains a heap object pointer. | 247 // register 'object' contains a heap object pointer. |
| 244 void MacroAssembler::RecordWriteForMap(Register object, | 248 void MacroAssembler::RecordWriteForMap(Register object, |
| 245 Register map, | 249 Register map, |
| 246 Register dst, | 250 Register dst, |
| 247 RAStatus ra_status, | 251 RAStatus ra_status, |
| 248 SaveFPRegsMode fp_mode) { | 252 SaveFPRegsMode fp_mode) { |
| 249 if (emit_debug_code()) { | 253 if (emit_debug_code()) { |
| 250 ASSERT(!dst.is(at)); | 254 ASSERT(!dst.is(at)); |
| 251 lw(dst, FieldMemOperand(map, HeapObject::kMapOffset)); | 255 ld(dst, FieldMemOperand(map, HeapObject::kMapOffset)); |
| 252 Check(eq, | 256 Check(eq, |
| 253 kWrongAddressOrValuePassedToRecordWrite, | 257 kWrongAddressOrValuePassedToRecordWrite, |
| 254 dst, | 258 dst, |
| 255 Operand(isolate()->factory()->meta_map())); | 259 Operand(isolate()->factory()->meta_map())); |
| 256 } | 260 } |
| 257 | 261 |
| 258 if (!FLAG_incremental_marking) { | 262 if (!FLAG_incremental_marking) { |
| 259 return; | 263 return; |
| 260 } | 264 } |
| 261 | 265 |
| 262 // Count number of write barriers in generated code. | 266 // Count number of write barriers in generated code. |
| 263 isolate()->counters()->write_barriers_static()->Increment(); | 267 isolate()->counters()->write_barriers_static()->Increment(); |
| 264 // TODO(mstarzinger): Dynamic counter missing. | 268 // TODO(mstarzinger): Dynamic counter missing. |
| 265 | 269 |
| 266 if (emit_debug_code()) { | 270 if (emit_debug_code()) { |
| 267 lw(at, FieldMemOperand(object, HeapObject::kMapOffset)); | 271 ld(at, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 268 Check(eq, | 272 Check(eq, |
| 269 kWrongAddressOrValuePassedToRecordWrite, | 273 kWrongAddressOrValuePassedToRecordWrite, |
| 270 map, | 274 map, |
| 271 Operand(at)); | 275 Operand(at)); |
| 272 } | 276 } |
| 273 | 277 |
| 274 Label done; | 278 Label done; |
| 275 | 279 |
| 276 // A single check of the map's pages interesting flag suffices, since it is | 280 // A single check of the map's pages interesting flag suffices, since it is |
| 277 // only set during incremental collection, and then it's also guaranteed that | 281 // only set during incremental collection, and then it's also guaranteed that |
| 278 // the from object's page's interesting flag is also set. This optimization | 282 // the from object's page's interesting flag is also set. This optimization |
| 279 // relies on the fact that maps can never be in new space. | 283 // relies on the fact that maps can never be in new space. |
| 280 CheckPageFlag(map, | 284 CheckPageFlag(map, |
| 281 map, // Used as scratch. | 285 map, // Used as scratch. |
| 282 MemoryChunk::kPointersToHereAreInterestingMask, | 286 MemoryChunk::kPointersToHereAreInterestingMask, |
| 283 eq, | 287 eq, |
| 284 &done); | 288 &done); |
| 285 | 289 |
| 286 Addu(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag)); | 290 Daddu(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag)); |
| 287 if (emit_debug_code()) { | 291 if (emit_debug_code()) { |
| 288 Label ok; | 292 Label ok; |
| 289 And(at, dst, Operand((1 << kPointerSizeLog2) - 1)); | 293 And(at, dst, Operand((1 << kPointerSizeLog2) - 1)); |
| 290 Branch(&ok, eq, at, Operand(zero_reg)); | 294 Branch(&ok, eq, at, Operand(zero_reg)); |
| 291 stop("Unaligned cell in write barrier"); | 295 stop("Unaligned cell in write barrier"); |
| 292 bind(&ok); | 296 bind(&ok); |
| 293 } | 297 } |
| 294 | 298 |
| 295 // Record the actual write. | 299 // Record the actual write. |
| 296 if (ra_status == kRAHasNotBeenSaved) { | 300 if (ra_status == kRAHasNotBeenSaved) { |
| 297 push(ra); | 301 push(ra); |
| 298 } | 302 } |
| 299 RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET, | 303 RecordWriteStub stub(isolate(), object, map, dst, OMIT_REMEMBERED_SET, |
| 300 fp_mode); | 304 fp_mode); |
| 301 CallStub(&stub); | 305 CallStub(&stub); |
| 302 if (ra_status == kRAHasNotBeenSaved) { | 306 if (ra_status == kRAHasNotBeenSaved) { |
| 303 pop(ra); | 307 pop(ra); |
| 304 } | 308 } |
| 305 | 309 |
| 306 bind(&done); | 310 bind(&done); |
| 307 | 311 |
| 308 // Clobber clobbered registers when running with the debug-code flag | 312 // Clobber clobbered registers when running with the debug-code flag |
| 309 // turned on to provoke errors. | 313 // turned on to provoke errors. |
| 310 if (emit_debug_code()) { | 314 if (emit_debug_code()) { |
| 311 li(dst, Operand(BitCast<int32_t>(kZapValue + 12))); | 315 li(dst, Operand(BitCast<int64_t>(kZapValue + 12))); |
| 312 li(map, Operand(BitCast<int32_t>(kZapValue + 16))); | 316 li(map, Operand(BitCast<int64_t>(kZapValue + 16))); |
| 313 } | 317 } |
| 314 } | 318 } |
| 315 | 319 |
| 316 | 320 |
| 317 // Will clobber 4 registers: object, address, scratch, ip. The | 321 // Will clobber 4 registers: object, address, scratch, ip. The |
| 318 // register 'object' contains a heap object pointer. The heap object | 322 // register 'object' contains a heap object pointer. The heap object |
| 319 // tag is shifted away. | 323 // tag is shifted away. |
| 320 void MacroAssembler::RecordWrite( | 324 void MacroAssembler::RecordWrite( |
| 321 Register object, | 325 Register object, |
| 322 Register address, | 326 Register address, |
| 323 Register value, | 327 Register value, |
| 324 RAStatus ra_status, | 328 RAStatus ra_status, |
| 325 SaveFPRegsMode fp_mode, | 329 SaveFPRegsMode fp_mode, |
| 326 RememberedSetAction remembered_set_action, | 330 RememberedSetAction remembered_set_action, |
| 327 SmiCheck smi_check, | 331 SmiCheck smi_check, |
| 328 PointersToHereCheck pointers_to_here_check_for_value) { | 332 PointersToHereCheck pointers_to_here_check_for_value) { |
| 329 ASSERT(!AreAliased(object, address, value, t8)); | 333 ASSERT(!AreAliased(object, address, value, t8)); |
| 330 ASSERT(!AreAliased(object, address, value, t9)); | 334 ASSERT(!AreAliased(object, address, value, t9)); |
| 331 | 335 |
| 332 if (emit_debug_code()) { | 336 if (emit_debug_code()) { |
| 333 lw(at, MemOperand(address)); | 337 ld(at, MemOperand(address)); |
| 334 Assert( | 338 Assert( |
| 335 eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value)); | 339 eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value)); |
| 336 } | 340 } |
| 337 | 341 |
| 338 if (remembered_set_action == OMIT_REMEMBERED_SET && | 342 if (remembered_set_action == OMIT_REMEMBERED_SET && |
| 339 !FLAG_incremental_marking) { | 343 !FLAG_incremental_marking) { |
| 340 return; | 344 return; |
| 341 } | 345 } |
| 342 | 346 |
| 343 // Count number of write barriers in generated code. | 347 // Count number of write barriers in generated code. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 CallStub(&stub); | 379 CallStub(&stub); |
| 376 if (ra_status == kRAHasNotBeenSaved) { | 380 if (ra_status == kRAHasNotBeenSaved) { |
| 377 pop(ra); | 381 pop(ra); |
| 378 } | 382 } |
| 379 | 383 |
| 380 bind(&done); | 384 bind(&done); |
| 381 | 385 |
| 382 // Clobber clobbered registers when running with the debug-code flag | 386 // Clobber clobbered registers when running with the debug-code flag |
| 383 // turned on to provoke errors. | 387 // turned on to provoke errors. |
| 384 if (emit_debug_code()) { | 388 if (emit_debug_code()) { |
| 385 li(address, Operand(BitCast<int32_t>(kZapValue + 12))); | 389 li(address, Operand(BitCast<int64_t>(kZapValue + 12))); |
| 386 li(value, Operand(BitCast<int32_t>(kZapValue + 16))); | 390 li(value, Operand(BitCast<int64_t>(kZapValue + 16))); |
| 387 } | 391 } |
| 388 } | 392 } |
| 389 | 393 |
| 390 | 394 |
| 391 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. | 395 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. |
| 392 Register address, | 396 Register address, |
| 393 Register scratch, | 397 Register scratch, |
| 394 SaveFPRegsMode fp_mode, | 398 SaveFPRegsMode fp_mode, |
| 395 RememberedSetFinalAction and_then) { | 399 RememberedSetFinalAction and_then) { |
| 396 Label done; | 400 Label done; |
| 397 if (emit_debug_code()) { | 401 if (emit_debug_code()) { |
| 398 Label ok; | 402 Label ok; |
| 399 JumpIfNotInNewSpace(object, scratch, &ok); | 403 JumpIfNotInNewSpace(object, scratch, &ok); |
| 400 stop("Remembered set pointer is in new space"); | 404 stop("Remembered set pointer is in new space"); |
| 401 bind(&ok); | 405 bind(&ok); |
| 402 } | 406 } |
| 403 // Load store buffer top. | 407 // Load store buffer top. |
| 404 ExternalReference store_buffer = | 408 ExternalReference store_buffer = |
| 405 ExternalReference::store_buffer_top(isolate()); | 409 ExternalReference::store_buffer_top(isolate()); |
| 406 li(t8, Operand(store_buffer)); | 410 li(t8, Operand(store_buffer)); |
| 407 lw(scratch, MemOperand(t8)); | 411 ld(scratch, MemOperand(t8)); |
| 408 // Store pointer to buffer and increment buffer top. | 412 // Store pointer to buffer and increment buffer top. |
| 409 sw(address, MemOperand(scratch)); | 413 sd(address, MemOperand(scratch)); |
| 410 Addu(scratch, scratch, kPointerSize); | 414 Daddu(scratch, scratch, kPointerSize); |
| 411 // Write back new top of buffer. | 415 // Write back new top of buffer. |
| 412 sw(scratch, MemOperand(t8)); | 416 sd(scratch, MemOperand(t8)); |
| 413 // Call stub on end of buffer. | 417 // Call stub on end of buffer. |
| 414 // Check for end of buffer. | 418 // Check for end of buffer. |
| 415 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); | 419 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); |
| 420 ASSERT(!scratch.is(t8)); |
| 416 if (and_then == kFallThroughAtEnd) { | 421 if (and_then == kFallThroughAtEnd) { |
| 417 Branch(&done, eq, t8, Operand(zero_reg)); | 422 Branch(&done, eq, t8, Operand(zero_reg)); |
| 418 } else { | 423 } else { |
| 419 ASSERT(and_then == kReturnAtEnd); | 424 ASSERT(and_then == kReturnAtEnd); |
| 420 Ret(eq, t8, Operand(zero_reg)); | 425 Ret(eq, t8, Operand(zero_reg)); |
| 421 } | 426 } |
| 422 push(ra); | 427 push(ra); |
| 423 StoreBufferOverflowStub store_buffer_overflow = | 428 StoreBufferOverflowStub store_buffer_overflow = |
| 424 StoreBufferOverflowStub(isolate(), fp_mode); | 429 StoreBufferOverflowStub(isolate(), fp_mode); |
| 425 CallStub(&store_buffer_overflow); | 430 CallStub(&store_buffer_overflow); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 438 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 443 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 439 Register scratch, | 444 Register scratch, |
| 440 Label* miss) { | 445 Label* miss) { |
| 441 Label same_contexts; | 446 Label same_contexts; |
| 442 | 447 |
| 443 ASSERT(!holder_reg.is(scratch)); | 448 ASSERT(!holder_reg.is(scratch)); |
| 444 ASSERT(!holder_reg.is(at)); | 449 ASSERT(!holder_reg.is(at)); |
| 445 ASSERT(!scratch.is(at)); | 450 ASSERT(!scratch.is(at)); |
| 446 | 451 |
| 447 // Load current lexical context from the stack frame. | 452 // Load current lexical context from the stack frame. |
| 448 lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 453 ld(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 449 // In debug mode, make sure the lexical context is set. | 454 // In debug mode, make sure the lexical context is set. |
| 450 #ifdef DEBUG | 455 #ifdef DEBUG |
| 451 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, | 456 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, |
| 452 scratch, Operand(zero_reg)); | 457 scratch, Operand(zero_reg)); |
| 453 #endif | 458 #endif |
| 454 | 459 |
| 455 // Load the native context of the current context. | 460 // Load the native context of the current context. |
| 456 int offset = | 461 int offset = |
| 457 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; | 462 Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; |
| 458 lw(scratch, FieldMemOperand(scratch, offset)); | 463 ld(scratch, FieldMemOperand(scratch, offset)); |
| 459 lw(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 464 ld(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 460 | 465 |
| 461 // Check the context is a native context. | 466 // Check the context is a native context. |
| 462 if (emit_debug_code()) { | 467 if (emit_debug_code()) { |
| 463 push(holder_reg); // Temporarily save holder on the stack. | 468 push(holder_reg); // Temporarily save holder on the stack. |
| 464 // Read the first word and compare to the native_context_map. | 469 // Read the first word and compare to the native_context_map. |
| 465 lw(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset)); | 470 ld(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset)); |
| 466 LoadRoot(at, Heap::kNativeContextMapRootIndex); | 471 LoadRoot(at, Heap::kNativeContextMapRootIndex); |
| 467 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext, | 472 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext, |
| 468 holder_reg, Operand(at)); | 473 holder_reg, Operand(at)); |
| 469 pop(holder_reg); // Restore holder. | 474 pop(holder_reg); // Restore holder. |
| 470 } | 475 } |
| 471 | 476 |
| 472 // Check if both contexts are the same. | 477 // Check if both contexts are the same. |
| 473 lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); | 478 ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); |
| 474 Branch(&same_contexts, eq, scratch, Operand(at)); | 479 Branch(&same_contexts, eq, scratch, Operand(at)); |
| 475 | 480 |
| 476 // Check the context is a native context. | 481 // Check the context is a native context. |
| 477 if (emit_debug_code()) { | 482 if (emit_debug_code()) { |
| 478 push(holder_reg); // Temporarily save holder on the stack. | 483 push(holder_reg); // Temporarily save holder on the stack. |
| 479 mov(holder_reg, at); // Move at to its holding place. | 484 mov(holder_reg, at); // Move at to its holding place. |
| 480 LoadRoot(at, Heap::kNullValueRootIndex); | 485 LoadRoot(at, Heap::kNullValueRootIndex); |
| 481 Check(ne, kJSGlobalProxyContextShouldNotBeNull, | 486 Check(ne, kJSGlobalProxyContextShouldNotBeNull, |
| 482 holder_reg, Operand(at)); | 487 holder_reg, Operand(at)); |
| 483 | 488 |
| 484 lw(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset)); | 489 ld(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset)); |
| 485 LoadRoot(at, Heap::kNativeContextMapRootIndex); | 490 LoadRoot(at, Heap::kNativeContextMapRootIndex); |
| 486 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext, | 491 Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext, |
| 487 holder_reg, Operand(at)); | 492 holder_reg, Operand(at)); |
| 488 // Restore at is not needed. at is reloaded below. | 493 // Restore at is not needed. at is reloaded below. |
| 489 pop(holder_reg); // Restore holder. | 494 pop(holder_reg); // Restore holder. |
| 490 // Restore at to holder's context. | 495 // Restore at to holder's context. |
| 491 lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); | 496 ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset)); |
| 492 } | 497 } |
| 493 | 498 |
| 494 // Check that the security token in the calling global object is | 499 // Check that the security token in the calling global object is |
| 495 // compatible with the security token in the receiving global | 500 // compatible with the security token in the receiving global |
| 496 // object. | 501 // object. |
| 497 int token_offset = Context::kHeaderSize + | 502 int token_offset = Context::kHeaderSize + |
| 498 Context::SECURITY_TOKEN_INDEX * kPointerSize; | 503 Context::SECURITY_TOKEN_INDEX * kPointerSize; |
| 499 | 504 |
| 500 lw(scratch, FieldMemOperand(scratch, token_offset)); | 505 ld(scratch, FieldMemOperand(scratch, token_offset)); |
| 501 lw(at, FieldMemOperand(at, token_offset)); | 506 ld(at, FieldMemOperand(at, token_offset)); |
| 502 Branch(miss, ne, scratch, Operand(at)); | 507 Branch(miss, ne, scratch, Operand(at)); |
| 503 | 508 |
| 504 bind(&same_contexts); | 509 bind(&same_contexts); |
| 505 } | 510 } |
| 506 | 511 |
| 507 | 512 |
| 508 void MacroAssembler::GetNumberHash(Register reg0, Register scratch) { | 513 void MacroAssembler::GetNumberHash(Register reg0, Register scratch) { |
| 509 // First of all we assign the hash seed to scratch. | 514 // First of all we assign the hash seed to scratch. |
| 510 LoadRoot(scratch, Heap::kHashSeedRootIndex); | 515 LoadRoot(scratch, Heap::kHashSeedRootIndex); |
| 511 SmiUntag(scratch); | 516 SmiUntag(scratch); |
| 512 | 517 |
| 513 // Xor original key with a seed. | 518 // Xor original key with a seed. |
| 514 xor_(reg0, reg0, scratch); | 519 xor_(reg0, reg0, scratch); |
| 515 | 520 |
| 516 // Compute the hash code from the untagged key. This must be kept in sync | 521 // Compute the hash code from the untagged key. This must be kept in sync |
| 517 // with ComputeIntegerHash in utils.h. | 522 // with ComputeIntegerHash in utils.h. |
| 518 // | 523 // |
| 519 // hash = ~hash + (hash << 15); | 524 // hash = ~hash + (hash << 15); |
| 525 // The algorithm uses 32-bit integer values. |
| 520 nor(scratch, reg0, zero_reg); | 526 nor(scratch, reg0, zero_reg); |
| 521 sll(at, reg0, 15); | 527 sll(at, reg0, 15); |
| 522 addu(reg0, scratch, at); | 528 addu(reg0, scratch, at); |
| 523 | 529 |
| 524 // hash = hash ^ (hash >> 12); | 530 // hash = hash ^ (hash >> 12); |
| 525 srl(at, reg0, 12); | 531 srl(at, reg0, 12); |
| 526 xor_(reg0, reg0, at); | 532 xor_(reg0, reg0, at); |
| 527 | 533 |
| 528 // hash = hash + (hash << 2); | 534 // hash = hash + (hash << 2); |
| 529 sll(at, reg0, 2); | 535 sll(at, reg0, 2); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 // | 578 // |
| 573 // reg1 - Used to hold the capacity mask of the dictionary. | 579 // reg1 - Used to hold the capacity mask of the dictionary. |
| 574 // | 580 // |
| 575 // reg2 - Used for the index into the dictionary. | 581 // reg2 - Used for the index into the dictionary. |
| 576 // at - Temporary (avoid MacroAssembler instructions also using 'at'). | 582 // at - Temporary (avoid MacroAssembler instructions also using 'at'). |
| 577 Label done; | 583 Label done; |
| 578 | 584 |
| 579 GetNumberHash(reg0, reg1); | 585 GetNumberHash(reg0, reg1); |
| 580 | 586 |
| 581 // Compute the capacity mask. | 587 // Compute the capacity mask. |
| 582 lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); | 588 ld(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); |
| 583 sra(reg1, reg1, kSmiTagSize); | 589 SmiUntag(reg1, reg1); |
| 584 Subu(reg1, reg1, Operand(1)); | 590 Dsubu(reg1, reg1, Operand(1)); |
| 585 | 591 |
| 586 // Generate an unrolled loop that performs a few probes before giving up. | 592 // Generate an unrolled loop that performs a few probes before giving up. |
| 587 for (int i = 0; i < kNumberDictionaryProbes; i++) { | 593 for (int i = 0; i < kNumberDictionaryProbes; i++) { |
| 588 // Use reg2 for index calculations and keep the hash intact in reg0. | 594 // Use reg2 for index calculations and keep the hash intact in reg0. |
| 589 mov(reg2, reg0); | 595 mov(reg2, reg0); |
| 590 // Compute the masked index: (hash + i + i * i) & mask. | 596 // Compute the masked index: (hash + i + i * i) & mask. |
| 591 if (i > 0) { | 597 if (i > 0) { |
| 592 Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); | 598 Daddu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); |
| 593 } | 599 } |
| 594 and_(reg2, reg2, reg1); | 600 and_(reg2, reg2, reg1); |
| 595 | 601 |
| 596 // Scale the index by multiplying by the element size. | 602 // Scale the index by multiplying by the element size. |
| 597 ASSERT(SeededNumberDictionary::kEntrySize == 3); | 603 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
| 598 sll(at, reg2, 1); // 2x. | 604 dsll(at, reg2, 1); // 2x. |
| 599 addu(reg2, reg2, at); // reg2 = reg2 * 3. | 605 daddu(reg2, reg2, at); // reg2 = reg2 * 3. |
| 600 | 606 |
| 601 // Check if the key is identical to the name. | 607 // Check if the key is identical to the name. |
| 602 sll(at, reg2, kPointerSizeLog2); | 608 dsll(at, reg2, kPointerSizeLog2); |
| 603 addu(reg2, elements, at); | 609 daddu(reg2, elements, at); |
| 604 | 610 |
| 605 lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); | 611 ld(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); |
| 606 if (i != kNumberDictionaryProbes - 1) { | 612 if (i != kNumberDictionaryProbes - 1) { |
| 607 Branch(&done, eq, key, Operand(at)); | 613 Branch(&done, eq, key, Operand(at)); |
| 608 } else { | 614 } else { |
| 609 Branch(miss, ne, key, Operand(at)); | 615 Branch(miss, ne, key, Operand(at)); |
| 610 } | 616 } |
| 611 } | 617 } |
| 612 | 618 |
| 613 bind(&done); | 619 bind(&done); |
| 614 // Check that the value is a normal property. | 620 // Check that the value is a normal property. |
| 615 // reg2: elements + (index * kPointerSize). | 621 // reg2: elements + (index * kPointerSize). |
| 616 const int kDetailsOffset = | 622 const int kDetailsOffset = |
| 617 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 623 SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
| 618 lw(reg1, FieldMemOperand(reg2, kDetailsOffset)); | 624 ld(reg1, FieldMemOperand(reg2, kDetailsOffset)); |
| 619 And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); | 625 And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); |
| 620 Branch(miss, ne, at, Operand(zero_reg)); | 626 Branch(miss, ne, at, Operand(zero_reg)); |
| 621 | 627 |
| 622 // Get the value at the masked, scaled index and return. | 628 // Get the value at the masked, scaled index and return. |
| 623 const int kValueOffset = | 629 const int kValueOffset = |
| 624 SeededNumberDictionary::kElementsStartOffset + kPointerSize; | 630 SeededNumberDictionary::kElementsStartOffset + kPointerSize; |
| 625 lw(result, FieldMemOperand(reg2, kValueOffset)); | 631 ld(result, FieldMemOperand(reg2, kValueOffset)); |
| 626 } | 632 } |
| 627 | 633 |
| 628 | 634 |
| 629 // --------------------------------------------------------------------------- | 635 // --------------------------------------------------------------------------- |
| 630 // Instruction macros. | 636 // Instruction macros. |
| 631 | 637 |
| 632 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { | 638 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { |
| 633 if (rt.is_reg()) { | 639 if (rt.is_reg()) { |
| 634 addu(rd, rs, rt.rm()); | 640 addu(rd, rs, rt.rm()); |
| 635 } else { | 641 } else { |
| 636 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 642 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 637 addiu(rd, rs, rt.imm32_); | 643 addiu(rd, rs, rt.imm64_); |
| 638 } else { | 644 } else { |
| 639 // li handles the relocation. | 645 // li handles the relocation. |
| 640 ASSERT(!rs.is(at)); | 646 ASSERT(!rs.is(at)); |
| 641 li(at, rt); | 647 li(at, rt); |
| 642 addu(rd, rs, at); | 648 addu(rd, rs, at); |
| 643 } | 649 } |
| 644 } | 650 } |
| 645 } | 651 } |
| 646 | 652 |
| 647 | 653 |
| 654 void MacroAssembler::Daddu(Register rd, Register rs, const Operand& rt) { |
| 655 if (rt.is_reg()) { |
| 656 daddu(rd, rs, rt.rm()); |
| 657 } else { |
| 658 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 659 daddiu(rd, rs, rt.imm64_); |
| 660 } else { |
| 661 // li handles the relocation. |
| 662 ASSERT(!rs.is(at)); |
| 663 li(at, rt); |
| 664 daddu(rd, rs, at); |
| 665 } |
| 666 } |
| 667 } |
| 668 |
| 669 |
| 648 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) { | 670 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) { |
| 649 if (rt.is_reg()) { | 671 if (rt.is_reg()) { |
| 650 subu(rd, rs, rt.rm()); | 672 subu(rd, rs, rt.rm()); |
| 651 } else { | 673 } else { |
| 652 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 674 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 653 addiu(rd, rs, -rt.imm32_); // No subiu instr, use addiu(x, y, -imm). | 675 addiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm). |
| 654 } else { | 676 } else { |
| 655 // li handles the relocation. | 677 // li handles the relocation. |
| 656 ASSERT(!rs.is(at)); | 678 ASSERT(!rs.is(at)); |
| 657 li(at, rt); | 679 li(at, rt); |
| 658 subu(rd, rs, at); | 680 subu(rd, rs, at); |
| 659 } | 681 } |
| 660 } | 682 } |
| 661 } | 683 } |
| 662 | 684 |
| 663 | 685 |
| 686 void MacroAssembler::Dsubu(Register rd, Register rs, const Operand& rt) { |
| 687 if (rt.is_reg()) { |
| 688 dsubu(rd, rs, rt.rm()); |
| 689 } else { |
| 690 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 691 daddiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm). |
| 692 } else { |
| 693 // li handles the relocation. |
| 694 ASSERT(!rs.is(at)); |
| 695 li(at, rt); |
| 696 dsubu(rd, rs, at); |
| 697 } |
| 698 } |
| 699 } |
| 700 |
| 701 |
| 664 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) { | 702 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) { |
| 665 if (rt.is_reg()) { | 703 if (rt.is_reg()) { |
| 666 if (kArchVariant == kLoongson) { | 704 if (kArchVariant == kLoongson) { |
| 667 mult(rs, rt.rm()); | 705 mult(rs, rt.rm()); |
| 668 mflo(rd); | 706 mflo(rd); |
| 669 } else { | 707 } else { |
| 670 mul(rd, rs, rt.rm()); | 708 mul(rd, rs, rt.rm()); |
| 671 } | 709 } |
| 672 } else { | 710 } else { |
| 673 // li handles the relocation. | 711 // li handles the relocation. |
| 674 ASSERT(!rs.is(at)); | 712 ASSERT(!rs.is(at)); |
| 675 li(at, rt); | 713 li(at, rt); |
| 676 if (kArchVariant == kLoongson) { | 714 if (kArchVariant == kLoongson) { |
| 677 mult(rs, at); | 715 mult(rs, at); |
| 678 mflo(rd); | 716 mflo(rd); |
| 679 } else { | 717 } else { |
| 680 mul(rd, rs, at); | 718 mul(rd, rs, at); |
| 681 } | 719 } |
| 682 } | 720 } |
| 683 } | 721 } |
| 684 | 722 |
| 685 | 723 |
| 724 void MacroAssembler::Dmul(Register rd, Register rs, const Operand& rt) { |
| 725 if (rt.is_reg()) { |
| 726 if (kArchVariant == kLoongson) { |
| 727 dmult(rs, rt.rm()); |
| 728 mflo(rd); |
| 729 } else { |
| 730 // TODO(yuyin): |
| 731 // dmul(rd, rs, rt.rm()); |
| 732 dmult(rs, rt.rm()); |
| 733 mflo(rd); |
| 734 } |
| 735 } else { |
| 736 // li handles the relocation. |
| 737 ASSERT(!rs.is(at)); |
| 738 li(at, rt); |
| 739 if (kArchVariant == kLoongson) { |
| 740 dmult(rs, at); |
| 741 mflo(rd); |
| 742 } else { |
| 743 // TODO(yuyin): |
| 744 // dmul(rd, rs, at); |
| 745 dmult(rs, at); |
| 746 mflo(rd); |
| 747 } |
| 748 } |
| 749 } |
| 750 |
| 751 |
| 686 void MacroAssembler::Mult(Register rs, const Operand& rt) { | 752 void MacroAssembler::Mult(Register rs, const Operand& rt) { |
| 687 if (rt.is_reg()) { | 753 if (rt.is_reg()) { |
| 688 mult(rs, rt.rm()); | 754 mult(rs, rt.rm()); |
| 689 } else { | 755 } else { |
| 690 // li handles the relocation. | 756 // li handles the relocation. |
| 691 ASSERT(!rs.is(at)); | 757 ASSERT(!rs.is(at)); |
| 692 li(at, rt); | 758 li(at, rt); |
| 693 mult(rs, at); | 759 mult(rs, at); |
| 694 } | 760 } |
| 695 } | 761 } |
| 696 | 762 |
| 697 | 763 |
| 764 void MacroAssembler::Dmult(Register rs, const Operand& rt) { |
| 765 if (rt.is_reg()) { |
| 766 dmult(rs, rt.rm()); |
| 767 } else { |
| 768 // li handles the relocation. |
| 769 ASSERT(!rs.is(at)); |
| 770 li(at, rt); |
| 771 dmult(rs, at); |
| 772 } |
| 773 } |
| 774 |
| 775 |
| 698 void MacroAssembler::Multu(Register rs, const Operand& rt) { | 776 void MacroAssembler::Multu(Register rs, const Operand& rt) { |
| 699 if (rt.is_reg()) { | 777 if (rt.is_reg()) { |
| 700 multu(rs, rt.rm()); | 778 multu(rs, rt.rm()); |
| 701 } else { | 779 } else { |
| 702 // li handles the relocation. | 780 // li handles the relocation. |
| 703 ASSERT(!rs.is(at)); | 781 ASSERT(!rs.is(at)); |
| 704 li(at, rt); | 782 li(at, rt); |
| 705 multu(rs, at); | 783 multu(rs, at); |
| 706 } | 784 } |
| 707 } | 785 } |
| 708 | 786 |
| 709 | 787 |
| 788 void MacroAssembler::Dmultu(Register rs, const Operand& rt) { |
| 789 if (rt.is_reg()) { |
| 790 dmultu(rs, rt.rm()); |
| 791 } else { |
| 792 // li handles the relocation. |
| 793 ASSERT(!rs.is(at)); |
| 794 li(at, rt); |
| 795 dmultu(rs, at); |
| 796 } |
| 797 } |
| 798 |
| 799 |
| 710 void MacroAssembler::Div(Register rs, const Operand& rt) { | 800 void MacroAssembler::Div(Register rs, const Operand& rt) { |
| 711 if (rt.is_reg()) { | 801 if (rt.is_reg()) { |
| 712 div(rs, rt.rm()); | 802 div(rs, rt.rm()); |
| 713 } else { | 803 } else { |
| 714 // li handles the relocation. | 804 // li handles the relocation. |
| 715 ASSERT(!rs.is(at)); | 805 ASSERT(!rs.is(at)); |
| 716 li(at, rt); | 806 li(at, rt); |
| 717 div(rs, at); | 807 div(rs, at); |
| 718 } | 808 } |
| 719 } | 809 } |
| 720 | 810 |
| 721 | 811 |
| 812 void MacroAssembler::Ddiv(Register rs, const Operand& rt) { |
| 813 if (rt.is_reg()) { |
| 814 ddiv(rs, rt.rm()); |
| 815 } else { |
| 816 // li handles the relocation. |
| 817 ASSERT(!rs.is(at)); |
| 818 li(at, rt); |
| 819 ddiv(rs, at); |
| 820 } |
| 821 } |
| 822 |
| 823 |
| 722 void MacroAssembler::Divu(Register rs, const Operand& rt) { | 824 void MacroAssembler::Divu(Register rs, const Operand& rt) { |
| 723 if (rt.is_reg()) { | 825 if (rt.is_reg()) { |
| 724 divu(rs, rt.rm()); | 826 divu(rs, rt.rm()); |
| 725 } else { | 827 } else { |
| 726 // li handles the relocation. | 828 // li handles the relocation. |
| 727 ASSERT(!rs.is(at)); | 829 ASSERT(!rs.is(at)); |
| 728 li(at, rt); | 830 li(at, rt); |
| 729 divu(rs, at); | 831 divu(rs, at); |
| 730 } | 832 } |
| 731 } | 833 } |
| 732 | 834 |
| 733 | 835 |
| 836 void MacroAssembler::Ddivu(Register rs, const Operand& rt) { |
| 837 if (rt.is_reg()) { |
| 838 ddivu(rs, rt.rm()); |
| 839 } else { |
| 840 // li handles the relocation. |
| 841 ASSERT(!rs.is(at)); |
| 842 li(at, rt); |
| 843 ddivu(rs, at); |
| 844 } |
| 845 } |
| 846 |
| 847 |
| 734 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) { | 848 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) { |
| 735 if (rt.is_reg()) { | 849 if (rt.is_reg()) { |
| 736 and_(rd, rs, rt.rm()); | 850 and_(rd, rs, rt.rm()); |
| 737 } else { | 851 } else { |
| 738 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 852 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 739 andi(rd, rs, rt.imm32_); | 853 andi(rd, rs, rt.imm64_); |
| 740 } else { | 854 } else { |
| 741 // li handles the relocation. | 855 // li handles the relocation. |
| 742 ASSERT(!rs.is(at)); | 856 ASSERT(!rs.is(at)); |
| 743 li(at, rt); | 857 li(at, rt); |
| 744 and_(rd, rs, at); | 858 and_(rd, rs, at); |
| 745 } | 859 } |
| 746 } | 860 } |
| 747 } | 861 } |
| 748 | 862 |
| 749 | 863 |
| 750 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) { | 864 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) { |
| 751 if (rt.is_reg()) { | 865 if (rt.is_reg()) { |
| 752 or_(rd, rs, rt.rm()); | 866 or_(rd, rs, rt.rm()); |
| 753 } else { | 867 } else { |
| 754 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 868 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 755 ori(rd, rs, rt.imm32_); | 869 ori(rd, rs, rt.imm64_); |
| 756 } else { | 870 } else { |
| 757 // li handles the relocation. | 871 // li handles the relocation. |
| 758 ASSERT(!rs.is(at)); | 872 ASSERT(!rs.is(at)); |
| 759 li(at, rt); | 873 li(at, rt); |
| 760 or_(rd, rs, at); | 874 or_(rd, rs, at); |
| 761 } | 875 } |
| 762 } | 876 } |
| 763 } | 877 } |
| 764 | 878 |
| 765 | 879 |
| 766 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) { | 880 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) { |
| 767 if (rt.is_reg()) { | 881 if (rt.is_reg()) { |
| 768 xor_(rd, rs, rt.rm()); | 882 xor_(rd, rs, rt.rm()); |
| 769 } else { | 883 } else { |
| 770 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 884 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 771 xori(rd, rs, rt.imm32_); | 885 xori(rd, rs, rt.imm64_); |
| 772 } else { | 886 } else { |
| 773 // li handles the relocation. | 887 // li handles the relocation. |
| 774 ASSERT(!rs.is(at)); | 888 ASSERT(!rs.is(at)); |
| 775 li(at, rt); | 889 li(at, rt); |
| 776 xor_(rd, rs, at); | 890 xor_(rd, rs, at); |
| 777 } | 891 } |
| 778 } | 892 } |
| 779 } | 893 } |
| 780 | 894 |
| 781 | 895 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 797 ASSERT(!at.is(rt.rm())); | 911 ASSERT(!at.is(rt.rm())); |
| 798 li(at, -1); | 912 li(at, -1); |
| 799 xor_(rs, rt.rm(), at); | 913 xor_(rs, rt.rm(), at); |
| 800 } | 914 } |
| 801 | 915 |
| 802 | 916 |
| 803 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) { | 917 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) { |
| 804 if (rt.is_reg()) { | 918 if (rt.is_reg()) { |
| 805 slt(rd, rs, rt.rm()); | 919 slt(rd, rs, rt.rm()); |
| 806 } else { | 920 } else { |
| 807 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 921 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 808 slti(rd, rs, rt.imm32_); | 922 slti(rd, rs, rt.imm64_); |
| 809 } else { | 923 } else { |
| 810 // li handles the relocation. | 924 // li handles the relocation. |
| 811 ASSERT(!rs.is(at)); | 925 ASSERT(!rs.is(at)); |
| 812 li(at, rt); | 926 li(at, rt); |
| 813 slt(rd, rs, at); | 927 slt(rd, rs, at); |
| 814 } | 928 } |
| 815 } | 929 } |
| 816 } | 930 } |
| 817 | 931 |
| 818 | 932 |
| 819 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { | 933 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { |
| 820 if (rt.is_reg()) { | 934 if (rt.is_reg()) { |
| 821 sltu(rd, rs, rt.rm()); | 935 sltu(rd, rs, rt.rm()); |
| 822 } else { | 936 } else { |
| 823 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 937 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
| 824 sltiu(rd, rs, rt.imm32_); | 938 sltiu(rd, rs, rt.imm64_); |
| 825 } else { | 939 } else { |
| 826 // li handles the relocation. | 940 // li handles the relocation. |
| 827 ASSERT(!rs.is(at)); | 941 ASSERT(!rs.is(at)); |
| 828 li(at, rt); | 942 li(at, rt); |
| 829 sltu(rd, rs, at); | 943 sltu(rd, rs, at); |
| 830 } | 944 } |
| 831 } | 945 } |
| 832 } | 946 } |
| 833 | 947 |
| 834 | 948 |
| 835 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) { | 949 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) { |
| 836 if (kArchVariant == kMips32r2) { | 950 if (kArchVariant == kMips64r2) { |
| 837 if (rt.is_reg()) { | 951 if (rt.is_reg()) { |
| 838 rotrv(rd, rs, rt.rm()); | 952 rotrv(rd, rs, rt.rm()); |
| 839 } else { | 953 } else { |
| 840 rotr(rd, rs, rt.imm32_); | 954 rotr(rd, rs, rt.imm64_); |
| 841 } | 955 } |
| 842 } else { | 956 } else { |
| 843 if (rt.is_reg()) { | 957 if (rt.is_reg()) { |
| 844 subu(at, zero_reg, rt.rm()); | 958 subu(at, zero_reg, rt.rm()); |
| 845 sllv(at, rs, at); | 959 sllv(at, rs, at); |
| 846 srlv(rd, rs, rt.rm()); | 960 srlv(rd, rs, rt.rm()); |
| 847 or_(rd, rd, at); | 961 or_(rd, rd, at); |
| 848 } else { | 962 } else { |
| 849 if (rt.imm32_ == 0) { | 963 if (rt.imm64_ == 0) { |
| 850 srl(rd, rs, 0); | 964 srl(rd, rs, 0); |
| 851 } else { | 965 } else { |
| 852 srl(at, rs, rt.imm32_); | 966 srl(at, rs, rt.imm64_); |
| 853 sll(rd, rs, (0x20 - rt.imm32_) & 0x1f); | 967 sll(rd, rs, (0x20 - rt.imm64_) & 0x1f); |
| 854 or_(rd, rd, at); | 968 or_(rd, rd, at); |
| 855 } | 969 } |
| 856 } | 970 } |
| 857 } | 971 } |
| 858 } | 972 } |
| 859 | 973 |
| 860 | 974 |
| 975 void MacroAssembler::Dror(Register rd, Register rs, const Operand& rt) { |
| 976 if (rt.is_reg()) { |
| 977 drotrv(rd, rs, rt.rm()); |
| 978 } else { |
| 979 drotr(rd, rs, rt.imm64_); |
| 980 } |
| 981 } |
| 982 |
| 983 |
| 861 void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) { | 984 void MacroAssembler::Pref(int32_t hint, const MemOperand& rs) { |
| 862 if (kArchVariant == kLoongson) { | 985 if (kArchVariant == kLoongson) { |
| 863 lw(zero_reg, rs); | 986 lw(zero_reg, rs); |
| 864 } else { | 987 } else { |
| 865 pref(hint, rs); | 988 pref(hint, rs); |
| 866 } | 989 } |
| 867 } | 990 } |
| 868 | 991 |
| 869 | 992 |
| 870 // ------------Pseudo-instructions------------- | 993 // ------------Pseudo-instructions------------- |
| 871 | 994 |
| 872 void MacroAssembler::Ulw(Register rd, const MemOperand& rs) { | 995 void MacroAssembler::Ulw(Register rd, const MemOperand& rs) { |
| 873 lwr(rd, rs); | 996 lwr(rd, rs); |
| 874 lwl(rd, MemOperand(rs.rm(), rs.offset() + 3)); | 997 lwl(rd, MemOperand(rs.rm(), rs.offset() + 3)); |
| 875 } | 998 } |
| 876 | 999 |
| 877 | 1000 |
| 878 void MacroAssembler::Usw(Register rd, const MemOperand& rs) { | 1001 void MacroAssembler::Usw(Register rd, const MemOperand& rs) { |
| 879 swr(rd, rs); | 1002 swr(rd, rs); |
| 880 swl(rd, MemOperand(rs.rm(), rs.offset() + 3)); | 1003 swl(rd, MemOperand(rs.rm(), rs.offset() + 3)); |
| 881 } | 1004 } |
| 882 | 1005 |
| 883 | 1006 |
| 1007 // Do 64-bit load from unaligned address. Note this only handles |
| 1008 // the specific case of 32-bit aligned, but not 64-bit aligned. |
| 1009 void MacroAssembler::Uld(Register rd, const MemOperand& rs, Register scratch) { |
| 1010 // Assert fail if the offset from start of object IS actually aligned. |
| 1011 // ONLY use with known misalignment, since there is performance cost. |
| 1012 ASSERT((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); |
| 1013 // TODO(plind): endian dependency. |
| 1014 lwu(rd, rs); |
| 1015 lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); |
| 1016 dsll32(scratch, scratch, 0); |
| 1017 Daddu(rd, rd, scratch); |
| 1018 } |
| 1019 |
| 1020 |
| 1021 // Do 64-bit store to unaligned address. Note this only handles |
| 1022 // the specific case of 32-bit aligned, but not 64-bit aligned. |
| 1023 void MacroAssembler::Usd(Register rd, const MemOperand& rs, Register scratch) { |
| 1024 // Assert fail if the offset from start of object IS actually aligned. |
| 1025 // ONLY use with known misalignment, since there is performance cost. |
| 1026 ASSERT((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); |
| 1027 // TODO(plind): endian dependency. |
| 1028 sw(rd, rs); |
| 1029 dsrl32(scratch, rd, 0); |
| 1030 sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); |
| 1031 } |
| 1032 |
| 1033 |
| 884 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) { | 1034 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) { |
| 885 AllowDeferredHandleDereference smi_check; | 1035 AllowDeferredHandleDereference smi_check; |
| 886 if (value->IsSmi()) { | 1036 if (value->IsSmi()) { |
| 887 li(dst, Operand(value), mode); | 1037 li(dst, Operand(value), mode); |
| 888 } else { | 1038 } else { |
| 889 ASSERT(value->IsHeapObject()); | 1039 ASSERT(value->IsHeapObject()); |
| 890 if (isolate()->heap()->InNewSpace(*value)) { | 1040 if (isolate()->heap()->InNewSpace(*value)) { |
| 891 Handle<Cell> cell = isolate()->factory()->NewCell(value); | 1041 Handle<Cell> cell = isolate()->factory()->NewCell(value); |
| 892 li(dst, Operand(cell)); | 1042 li(dst, Operand(cell)); |
| 893 lw(dst, FieldMemOperand(dst, Cell::kValueOffset)); | 1043 ld(dst, FieldMemOperand(dst, Cell::kValueOffset)); |
| 894 } else { | 1044 } else { |
| 895 li(dst, Operand(value)); | 1045 li(dst, Operand(value)); |
| 896 } | 1046 } |
| 897 } | 1047 } |
| 898 } | 1048 } |
| 899 | 1049 |
| 900 | 1050 |
| 901 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) { | 1051 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) { |
| 902 ASSERT(!j.is_reg()); | 1052 ASSERT(!j.is_reg()); |
| 903 BlockTrampolinePoolScope block_trampoline_pool(this); | 1053 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 904 if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) { | 1054 if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) { |
| 905 // Normal load of an immediate value which does not need Relocation Info. | 1055 // Normal load of an immediate value which does not need Relocation Info. |
| 906 if (is_int16(j.imm32_)) { | 1056 if (is_int32(j.imm64_)) { |
| 907 addiu(rd, zero_reg, j.imm32_); | 1057 if (is_int16(j.imm64_)) { |
| 908 } else if (!(j.imm32_ & kHiMask)) { | 1058 daddiu(rd, zero_reg, (j.imm64_ & kImm16Mask)); |
| 909 ori(rd, zero_reg, j.imm32_); | 1059 } else if (!(j.imm64_ & kHiMask)) { |
| 910 } else if (!(j.imm32_ & kImm16Mask)) { | 1060 ori(rd, zero_reg, (j.imm64_ & kImm16Mask)); |
| 911 lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask); | 1061 } else if (!(j.imm64_ & kImm16Mask)) { |
| 1062 lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask); |
| 1063 } else { |
| 1064 lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask); |
| 1065 ori(rd, rd, (j.imm64_ & kImm16Mask)); |
| 1066 } |
| 912 } else { | 1067 } else { |
| 913 lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask); | 1068 lui(rd, (j.imm64_ >> 48) & kImm16Mask); |
| 914 ori(rd, rd, (j.imm32_ & kImm16Mask)); | 1069 ori(rd, rd, (j.imm64_ >> 32) & kImm16Mask); |
| 1070 dsll(rd, rd, 16); |
| 1071 ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask); |
| 1072 dsll(rd, rd, 16); |
| 1073 ori(rd, rd, j.imm64_ & kImm16Mask); |
| 915 } | 1074 } |
| 1075 } else if (MustUseReg(j.rmode_)) { |
| 1076 RecordRelocInfo(j.rmode_, j.imm64_); |
| 1077 lui(rd, (j.imm64_ >> 32) & kImm16Mask); |
| 1078 ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask); |
| 1079 dsll(rd, rd, 16); |
| 1080 ori(rd, rd, j.imm64_ & kImm16Mask); |
| 1081 } else if (mode == ADDRESS_LOAD) { |
| 1082 // We always need the same number of instructions as we may need to patch |
| 1083 // this code to load another value which may need all 4 instructions. |
| 1084 lui(rd, (j.imm64_ >> 32) & kImm16Mask); |
| 1085 ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask); |
| 1086 dsll(rd, rd, 16); |
| 1087 ori(rd, rd, j.imm64_ & kImm16Mask); |
| 916 } else { | 1088 } else { |
| 917 if (MustUseReg(j.rmode_)) { | 1089 lui(rd, (j.imm64_ >> 48) & kImm16Mask); |
| 918 RecordRelocInfo(j.rmode_, j.imm32_); | 1090 ori(rd, rd, (j.imm64_ >> 32) & kImm16Mask); |
| 919 } | 1091 dsll(rd, rd, 16); |
| 920 // We always need the same number of instructions as we may need to patch | 1092 ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask); |
| 921 // this code to load another value which may need 2 instructions to load. | 1093 dsll(rd, rd, 16); |
| 922 lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask); | 1094 ori(rd, rd, j.imm64_ & kImm16Mask); |
| 923 ori(rd, rd, (j.imm32_ & kImm16Mask)); | |
| 924 } | 1095 } |
| 925 } | 1096 } |
| 926 | 1097 |
| 927 | 1098 |
| 928 void MacroAssembler::MultiPush(RegList regs) { | 1099 void MacroAssembler::MultiPush(RegList regs) { |
| 929 int16_t num_to_push = NumberOfBitsSet(regs); | 1100 int16_t num_to_push = NumberOfBitsSet(regs); |
| 930 int16_t stack_offset = num_to_push * kPointerSize; | 1101 int16_t stack_offset = num_to_push * kPointerSize; |
| 931 | 1102 |
| 932 Subu(sp, sp, Operand(stack_offset)); | 1103 Dsubu(sp, sp, Operand(stack_offset)); |
| 933 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { | 1104 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { |
| 934 if ((regs & (1 << i)) != 0) { | 1105 if ((regs & (1 << i)) != 0) { |
| 935 stack_offset -= kPointerSize; | 1106 stack_offset -= kPointerSize; |
| 936 sw(ToRegister(i), MemOperand(sp, stack_offset)); | 1107 sd(ToRegister(i), MemOperand(sp, stack_offset)); |
| 937 } | 1108 } |
| 938 } | 1109 } |
| 939 } | 1110 } |
| 940 | 1111 |
| 941 | 1112 |
| 942 void MacroAssembler::MultiPushReversed(RegList regs) { | 1113 void MacroAssembler::MultiPushReversed(RegList regs) { |
| 943 int16_t num_to_push = NumberOfBitsSet(regs); | 1114 int16_t num_to_push = NumberOfBitsSet(regs); |
| 944 int16_t stack_offset = num_to_push * kPointerSize; | 1115 int16_t stack_offset = num_to_push * kPointerSize; |
| 945 | 1116 |
| 946 Subu(sp, sp, Operand(stack_offset)); | 1117 Dsubu(sp, sp, Operand(stack_offset)); |
| 947 for (int16_t i = 0; i < kNumRegisters; i++) { | 1118 for (int16_t i = 0; i < kNumRegisters; i++) { |
| 948 if ((regs & (1 << i)) != 0) { | 1119 if ((regs & (1 << i)) != 0) { |
| 949 stack_offset -= kPointerSize; | 1120 stack_offset -= kPointerSize; |
| 950 sw(ToRegister(i), MemOperand(sp, stack_offset)); | 1121 sd(ToRegister(i), MemOperand(sp, stack_offset)); |
| 951 } | 1122 } |
| 952 } | 1123 } |
| 953 } | 1124 } |
| 954 | 1125 |
| 955 | 1126 |
| 956 void MacroAssembler::MultiPop(RegList regs) { | 1127 void MacroAssembler::MultiPop(RegList regs) { |
| 957 int16_t stack_offset = 0; | 1128 int16_t stack_offset = 0; |
| 958 | 1129 |
| 959 for (int16_t i = 0; i < kNumRegisters; i++) { | 1130 for (int16_t i = 0; i < kNumRegisters; i++) { |
| 960 if ((regs & (1 << i)) != 0) { | 1131 if ((regs & (1 << i)) != 0) { |
| 961 lw(ToRegister(i), MemOperand(sp, stack_offset)); | 1132 ld(ToRegister(i), MemOperand(sp, stack_offset)); |
| 962 stack_offset += kPointerSize; | 1133 stack_offset += kPointerSize; |
| 963 } | 1134 } |
| 964 } | 1135 } |
| 965 addiu(sp, sp, stack_offset); | 1136 daddiu(sp, sp, stack_offset); |
| 966 } | 1137 } |
| 967 | 1138 |
| 968 | 1139 |
| 969 void MacroAssembler::MultiPopReversed(RegList regs) { | 1140 void MacroAssembler::MultiPopReversed(RegList regs) { |
| 970 int16_t stack_offset = 0; | 1141 int16_t stack_offset = 0; |
| 971 | 1142 |
| 972 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { | 1143 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { |
| 973 if ((regs & (1 << i)) != 0) { | 1144 if ((regs & (1 << i)) != 0) { |
| 974 lw(ToRegister(i), MemOperand(sp, stack_offset)); | 1145 ld(ToRegister(i), MemOperand(sp, stack_offset)); |
| 975 stack_offset += kPointerSize; | 1146 stack_offset += kPointerSize; |
| 976 } | 1147 } |
| 977 } | 1148 } |
| 978 addiu(sp, sp, stack_offset); | 1149 daddiu(sp, sp, stack_offset); |
| 979 } | 1150 } |
| 980 | 1151 |
| 981 | 1152 |
| 982 void MacroAssembler::MultiPushFPU(RegList regs) { | 1153 void MacroAssembler::MultiPushFPU(RegList regs) { |
| 983 int16_t num_to_push = NumberOfBitsSet(regs); | 1154 int16_t num_to_push = NumberOfBitsSet(regs); |
| 984 int16_t stack_offset = num_to_push * kDoubleSize; | 1155 int16_t stack_offset = num_to_push * kDoubleSize; |
| 985 | 1156 |
| 986 Subu(sp, sp, Operand(stack_offset)); | 1157 Dsubu(sp, sp, Operand(stack_offset)); |
| 987 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { | 1158 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { |
| 988 if ((regs & (1 << i)) != 0) { | 1159 if ((regs & (1 << i)) != 0) { |
| 989 stack_offset -= kDoubleSize; | 1160 stack_offset -= kDoubleSize; |
| 990 sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); | 1161 sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); |
| 991 } | 1162 } |
| 992 } | 1163 } |
| 993 } | 1164 } |
| 994 | 1165 |
| 995 | 1166 |
| 996 void MacroAssembler::MultiPushReversedFPU(RegList regs) { | 1167 void MacroAssembler::MultiPushReversedFPU(RegList regs) { |
| 997 int16_t num_to_push = NumberOfBitsSet(regs); | 1168 int16_t num_to_push = NumberOfBitsSet(regs); |
| 998 int16_t stack_offset = num_to_push * kDoubleSize; | 1169 int16_t stack_offset = num_to_push * kDoubleSize; |
| 999 | 1170 |
| 1000 Subu(sp, sp, Operand(stack_offset)); | 1171 Dsubu(sp, sp, Operand(stack_offset)); |
| 1001 for (int16_t i = 0; i < kNumRegisters; i++) { | 1172 for (int16_t i = 0; i < kNumRegisters; i++) { |
| 1002 if ((regs & (1 << i)) != 0) { | 1173 if ((regs & (1 << i)) != 0) { |
| 1003 stack_offset -= kDoubleSize; | 1174 stack_offset -= kDoubleSize; |
| 1004 sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); | 1175 sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); |
| 1005 } | 1176 } |
| 1006 } | 1177 } |
| 1007 } | 1178 } |
| 1008 | 1179 |
| 1009 | 1180 |
| 1010 void MacroAssembler::MultiPopFPU(RegList regs) { | 1181 void MacroAssembler::MultiPopFPU(RegList regs) { |
| 1011 int16_t stack_offset = 0; | 1182 int16_t stack_offset = 0; |
| 1012 | 1183 |
| 1013 for (int16_t i = 0; i < kNumRegisters; i++) { | 1184 for (int16_t i = 0; i < kNumRegisters; i++) { |
| 1014 if ((regs & (1 << i)) != 0) { | 1185 if ((regs & (1 << i)) != 0) { |
| 1015 ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); | 1186 ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); |
| 1016 stack_offset += kDoubleSize; | 1187 stack_offset += kDoubleSize; |
| 1017 } | 1188 } |
| 1018 } | 1189 } |
| 1019 addiu(sp, sp, stack_offset); | 1190 daddiu(sp, sp, stack_offset); |
| 1020 } | 1191 } |
| 1021 | 1192 |
| 1022 | 1193 |
| 1023 void MacroAssembler::MultiPopReversedFPU(RegList regs) { | 1194 void MacroAssembler::MultiPopReversedFPU(RegList regs) { |
| 1024 int16_t stack_offset = 0; | 1195 int16_t stack_offset = 0; |
| 1025 | 1196 |
| 1026 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { | 1197 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { |
| 1027 if ((regs & (1 << i)) != 0) { | 1198 if ((regs & (1 << i)) != 0) { |
| 1028 ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); | 1199 ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); |
| 1029 stack_offset += kDoubleSize; | 1200 stack_offset += kDoubleSize; |
| 1030 } | 1201 } |
| 1031 } | 1202 } |
| 1032 addiu(sp, sp, stack_offset); | 1203 daddiu(sp, sp, stack_offset); |
| 1033 } | 1204 } |
| 1034 | 1205 |
| 1035 | 1206 |
| 1036 void MacroAssembler::FlushICache(Register address, unsigned instructions) { | 1207 void MacroAssembler::FlushICache(Register address, unsigned instructions) { |
| 1037 RegList saved_regs = kJSCallerSaved | ra.bit(); | 1208 RegList saved_regs = kJSCallerSaved | ra.bit(); |
| 1038 MultiPush(saved_regs); | 1209 MultiPush(saved_regs); |
| 1039 AllowExternalCallThatCantCauseGC scope(this); | 1210 AllowExternalCallThatCantCauseGC scope(this); |
| 1040 | 1211 |
| 1041 // Save to a0 in case address == t0. | 1212 // Save to a0 in case address == a4. |
| 1042 Move(a0, address); | 1213 Move(a0, address); |
| 1043 PrepareCallCFunction(2, t0); | 1214 PrepareCallCFunction(2, a4); |
| 1044 | 1215 |
| 1045 li(a1, instructions * kInstrSize); | 1216 li(a1, instructions * kInstrSize); |
| 1046 CallCFunction(ExternalReference::flush_icache_function(isolate()), 2); | 1217 CallCFunction(ExternalReference::flush_icache_function(isolate()), 2); |
| 1047 MultiPop(saved_regs); | 1218 MultiPop(saved_regs); |
| 1048 } | 1219 } |
| 1049 | 1220 |
| 1050 | 1221 |
| 1051 void MacroAssembler::Ext(Register rt, | 1222 void MacroAssembler::Ext(Register rt, |
| 1052 Register rs, | 1223 Register rs, |
| 1053 uint16_t pos, | 1224 uint16_t pos, |
| 1054 uint16_t size) { | 1225 uint16_t size) { |
| 1055 ASSERT(pos < 32); | 1226 ASSERT(pos < 32); |
| 1056 ASSERT(pos + size < 33); | 1227 ASSERT(pos + size < 33); |
| 1057 | 1228 ext_(rt, rs, pos, size); |
| 1058 if (kArchVariant == kMips32r2) { | |
| 1059 ext_(rt, rs, pos, size); | |
| 1060 } else { | |
| 1061 // Move rs to rt and shift it left then right to get the | |
| 1062 // desired bitfield on the right side and zeroes on the left. | |
| 1063 int shift_left = 32 - (pos + size); | |
| 1064 sll(rt, rs, shift_left); // Acts as a move if shift_left == 0. | |
| 1065 | |
| 1066 int shift_right = 32 - size; | |
| 1067 if (shift_right > 0) { | |
| 1068 srl(rt, rt, shift_right); | |
| 1069 } | |
| 1070 } | |
| 1071 } | 1229 } |
| 1072 | 1230 |
| 1073 | 1231 |
| 1074 void MacroAssembler::Ins(Register rt, | 1232 void MacroAssembler::Ins(Register rt, |
| 1075 Register rs, | 1233 Register rs, |
| 1076 uint16_t pos, | 1234 uint16_t pos, |
| 1077 uint16_t size) { | 1235 uint16_t size) { |
| 1078 ASSERT(pos < 32); | 1236 ASSERT(pos < 32); |
| 1079 ASSERT(pos + size <= 32); | 1237 ASSERT(pos + size <= 32); |
| 1080 ASSERT(size != 0); | 1238 ASSERT(size != 0); |
| 1081 | 1239 ins_(rt, rs, pos, size); |
| 1082 if (kArchVariant == kMips32r2) { | |
| 1083 ins_(rt, rs, pos, size); | |
| 1084 } else { | |
| 1085 ASSERT(!rt.is(t8) && !rs.is(t8)); | |
| 1086 Subu(at, zero_reg, Operand(1)); | |
| 1087 srl(at, at, 32 - size); | |
| 1088 and_(t8, rs, at); | |
| 1089 sll(t8, t8, pos); | |
| 1090 sll(at, at, pos); | |
| 1091 nor(at, at, zero_reg); | |
| 1092 and_(at, rt, at); | |
| 1093 or_(rt, t8, at); | |
| 1094 } | |
| 1095 } | 1240 } |
| 1096 | 1241 |
| 1097 | 1242 |
| 1098 void MacroAssembler::Cvt_d_uw(FPURegister fd, | 1243 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
| 1099 FPURegister fs, | 1244 FPURegister fs, |
| 1100 FPURegister scratch) { | 1245 FPURegister scratch) { |
| 1101 // Move the data from fs to t8. | 1246 // Move the data from fs to t8. |
| 1102 mfc1(t8, fs); | 1247 mfc1(t8, fs); |
| 1103 Cvt_d_uw(fd, t8, scratch); | 1248 Cvt_d_uw(fd, t8, scratch); |
| 1104 } | 1249 } |
| 1105 | 1250 |
| 1106 | 1251 |
| 1107 void MacroAssembler::Cvt_d_uw(FPURegister fd, | 1252 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
| 1108 Register rs, | 1253 Register rs, |
| 1109 FPURegister scratch) { | 1254 FPURegister scratch) { |
| 1110 // Convert rs to a FP value in fd (and fd + 1). | 1255 // Convert rs to a FP value in fd (and fd + 1). |
| 1111 // We do this by converting rs minus the MSB to avoid sign conversion, | 1256 // We do this by converting rs minus the MSB to avoid sign conversion, |
| 1112 // then adding 2^31 to the result (if needed). | 1257 // then adding 2^31 to the result (if needed). |
| 1113 | 1258 |
| 1114 ASSERT(!fd.is(scratch)); | 1259 ASSERT(!fd.is(scratch)); |
| 1115 ASSERT(!rs.is(t9)); | 1260 ASSERT(!rs.is(t9)); |
| 1116 ASSERT(!rs.is(at)); | 1261 ASSERT(!rs.is(at)); |
| 1117 | 1262 |
| 1118 // Save rs's MSB to t9. | 1263 // Save rs's MSB to t9. |
| 1119 Ext(t9, rs, 31, 1); | 1264 Ext(t9, rs, 31, 1); |
| 1120 // Remove rs's MSB. | 1265 // Remove rs's MSB. |
| 1121 Ext(at, rs, 0, 31); | 1266 Ext(at, rs, 0, 31); |
| 1122 // Move the result to fd. | 1267 // Move the result to fd. |
| 1123 mtc1(at, fd); | 1268 mtc1(at, fd); |
| 1269 mthc1(zero_reg, fd); |
| 1124 | 1270 |
| 1125 // Convert fd to a real FP value. | 1271 // Convert fd to a real FP value. |
| 1126 cvt_d_w(fd, fd); | 1272 cvt_d_w(fd, fd); |
| 1127 | 1273 |
| 1128 Label conversion_done; | 1274 Label conversion_done; |
| 1129 | 1275 |
| 1130 // If rs's MSB was 0, it's done. | 1276 // If rs's MSB was 0, it's done. |
| 1131 // Otherwise we need to add that to the FP register. | 1277 // Otherwise we need to add that to the FP register. |
| 1132 Branch(&conversion_done, eq, t9, Operand(zero_reg)); | 1278 Branch(&conversion_done, eq, t9, Operand(zero_reg)); |
| 1133 | 1279 |
| 1134 // Load 2^31 into f20 as its float representation. | 1280 // Load 2^31 into f20 as its float representation. |
| 1135 li(at, 0x41E00000); | 1281 li(at, 0x41E00000); |
| 1136 mtc1(at, FPURegister::from_code(scratch.code() + 1)); | |
| 1137 mtc1(zero_reg, scratch); | 1282 mtc1(zero_reg, scratch); |
| 1283 mthc1(at, scratch); |
| 1138 // Add it to fd. | 1284 // Add it to fd. |
| 1139 add_d(fd, fd, scratch); | 1285 add_d(fd, fd, scratch); |
| 1140 | 1286 |
| 1141 bind(&conversion_done); | 1287 bind(&conversion_done); |
| 1142 } | 1288 } |
| 1143 | 1289 |
| 1144 | 1290 |
| 1291 void MacroAssembler::Round_l_d(FPURegister fd, FPURegister fs) { |
| 1292 round_l_d(fd, fs); |
| 1293 } |
| 1294 |
| 1295 |
| 1296 void MacroAssembler::Floor_l_d(FPURegister fd, FPURegister fs) { |
| 1297 floor_l_d(fd, fs); |
| 1298 } |
| 1299 |
| 1300 |
| 1301 void MacroAssembler::Ceil_l_d(FPURegister fd, FPURegister fs) { |
| 1302 ceil_l_d(fd, fs); |
| 1303 } |
| 1304 |
| 1305 |
| 1306 void MacroAssembler::Trunc_l_d(FPURegister fd, FPURegister fs) { |
| 1307 trunc_l_d(fd, fs); |
| 1308 } |
| 1309 |
| 1310 |
| 1311 void MacroAssembler::Trunc_l_ud(FPURegister fd, |
| 1312 FPURegister fs, |
| 1313 FPURegister scratch) { |
| 1314 // Load to GPR. |
| 1315 dmfc1(t8, fs); |
| 1316 // Reset sign bit. |
| 1317 li(at, 0x7fffffffffffffff); |
| 1318 and_(t8, t8, at); |
| 1319 dmtc1(t8, fs); |
| 1320 trunc_l_d(fd, fs); |
| 1321 } |
| 1322 |
| 1323 |
| 1145 void MacroAssembler::Trunc_uw_d(FPURegister fd, | 1324 void MacroAssembler::Trunc_uw_d(FPURegister fd, |
| 1146 FPURegister fs, | 1325 FPURegister fs, |
| 1147 FPURegister scratch) { | 1326 FPURegister scratch) { |
| 1148 Trunc_uw_d(fs, t8, scratch); | 1327 Trunc_uw_d(fs, t8, scratch); |
| 1149 mtc1(t8, fd); | 1328 mtc1(t8, fd); |
| 1150 } | 1329 } |
| 1151 | 1330 |
| 1152 | 1331 |
| 1153 void MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) { | 1332 void MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) { |
| 1154 if (kArchVariant == kLoongson && fd.is(fs)) { | 1333 trunc_w_d(fd, fs); |
| 1155 mfc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1156 trunc_w_d(fd, fs); | |
| 1157 mtc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1158 } else { | |
| 1159 trunc_w_d(fd, fs); | |
| 1160 } | |
| 1161 } | 1334 } |
| 1162 | 1335 |
| 1163 | 1336 |
| 1164 void MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) { | 1337 void MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) { |
| 1165 if (kArchVariant == kLoongson && fd.is(fs)) { | 1338 round_w_d(fd, fs); |
| 1166 mfc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1167 round_w_d(fd, fs); | |
| 1168 mtc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1169 } else { | |
| 1170 round_w_d(fd, fs); | |
| 1171 } | |
| 1172 } | 1339 } |
| 1173 | 1340 |
| 1174 | 1341 |
| 1175 void MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) { | 1342 void MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) { |
| 1176 if (kArchVariant == kLoongson && fd.is(fs)) { | 1343 floor_w_d(fd, fs); |
| 1177 mfc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1178 floor_w_d(fd, fs); | |
| 1179 mtc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1180 } else { | |
| 1181 floor_w_d(fd, fs); | |
| 1182 } | |
| 1183 } | 1344 } |
| 1184 | 1345 |
| 1185 | 1346 |
| 1186 void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) { | 1347 void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) { |
| 1187 if (kArchVariant == kLoongson && fd.is(fs)) { | 1348 ceil_w_d(fd, fs); |
| 1188 mfc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1189 ceil_w_d(fd, fs); | |
| 1190 mtc1(t8, FPURegister::from_code(fs.code() + 1)); | |
| 1191 } else { | |
| 1192 ceil_w_d(fd, fs); | |
| 1193 } | |
| 1194 } | 1349 } |
| 1195 | 1350 |
| 1196 | 1351 |
| 1197 void MacroAssembler::Trunc_uw_d(FPURegister fd, | 1352 void MacroAssembler::Trunc_uw_d(FPURegister fd, |
| 1198 Register rs, | 1353 Register rs, |
| 1199 FPURegister scratch) { | 1354 FPURegister scratch) { |
| 1200 ASSERT(!fd.is(scratch)); | 1355 ASSERT(!fd.is(scratch)); |
| 1201 ASSERT(!rs.is(at)); | 1356 ASSERT(!rs.is(at)); |
| 1202 | 1357 |
| 1203 // Load 2^31 into scratch as its float representation. | 1358 // Load 2^31 into scratch as its float representation. |
| 1204 li(at, 0x41E00000); | 1359 li(at, 0x41E00000); |
| 1205 mtc1(at, FPURegister::from_code(scratch.code() + 1)); | |
| 1206 mtc1(zero_reg, scratch); | 1360 mtc1(zero_reg, scratch); |
| 1361 mthc1(at, scratch); |
| 1207 // Test if scratch > fd. | 1362 // Test if scratch > fd. |
| 1208 // If fd < 2^31 we can convert it normally. | 1363 // If fd < 2^31 we can convert it normally. |
| 1209 Label simple_convert; | 1364 Label simple_convert; |
| 1210 BranchF(&simple_convert, NULL, lt, fd, scratch); | 1365 BranchF(&simple_convert, NULL, lt, fd, scratch); |
| 1211 | 1366 |
| 1212 // First we subtract 2^31 from fd, then trunc it to rs | 1367 // First we subtract 2^31 from fd, then trunc it to rs |
| 1213 // and add 2^31 to rs. | 1368 // and add 2^31 to rs. |
| 1214 sub_d(scratch, fd, scratch); | 1369 sub_d(scratch, fd, scratch); |
| 1215 trunc_w_d(scratch, scratch); | 1370 trunc_w_d(scratch, scratch); |
| 1216 mfc1(rs, scratch); | 1371 mfc1(rs, scratch); |
| 1217 Or(rs, rs, 1 << 31); | 1372 Or(rs, rs, 1 << 31); |
| 1218 | 1373 |
| 1219 Label done; | 1374 Label done; |
| 1220 Branch(&done); | 1375 Branch(&done); |
| 1221 // Simple conversion. | 1376 // Simple conversion. |
| 1222 bind(&simple_convert); | 1377 bind(&simple_convert); |
| 1223 trunc_w_d(scratch, fd); | 1378 trunc_w_d(scratch, fd); |
| 1224 mfc1(rs, scratch); | 1379 mfc1(rs, scratch); |
| 1225 | 1380 |
| 1226 bind(&done); | 1381 bind(&done); |
| 1227 } | 1382 } |
| 1228 | 1383 |
| 1229 | 1384 |
| 1385 void MacroAssembler::Madd_d(FPURegister fd, FPURegister fr, FPURegister fs, |
| 1386 FPURegister ft, FPURegister scratch) { |
| 1387 if (0) { // TODO(plind): find reasonable arch-variant symbol names. |
| 1388 madd_d(fd, fr, fs, ft); |
| 1389 } else { |
| 1390 // Can not change source regs's value. |
| 1391 ASSERT(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch)); |
| 1392 mul_d(scratch, fs, ft); |
| 1393 add_d(fd, fr, scratch); |
| 1394 } |
| 1395 } |
| 1396 |
| 1397 |
| 1230 void MacroAssembler::BranchF(Label* target, | 1398 void MacroAssembler::BranchF(Label* target, |
| 1231 Label* nan, | 1399 Label* nan, |
| 1232 Condition cc, | 1400 Condition cc, |
| 1233 FPURegister cmp1, | 1401 FPURegister cmp1, |
| 1234 FPURegister cmp2, | 1402 FPURegister cmp2, |
| 1235 BranchDelaySlot bd) { | 1403 BranchDelaySlot bd) { |
| 1236 BlockTrampolinePoolScope block_trampoline_pool(this); | 1404 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1237 if (cc == al) { | 1405 if (cc == al) { |
| 1238 Branch(bd, target); | 1406 Branch(bd, target); |
| 1239 return; | 1407 return; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 DoubleRepresentation value_rep(imm); | 1468 DoubleRepresentation value_rep(imm); |
| 1301 // Handle special values first. | 1469 // Handle special values first. |
| 1302 bool force_load = dst.is(kDoubleRegZero); | 1470 bool force_load = dst.is(kDoubleRegZero); |
| 1303 if (value_rep == zero && !force_load) { | 1471 if (value_rep == zero && !force_load) { |
| 1304 mov_d(dst, kDoubleRegZero); | 1472 mov_d(dst, kDoubleRegZero); |
| 1305 } else if (value_rep == minus_zero && !force_load) { | 1473 } else if (value_rep == minus_zero && !force_load) { |
| 1306 neg_d(dst, kDoubleRegZero); | 1474 neg_d(dst, kDoubleRegZero); |
| 1307 } else { | 1475 } else { |
| 1308 uint32_t lo, hi; | 1476 uint32_t lo, hi; |
| 1309 DoubleAsTwoUInt32(imm, &lo, &hi); | 1477 DoubleAsTwoUInt32(imm, &lo, &hi); |
| 1310 // Move the low part of the double into the lower of the corresponding FPU | 1478 // Move the low part of the double into the lower bits of the corresponding |
| 1311 // register of FPU register pair. | 1479 // FPU register. |
| 1312 if (lo != 0) { | 1480 if (lo != 0) { |
| 1313 li(at, Operand(lo)); | 1481 li(at, Operand(lo)); |
| 1314 mtc1(at, dst); | 1482 mtc1(at, dst); |
| 1315 } else { | 1483 } else { |
| 1316 mtc1(zero_reg, dst); | 1484 mtc1(zero_reg, dst); |
| 1317 } | 1485 } |
| 1318 // Move the high part of the double into the higher of the corresponding FPU | 1486 // Move the high part of the double into the high bits of the corresponding |
| 1319 // register of FPU register pair. | 1487 // FPU register. |
| 1320 if (hi != 0) { | 1488 if (hi != 0) { |
| 1321 li(at, Operand(hi)); | 1489 li(at, Operand(hi)); |
| 1322 mtc1(at, dst.high()); | 1490 mthc1(at, dst); |
| 1323 } else { | 1491 } else { |
| 1324 mtc1(zero_reg, dst.high()); | 1492 mthc1(zero_reg, dst); |
| 1325 } | 1493 } |
| 1326 } | 1494 } |
| 1327 } | 1495 } |
| 1328 | 1496 |
| 1329 | 1497 |
| 1330 void MacroAssembler::Movz(Register rd, Register rs, Register rt) { | 1498 void MacroAssembler::Movz(Register rd, Register rs, Register rt) { |
| 1331 if (kArchVariant == kLoongson) { | 1499 if (kArchVariant == kLoongson) { |
| 1332 Label done; | 1500 Label done; |
| 1333 Branch(&done, ne, rt, Operand(zero_reg)); | 1501 Branch(&done, ne, rt, Operand(zero_reg)); |
| 1334 mov(rd, rs); | 1502 mov(rd, rs); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1345 Branch(&done, eq, rt, Operand(zero_reg)); | 1513 Branch(&done, eq, rt, Operand(zero_reg)); |
| 1346 mov(rd, rs); | 1514 mov(rd, rs); |
| 1347 bind(&done); | 1515 bind(&done); |
| 1348 } else { | 1516 } else { |
| 1349 movn(rd, rs, rt); | 1517 movn(rd, rs, rt); |
| 1350 } | 1518 } |
| 1351 } | 1519 } |
| 1352 | 1520 |
| 1353 | 1521 |
| 1354 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) { | 1522 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) { |
| 1355 if (kArchVariant == kLoongson) { | 1523 movt(rd, rs, cc); |
| 1356 // Tests an FP condition code and then conditionally move rs to rd. | |
| 1357 // We do not currently use any FPU cc bit other than bit 0. | |
| 1358 ASSERT(cc == 0); | |
| 1359 ASSERT(!(rs.is(t8) || rd.is(t8))); | |
| 1360 Label done; | |
| 1361 Register scratch = t8; | |
| 1362 // For testing purposes we need to fetch content of the FCSR register and | |
| 1363 // than test its cc (floating point condition code) bit (for cc = 0, it is | |
| 1364 // 24. bit of the FCSR). | |
| 1365 cfc1(scratch, FCSR); | |
| 1366 // For the MIPS I, II and III architectures, the contents of scratch is | |
| 1367 // UNPREDICTABLE for the instruction immediately following CFC1. | |
| 1368 nop(); | |
| 1369 srl(scratch, scratch, 16); | |
| 1370 andi(scratch, scratch, 0x0080); | |
| 1371 Branch(&done, eq, scratch, Operand(zero_reg)); | |
| 1372 mov(rd, rs); | |
| 1373 bind(&done); | |
| 1374 } else { | |
| 1375 movt(rd, rs, cc); | |
| 1376 } | |
| 1377 } | 1524 } |
| 1378 | 1525 |
| 1379 | 1526 |
| 1380 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { | 1527 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { |
| 1381 if (kArchVariant == kLoongson) { | 1528 movf(rd, rs, cc); |
| 1382 // Tests an FP condition code and then conditionally move rs to rd. | |
| 1383 // We do not currently use any FPU cc bit other than bit 0. | |
| 1384 ASSERT(cc == 0); | |
| 1385 ASSERT(!(rs.is(t8) || rd.is(t8))); | |
| 1386 Label done; | |
| 1387 Register scratch = t8; | |
| 1388 // For testing purposes we need to fetch content of the FCSR register and | |
| 1389 // than test its cc (floating point condition code) bit (for cc = 0, it is | |
| 1390 // 24. bit of the FCSR). | |
| 1391 cfc1(scratch, FCSR); | |
| 1392 // For the MIPS I, II and III architectures, the contents of scratch is | |
| 1393 // UNPREDICTABLE for the instruction immediately following CFC1. | |
| 1394 nop(); | |
| 1395 srl(scratch, scratch, 16); | |
| 1396 andi(scratch, scratch, 0x0080); | |
| 1397 Branch(&done, ne, scratch, Operand(zero_reg)); | |
| 1398 mov(rd, rs); | |
| 1399 bind(&done); | |
| 1400 } else { | |
| 1401 movf(rd, rs, cc); | |
| 1402 } | |
| 1403 } | 1529 } |
| 1404 | 1530 |
| 1405 | 1531 |
| 1406 void MacroAssembler::Clz(Register rd, Register rs) { | 1532 void MacroAssembler::Clz(Register rd, Register rs) { |
| 1407 if (kArchVariant == kLoongson) { | 1533 clz(rd, rs); |
| 1408 ASSERT(!(rd.is(t8) || rd.is(t9)) && !(rs.is(t8) || rs.is(t9))); | |
| 1409 Register mask = t8; | |
| 1410 Register scratch = t9; | |
| 1411 Label loop, end; | |
| 1412 mov(at, rs); | |
| 1413 mov(rd, zero_reg); | |
| 1414 lui(mask, 0x8000); | |
| 1415 bind(&loop); | |
| 1416 and_(scratch, at, mask); | |
| 1417 Branch(&end, ne, scratch, Operand(zero_reg)); | |
| 1418 addiu(rd, rd, 1); | |
| 1419 Branch(&loop, ne, mask, Operand(zero_reg), USE_DELAY_SLOT); | |
| 1420 srl(mask, mask, 1); | |
| 1421 bind(&end); | |
| 1422 } else { | |
| 1423 clz(rd, rs); | |
| 1424 } | |
| 1425 } | 1534 } |
| 1426 | 1535 |
| 1427 | 1536 |
| 1428 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, | 1537 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, |
| 1429 Register result, | 1538 Register result, |
| 1430 DoubleRegister double_input, | 1539 DoubleRegister double_input, |
| 1431 Register scratch, | 1540 Register scratch, |
| 1432 DoubleRegister double_scratch, | 1541 DoubleRegister double_scratch, |
| 1433 Register except_flag, | 1542 Register except_flag, |
| 1434 CheckForInexactConversion check_inexact) { | 1543 CheckForInexactConversion check_inexact) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 | 1624 |
| 1516 | 1625 |
| 1517 void MacroAssembler::TruncateDoubleToI(Register result, | 1626 void MacroAssembler::TruncateDoubleToI(Register result, |
| 1518 DoubleRegister double_input) { | 1627 DoubleRegister double_input) { |
| 1519 Label done; | 1628 Label done; |
| 1520 | 1629 |
| 1521 TryInlineTruncateDoubleToI(result, double_input, &done); | 1630 TryInlineTruncateDoubleToI(result, double_input, &done); |
| 1522 | 1631 |
| 1523 // If we fell through then inline version didn't succeed - call stub instead. | 1632 // If we fell through then inline version didn't succeed - call stub instead. |
| 1524 push(ra); | 1633 push(ra); |
| 1525 Subu(sp, sp, Operand(kDoubleSize)); // Put input on stack. | 1634 Dsubu(sp, sp, Operand(kDoubleSize)); // Put input on stack. |
| 1526 sdc1(double_input, MemOperand(sp, 0)); | 1635 sdc1(double_input, MemOperand(sp, 0)); |
| 1527 | 1636 |
| 1528 DoubleToIStub stub(isolate(), sp, result, 0, true, true); | 1637 DoubleToIStub stub(isolate(), sp, result, 0, true, true); |
| 1529 CallStub(&stub); | 1638 CallStub(&stub); |
| 1530 | 1639 |
| 1531 Addu(sp, sp, Operand(kDoubleSize)); | 1640 Daddu(sp, sp, Operand(kDoubleSize)); |
| 1532 pop(ra); | 1641 pop(ra); |
| 1533 | 1642 |
| 1534 bind(&done); | 1643 bind(&done); |
| 1535 } | 1644 } |
| 1536 | 1645 |
| 1537 | 1646 |
| 1538 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) { | 1647 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) { |
| 1539 Label done; | 1648 Label done; |
| 1540 DoubleRegister double_scratch = f12; | 1649 DoubleRegister double_scratch = f12; |
| 1541 ASSERT(!result.is(object)); | 1650 ASSERT(!result.is(object)); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1571 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); | 1680 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); |
| 1572 TruncateHeapNumberToI(result, object); | 1681 TruncateHeapNumberToI(result, object); |
| 1573 | 1682 |
| 1574 bind(&done); | 1683 bind(&done); |
| 1575 } | 1684 } |
| 1576 | 1685 |
| 1577 | 1686 |
| 1578 void MacroAssembler::GetLeastBitsFromSmi(Register dst, | 1687 void MacroAssembler::GetLeastBitsFromSmi(Register dst, |
| 1579 Register src, | 1688 Register src, |
| 1580 int num_least_bits) { | 1689 int num_least_bits) { |
| 1581 Ext(dst, src, kSmiTagSize, num_least_bits); | 1690 // Ext(dst, src, kSmiTagSize, num_least_bits); |
| 1691 SmiUntag(dst, src); |
| 1692 And(dst, dst, Operand((1 << num_least_bits) - 1)); |
| 1582 } | 1693 } |
| 1583 | 1694 |
| 1584 | 1695 |
| 1585 void MacroAssembler::GetLeastBitsFromInt32(Register dst, | 1696 void MacroAssembler::GetLeastBitsFromInt32(Register dst, |
| 1586 Register src, | 1697 Register src, |
| 1587 int num_least_bits) { | 1698 int num_least_bits) { |
| 1699 ASSERT(!src.is(dst)); |
| 1588 And(dst, src, Operand((1 << num_least_bits) - 1)); | 1700 And(dst, src, Operand((1 << num_least_bits) - 1)); |
| 1589 } | 1701 } |
| 1590 | 1702 |
| 1591 | 1703 |
| 1592 // Emulated condtional branches do not emit a nop in the branch delay slot. | 1704 // Emulated condtional branches do not emit a nop in the branch delay slot. |
| 1593 // | 1705 // |
| 1594 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. | 1706 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. |
| 1595 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \ | 1707 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \ |
| 1596 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ | 1708 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ |
| 1597 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) | 1709 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1791 break; | 1903 break; |
| 1792 case ne: | 1904 case ne: |
| 1793 // We don't want any other register but scratch clobbered. | 1905 // We don't want any other register but scratch clobbered. |
| 1794 ASSERT(!scratch.is(rs)); | 1906 ASSERT(!scratch.is(rs)); |
| 1795 r2 = scratch; | 1907 r2 = scratch; |
| 1796 li(r2, rt); | 1908 li(r2, rt); |
| 1797 bne(rs, r2, offset); | 1909 bne(rs, r2, offset); |
| 1798 break; | 1910 break; |
| 1799 // Signed comparison. | 1911 // Signed comparison. |
| 1800 case greater: | 1912 case greater: |
| 1801 if (rt.imm32_ == 0) { | 1913 if (rt.imm64_ == 0) { |
| 1802 bgtz(rs, offset); | 1914 bgtz(rs, offset); |
| 1803 } else { | 1915 } else { |
| 1804 r2 = scratch; | 1916 r2 = scratch; |
| 1805 li(r2, rt); | 1917 li(r2, rt); |
| 1806 slt(scratch, r2, rs); | 1918 slt(scratch, r2, rs); |
| 1807 bne(scratch, zero_reg, offset); | 1919 bne(scratch, zero_reg, offset); |
| 1808 } | 1920 } |
| 1809 break; | 1921 break; |
| 1810 case greater_equal: | 1922 case greater_equal: |
| 1811 if (rt.imm32_ == 0) { | 1923 if (rt.imm64_ == 0) { |
| 1812 bgez(rs, offset); | 1924 bgez(rs, offset); |
| 1813 } else if (is_int16(rt.imm32_)) { | 1925 } else if (is_int16(rt.imm64_)) { |
| 1814 slti(scratch, rs, rt.imm32_); | 1926 slti(scratch, rs, rt.imm64_); |
| 1815 beq(scratch, zero_reg, offset); | 1927 beq(scratch, zero_reg, offset); |
| 1816 } else { | 1928 } else { |
| 1817 r2 = scratch; | 1929 r2 = scratch; |
| 1818 li(r2, rt); | 1930 li(r2, rt); |
| 1819 slt(scratch, rs, r2); | 1931 slt(scratch, rs, r2); |
| 1820 beq(scratch, zero_reg, offset); | 1932 beq(scratch, zero_reg, offset); |
| 1821 } | 1933 } |
| 1822 break; | 1934 break; |
| 1823 case less: | 1935 case less: |
| 1824 if (rt.imm32_ == 0) { | 1936 if (rt.imm64_ == 0) { |
| 1825 bltz(rs, offset); | 1937 bltz(rs, offset); |
| 1826 } else if (is_int16(rt.imm32_)) { | 1938 } else if (is_int16(rt.imm64_)) { |
| 1827 slti(scratch, rs, rt.imm32_); | 1939 slti(scratch, rs, rt.imm64_); |
| 1828 bne(scratch, zero_reg, offset); | 1940 bne(scratch, zero_reg, offset); |
| 1829 } else { | 1941 } else { |
| 1830 r2 = scratch; | 1942 r2 = scratch; |
| 1831 li(r2, rt); | 1943 li(r2, rt); |
| 1832 slt(scratch, rs, r2); | 1944 slt(scratch, rs, r2); |
| 1833 bne(scratch, zero_reg, offset); | 1945 bne(scratch, zero_reg, offset); |
| 1834 } | 1946 } |
| 1835 break; | 1947 break; |
| 1836 case less_equal: | 1948 case less_equal: |
| 1837 if (rt.imm32_ == 0) { | 1949 if (rt.imm64_ == 0) { |
| 1838 blez(rs, offset); | 1950 blez(rs, offset); |
| 1839 } else { | 1951 } else { |
| 1840 r2 = scratch; | 1952 r2 = scratch; |
| 1841 li(r2, rt); | 1953 li(r2, rt); |
| 1842 slt(scratch, r2, rs); | 1954 slt(scratch, r2, rs); |
| 1843 beq(scratch, zero_reg, offset); | 1955 beq(scratch, zero_reg, offset); |
| 1844 } | 1956 } |
| 1845 break; | 1957 break; |
| 1846 // Unsigned comparison. | 1958 // Unsigned comparison. |
| 1847 case Ugreater: | 1959 case Ugreater: |
| 1848 if (rt.imm32_ == 0) { | 1960 if (rt.imm64_ == 0) { |
| 1849 bgtz(rs, offset); | 1961 bgtz(rs, offset); |
| 1850 } else { | 1962 } else { |
| 1851 r2 = scratch; | 1963 r2 = scratch; |
| 1852 li(r2, rt); | 1964 li(r2, rt); |
| 1853 sltu(scratch, r2, rs); | 1965 sltu(scratch, r2, rs); |
| 1854 bne(scratch, zero_reg, offset); | 1966 bne(scratch, zero_reg, offset); |
| 1855 } | 1967 } |
| 1856 break; | 1968 break; |
| 1857 case Ugreater_equal: | 1969 case Ugreater_equal: |
| 1858 if (rt.imm32_ == 0) { | 1970 if (rt.imm64_ == 0) { |
| 1859 bgez(rs, offset); | 1971 bgez(rs, offset); |
| 1860 } else if (is_int16(rt.imm32_)) { | 1972 } else if (is_int16(rt.imm64_)) { |
| 1861 sltiu(scratch, rs, rt.imm32_); | 1973 sltiu(scratch, rs, rt.imm64_); |
| 1862 beq(scratch, zero_reg, offset); | 1974 beq(scratch, zero_reg, offset); |
| 1863 } else { | 1975 } else { |
| 1864 r2 = scratch; | 1976 r2 = scratch; |
| 1865 li(r2, rt); | 1977 li(r2, rt); |
| 1866 sltu(scratch, rs, r2); | 1978 sltu(scratch, rs, r2); |
| 1867 beq(scratch, zero_reg, offset); | 1979 beq(scratch, zero_reg, offset); |
| 1868 } | 1980 } |
| 1869 break; | 1981 break; |
| 1870 case Uless: | 1982 case Uless: |
| 1871 if (rt.imm32_ == 0) { | 1983 if (rt.imm64_ == 0) { |
| 1872 // No code needs to be emitted. | 1984 // No code needs to be emitted. |
| 1873 return; | 1985 return; |
| 1874 } else if (is_int16(rt.imm32_)) { | 1986 } else if (is_int16(rt.imm64_)) { |
| 1875 sltiu(scratch, rs, rt.imm32_); | 1987 sltiu(scratch, rs, rt.imm64_); |
| 1876 bne(scratch, zero_reg, offset); | 1988 bne(scratch, zero_reg, offset); |
| 1877 } else { | 1989 } else { |
| 1878 r2 = scratch; | 1990 r2 = scratch; |
| 1879 li(r2, rt); | 1991 li(r2, rt); |
| 1880 sltu(scratch, rs, r2); | 1992 sltu(scratch, rs, r2); |
| 1881 bne(scratch, zero_reg, offset); | 1993 bne(scratch, zero_reg, offset); |
| 1882 } | 1994 } |
| 1883 break; | 1995 break; |
| 1884 case Uless_equal: | 1996 case Uless_equal: |
| 1885 if (rt.imm32_ == 0) { | 1997 if (rt.imm64_ == 0) { |
| 1886 b(offset); | 1998 b(offset); |
| 1887 } else { | 1999 } else { |
| 1888 r2 = scratch; | 2000 r2 = scratch; |
| 1889 li(r2, rt); | 2001 li(r2, rt); |
| 1890 sltu(scratch, r2, rs); | 2002 sltu(scratch, r2, rs); |
| 1891 beq(scratch, zero_reg, offset); | 2003 beq(scratch, zero_reg, offset); |
| 1892 } | 2004 } |
| 1893 break; | 2005 break; |
| 1894 default: | 2006 default: |
| 1895 UNREACHABLE(); | 2007 UNREACHABLE(); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2044 break; | 2156 break; |
| 2045 case ne: | 2157 case ne: |
| 2046 ASSERT(!scratch.is(rs)); | 2158 ASSERT(!scratch.is(rs)); |
| 2047 r2 = scratch; | 2159 r2 = scratch; |
| 2048 li(r2, rt); | 2160 li(r2, rt); |
| 2049 offset = shifted_branch_offset(L, false); | 2161 offset = shifted_branch_offset(L, false); |
| 2050 bne(rs, r2, offset); | 2162 bne(rs, r2, offset); |
| 2051 break; | 2163 break; |
| 2052 // Signed comparison. | 2164 // Signed comparison. |
| 2053 case greater: | 2165 case greater: |
| 2054 if (rt.imm32_ == 0) { | 2166 if (rt.imm64_ == 0) { |
| 2055 offset = shifted_branch_offset(L, false); | 2167 offset = shifted_branch_offset(L, false); |
| 2056 bgtz(rs, offset); | 2168 bgtz(rs, offset); |
| 2057 } else { | 2169 } else { |
| 2058 ASSERT(!scratch.is(rs)); | 2170 ASSERT(!scratch.is(rs)); |
| 2059 r2 = scratch; | 2171 r2 = scratch; |
| 2060 li(r2, rt); | 2172 li(r2, rt); |
| 2061 slt(scratch, r2, rs); | 2173 slt(scratch, r2, rs); |
| 2062 offset = shifted_branch_offset(L, false); | 2174 offset = shifted_branch_offset(L, false); |
| 2063 bne(scratch, zero_reg, offset); | 2175 bne(scratch, zero_reg, offset); |
| 2064 } | 2176 } |
| 2065 break; | 2177 break; |
| 2066 case greater_equal: | 2178 case greater_equal: |
| 2067 if (rt.imm32_ == 0) { | 2179 if (rt.imm64_ == 0) { |
| 2068 offset = shifted_branch_offset(L, false); | 2180 offset = shifted_branch_offset(L, false); |
| 2069 bgez(rs, offset); | 2181 bgez(rs, offset); |
| 2070 } else if (is_int16(rt.imm32_)) { | 2182 } else if (is_int16(rt.imm64_)) { |
| 2071 slti(scratch, rs, rt.imm32_); | 2183 slti(scratch, rs, rt.imm64_); |
| 2072 offset = shifted_branch_offset(L, false); | 2184 offset = shifted_branch_offset(L, false); |
| 2073 beq(scratch, zero_reg, offset); | 2185 beq(scratch, zero_reg, offset); |
| 2074 } else { | 2186 } else { |
| 2075 ASSERT(!scratch.is(rs)); | 2187 ASSERT(!scratch.is(rs)); |
| 2076 r2 = scratch; | 2188 r2 = scratch; |
| 2077 li(r2, rt); | 2189 li(r2, rt); |
| 2078 slt(scratch, rs, r2); | 2190 slt(scratch, rs, r2); |
| 2079 offset = shifted_branch_offset(L, false); | 2191 offset = shifted_branch_offset(L, false); |
| 2080 beq(scratch, zero_reg, offset); | 2192 beq(scratch, zero_reg, offset); |
| 2081 } | 2193 } |
| 2082 break; | 2194 break; |
| 2083 case less: | 2195 case less: |
| 2084 if (rt.imm32_ == 0) { | 2196 if (rt.imm64_ == 0) { |
| 2085 offset = shifted_branch_offset(L, false); | 2197 offset = shifted_branch_offset(L, false); |
| 2086 bltz(rs, offset); | 2198 bltz(rs, offset); |
| 2087 } else if (is_int16(rt.imm32_)) { | 2199 } else if (is_int16(rt.imm64_)) { |
| 2088 slti(scratch, rs, rt.imm32_); | 2200 slti(scratch, rs, rt.imm64_); |
| 2089 offset = shifted_branch_offset(L, false); | 2201 offset = shifted_branch_offset(L, false); |
| 2090 bne(scratch, zero_reg, offset); | 2202 bne(scratch, zero_reg, offset); |
| 2091 } else { | 2203 } else { |
| 2092 ASSERT(!scratch.is(rs)); | 2204 ASSERT(!scratch.is(rs)); |
| 2093 r2 = scratch; | 2205 r2 = scratch; |
| 2094 li(r2, rt); | 2206 li(r2, rt); |
| 2095 slt(scratch, rs, r2); | 2207 slt(scratch, rs, r2); |
| 2096 offset = shifted_branch_offset(L, false); | 2208 offset = shifted_branch_offset(L, false); |
| 2097 bne(scratch, zero_reg, offset); | 2209 bne(scratch, zero_reg, offset); |
| 2098 } | 2210 } |
| 2099 break; | 2211 break; |
| 2100 case less_equal: | 2212 case less_equal: |
| 2101 if (rt.imm32_ == 0) { | 2213 if (rt.imm64_ == 0) { |
| 2102 offset = shifted_branch_offset(L, false); | 2214 offset = shifted_branch_offset(L, false); |
| 2103 blez(rs, offset); | 2215 blez(rs, offset); |
| 2104 } else { | 2216 } else { |
| 2105 ASSERT(!scratch.is(rs)); | 2217 ASSERT(!scratch.is(rs)); |
| 2106 r2 = scratch; | 2218 r2 = scratch; |
| 2107 li(r2, rt); | 2219 li(r2, rt); |
| 2108 slt(scratch, r2, rs); | 2220 slt(scratch, r2, rs); |
| 2109 offset = shifted_branch_offset(L, false); | 2221 offset = shifted_branch_offset(L, false); |
| 2110 beq(scratch, zero_reg, offset); | 2222 beq(scratch, zero_reg, offset); |
| 2111 } | 2223 } |
| 2112 break; | 2224 break; |
| 2113 // Unsigned comparison. | 2225 // Unsigned comparison. |
| 2114 case Ugreater: | 2226 case Ugreater: |
| 2115 if (rt.imm32_ == 0) { | 2227 if (rt.imm64_ == 0) { |
| 2116 offset = shifted_branch_offset(L, false); | 2228 offset = shifted_branch_offset(L, false); |
| 2117 bne(rs, zero_reg, offset); | 2229 bne(rs, zero_reg, offset); |
| 2118 } else { | 2230 } else { |
| 2119 ASSERT(!scratch.is(rs)); | 2231 ASSERT(!scratch.is(rs)); |
| 2120 r2 = scratch; | 2232 r2 = scratch; |
| 2121 li(r2, rt); | 2233 li(r2, rt); |
| 2122 sltu(scratch, r2, rs); | 2234 sltu(scratch, r2, rs); |
| 2123 offset = shifted_branch_offset(L, false); | 2235 offset = shifted_branch_offset(L, false); |
| 2124 bne(scratch, zero_reg, offset); | 2236 bne(scratch, zero_reg, offset); |
| 2125 } | 2237 } |
| 2126 break; | 2238 break; |
| 2127 case Ugreater_equal: | 2239 case Ugreater_equal: |
| 2128 if (rt.imm32_ == 0) { | 2240 if (rt.imm64_ == 0) { |
| 2129 offset = shifted_branch_offset(L, false); | 2241 offset = shifted_branch_offset(L, false); |
| 2130 bgez(rs, offset); | 2242 bgez(rs, offset); |
| 2131 } else if (is_int16(rt.imm32_)) { | 2243 } else if (is_int16(rt.imm64_)) { |
| 2132 sltiu(scratch, rs, rt.imm32_); | 2244 sltiu(scratch, rs, rt.imm64_); |
| 2133 offset = shifted_branch_offset(L, false); | 2245 offset = shifted_branch_offset(L, false); |
| 2134 beq(scratch, zero_reg, offset); | 2246 beq(scratch, zero_reg, offset); |
| 2135 } else { | 2247 } else { |
| 2136 ASSERT(!scratch.is(rs)); | 2248 ASSERT(!scratch.is(rs)); |
| 2137 r2 = scratch; | 2249 r2 = scratch; |
| 2138 li(r2, rt); | 2250 li(r2, rt); |
| 2139 sltu(scratch, rs, r2); | 2251 sltu(scratch, rs, r2); |
| 2140 offset = shifted_branch_offset(L, false); | 2252 offset = shifted_branch_offset(L, false); |
| 2141 beq(scratch, zero_reg, offset); | 2253 beq(scratch, zero_reg, offset); |
| 2142 } | 2254 } |
| 2143 break; | 2255 break; |
| 2144 case Uless: | 2256 case Uless: |
| 2145 if (rt.imm32_ == 0) { | 2257 if (rt.imm64_ == 0) { |
| 2146 // No code needs to be emitted. | 2258 // No code needs to be emitted. |
| 2147 return; | 2259 return; |
| 2148 } else if (is_int16(rt.imm32_)) { | 2260 } else if (is_int16(rt.imm64_)) { |
| 2149 sltiu(scratch, rs, rt.imm32_); | 2261 sltiu(scratch, rs, rt.imm64_); |
| 2150 offset = shifted_branch_offset(L, false); | 2262 offset = shifted_branch_offset(L, false); |
| 2151 bne(scratch, zero_reg, offset); | 2263 bne(scratch, zero_reg, offset); |
| 2152 } else { | 2264 } else { |
| 2153 ASSERT(!scratch.is(rs)); | 2265 ASSERT(!scratch.is(rs)); |
| 2154 r2 = scratch; | 2266 r2 = scratch; |
| 2155 li(r2, rt); | 2267 li(r2, rt); |
| 2156 sltu(scratch, rs, r2); | 2268 sltu(scratch, rs, r2); |
| 2157 offset = shifted_branch_offset(L, false); | 2269 offset = shifted_branch_offset(L, false); |
| 2158 bne(scratch, zero_reg, offset); | 2270 bne(scratch, zero_reg, offset); |
| 2159 } | 2271 } |
| 2160 break; | 2272 break; |
| 2161 case Uless_equal: | 2273 case Uless_equal: |
| 2162 if (rt.imm32_ == 0) { | 2274 if (rt.imm64_ == 0) { |
| 2163 offset = shifted_branch_offset(L, false); | 2275 offset = shifted_branch_offset(L, false); |
| 2164 beq(rs, zero_reg, offset); | 2276 beq(rs, zero_reg, offset); |
| 2165 } else { | 2277 } else { |
| 2166 ASSERT(!scratch.is(rs)); | 2278 ASSERT(!scratch.is(rs)); |
| 2167 r2 = scratch; | 2279 r2 = scratch; |
| 2168 li(r2, rt); | 2280 li(r2, rt); |
| 2169 sltu(scratch, r2, rs); | 2281 sltu(scratch, r2, rs); |
| 2170 offset = shifted_branch_offset(L, false); | 2282 offset = shifted_branch_offset(L, false); |
| 2171 beq(scratch, zero_reg, offset); | 2283 beq(scratch, zero_reg, offset); |
| 2172 } | 2284 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2279 break; | 2391 break; |
| 2280 case ne: | 2392 case ne: |
| 2281 beq(rs, r2, 2); | 2393 beq(rs, r2, 2); |
| 2282 nop(); | 2394 nop(); |
| 2283 bal(offset); | 2395 bal(offset); |
| 2284 break; | 2396 break; |
| 2285 | 2397 |
| 2286 // Signed comparison. | 2398 // Signed comparison. |
| 2287 case greater: | 2399 case greater: |
| 2288 slt(scratch, r2, rs); | 2400 slt(scratch, r2, rs); |
| 2289 addiu(scratch, scratch, -1); | 2401 daddiu(scratch, scratch, -1); |
| 2290 bgezal(scratch, offset); | 2402 bgezal(scratch, offset); |
| 2291 break; | 2403 break; |
| 2292 case greater_equal: | 2404 case greater_equal: |
| 2293 slt(scratch, rs, r2); | 2405 slt(scratch, rs, r2); |
| 2294 addiu(scratch, scratch, -1); | 2406 daddiu(scratch, scratch, -1); |
| 2295 bltzal(scratch, offset); | 2407 bltzal(scratch, offset); |
| 2296 break; | 2408 break; |
| 2297 case less: | 2409 case less: |
| 2298 slt(scratch, rs, r2); | 2410 slt(scratch, rs, r2); |
| 2299 addiu(scratch, scratch, -1); | 2411 daddiu(scratch, scratch, -1); |
| 2300 bgezal(scratch, offset); | 2412 bgezal(scratch, offset); |
| 2301 break; | 2413 break; |
| 2302 case less_equal: | 2414 case less_equal: |
| 2303 slt(scratch, r2, rs); | 2415 slt(scratch, r2, rs); |
| 2304 addiu(scratch, scratch, -1); | 2416 daddiu(scratch, scratch, -1); |
| 2305 bltzal(scratch, offset); | 2417 bltzal(scratch, offset); |
| 2306 break; | 2418 break; |
| 2307 | 2419 |
| 2308 // Unsigned comparison. | 2420 // Unsigned comparison. |
| 2309 case Ugreater: | 2421 case Ugreater: |
| 2310 sltu(scratch, r2, rs); | 2422 sltu(scratch, r2, rs); |
| 2311 addiu(scratch, scratch, -1); | 2423 daddiu(scratch, scratch, -1); |
| 2312 bgezal(scratch, offset); | 2424 bgezal(scratch, offset); |
| 2313 break; | 2425 break; |
| 2314 case Ugreater_equal: | 2426 case Ugreater_equal: |
| 2315 sltu(scratch, rs, r2); | 2427 sltu(scratch, rs, r2); |
| 2316 addiu(scratch, scratch, -1); | 2428 daddiu(scratch, scratch, -1); |
| 2317 bltzal(scratch, offset); | 2429 bltzal(scratch, offset); |
| 2318 break; | 2430 break; |
| 2319 case Uless: | 2431 case Uless: |
| 2320 sltu(scratch, rs, r2); | 2432 sltu(scratch, rs, r2); |
| 2321 addiu(scratch, scratch, -1); | 2433 daddiu(scratch, scratch, -1); |
| 2322 bgezal(scratch, offset); | 2434 bgezal(scratch, offset); |
| 2323 break; | 2435 break; |
| 2324 case Uless_equal: | 2436 case Uless_equal: |
| 2325 sltu(scratch, r2, rs); | 2437 sltu(scratch, r2, rs); |
| 2326 addiu(scratch, scratch, -1); | 2438 daddiu(scratch, scratch, -1); |
| 2327 bltzal(scratch, offset); | 2439 bltzal(scratch, offset); |
| 2328 break; | 2440 break; |
| 2329 | 2441 |
| 2330 default: | 2442 default: |
| 2331 UNREACHABLE(); | 2443 UNREACHABLE(); |
| 2332 } | 2444 } |
| 2333 } | 2445 } |
| 2334 // Emit a nop in the branch delay slot if required. | 2446 // Emit a nop in the branch delay slot if required. |
| 2335 if (bdslot == PROTECT) | 2447 if (bdslot == PROTECT) |
| 2336 nop(); | 2448 nop(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2377 case ne: | 2489 case ne: |
| 2378 beq(rs, r2, 2); | 2490 beq(rs, r2, 2); |
| 2379 nop(); | 2491 nop(); |
| 2380 offset = shifted_branch_offset(L, false); | 2492 offset = shifted_branch_offset(L, false); |
| 2381 bal(offset); | 2493 bal(offset); |
| 2382 break; | 2494 break; |
| 2383 | 2495 |
| 2384 // Signed comparison. | 2496 // Signed comparison. |
| 2385 case greater: | 2497 case greater: |
| 2386 slt(scratch, r2, rs); | 2498 slt(scratch, r2, rs); |
| 2387 addiu(scratch, scratch, -1); | 2499 daddiu(scratch, scratch, -1); |
| 2388 offset = shifted_branch_offset(L, false); | 2500 offset = shifted_branch_offset(L, false); |
| 2389 bgezal(scratch, offset); | 2501 bgezal(scratch, offset); |
| 2390 break; | 2502 break; |
| 2391 case greater_equal: | 2503 case greater_equal: |
| 2392 slt(scratch, rs, r2); | 2504 slt(scratch, rs, r2); |
| 2393 addiu(scratch, scratch, -1); | 2505 daddiu(scratch, scratch, -1); |
| 2394 offset = shifted_branch_offset(L, false); | 2506 offset = shifted_branch_offset(L, false); |
| 2395 bltzal(scratch, offset); | 2507 bltzal(scratch, offset); |
| 2396 break; | 2508 break; |
| 2397 case less: | 2509 case less: |
| 2398 slt(scratch, rs, r2); | 2510 slt(scratch, rs, r2); |
| 2399 addiu(scratch, scratch, -1); | 2511 daddiu(scratch, scratch, -1); |
| 2400 offset = shifted_branch_offset(L, false); | 2512 offset = shifted_branch_offset(L, false); |
| 2401 bgezal(scratch, offset); | 2513 bgezal(scratch, offset); |
| 2402 break; | 2514 break; |
| 2403 case less_equal: | 2515 case less_equal: |
| 2404 slt(scratch, r2, rs); | 2516 slt(scratch, r2, rs); |
| 2405 addiu(scratch, scratch, -1); | 2517 daddiu(scratch, scratch, -1); |
| 2406 offset = shifted_branch_offset(L, false); | 2518 offset = shifted_branch_offset(L, false); |
| 2407 bltzal(scratch, offset); | 2519 bltzal(scratch, offset); |
| 2408 break; | 2520 break; |
| 2409 | 2521 |
| 2410 // Unsigned comparison. | 2522 // Unsigned comparison. |
| 2411 case Ugreater: | 2523 case Ugreater: |
| 2412 sltu(scratch, r2, rs); | 2524 sltu(scratch, r2, rs); |
| 2413 addiu(scratch, scratch, -1); | 2525 daddiu(scratch, scratch, -1); |
| 2414 offset = shifted_branch_offset(L, false); | 2526 offset = shifted_branch_offset(L, false); |
| 2415 bgezal(scratch, offset); | 2527 bgezal(scratch, offset); |
| 2416 break; | 2528 break; |
| 2417 case Ugreater_equal: | 2529 case Ugreater_equal: |
| 2418 sltu(scratch, rs, r2); | 2530 sltu(scratch, rs, r2); |
| 2419 addiu(scratch, scratch, -1); | 2531 daddiu(scratch, scratch, -1); |
| 2420 offset = shifted_branch_offset(L, false); | 2532 offset = shifted_branch_offset(L, false); |
| 2421 bltzal(scratch, offset); | 2533 bltzal(scratch, offset); |
| 2422 break; | 2534 break; |
| 2423 case Uless: | 2535 case Uless: |
| 2424 sltu(scratch, rs, r2); | 2536 sltu(scratch, rs, r2); |
| 2425 addiu(scratch, scratch, -1); | 2537 daddiu(scratch, scratch, -1); |
| 2426 offset = shifted_branch_offset(L, false); | 2538 offset = shifted_branch_offset(L, false); |
| 2427 bgezal(scratch, offset); | 2539 bgezal(scratch, offset); |
| 2428 break; | 2540 break; |
| 2429 case Uless_equal: | 2541 case Uless_equal: |
| 2430 sltu(scratch, r2, rs); | 2542 sltu(scratch, r2, rs); |
| 2431 addiu(scratch, scratch, -1); | 2543 daddiu(scratch, scratch, -1); |
| 2432 offset = shifted_branch_offset(L, false); | 2544 offset = shifted_branch_offset(L, false); |
| 2433 bltzal(scratch, offset); | 2545 bltzal(scratch, offset); |
| 2434 break; | 2546 break; |
| 2435 | 2547 |
| 2436 default: | 2548 default: |
| 2437 UNREACHABLE(); | 2549 UNREACHABLE(); |
| 2438 } | 2550 } |
| 2439 } | 2551 } |
| 2440 // Check that offset could actually hold on an int16_t. | 2552 // Check that offset could actually hold on an int16_t. |
| 2441 ASSERT(is_int16(offset)); | 2553 ASSERT(is_int16(offset)); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2551 } | 2663 } |
| 2552 | 2664 |
| 2553 | 2665 |
| 2554 int MacroAssembler::CallSize(Address target, | 2666 int MacroAssembler::CallSize(Address target, |
| 2555 RelocInfo::Mode rmode, | 2667 RelocInfo::Mode rmode, |
| 2556 Condition cond, | 2668 Condition cond, |
| 2557 Register rs, | 2669 Register rs, |
| 2558 const Operand& rt, | 2670 const Operand& rt, |
| 2559 BranchDelaySlot bd) { | 2671 BranchDelaySlot bd) { |
| 2560 int size = CallSize(t9, cond, rs, rt, bd); | 2672 int size = CallSize(t9, cond, rs, rt, bd); |
| 2561 return size + 2 * kInstrSize; | 2673 return size + 4 * kInstrSize; |
| 2562 } | 2674 } |
| 2563 | 2675 |
| 2564 | 2676 |
| 2565 void MacroAssembler::Call(Address target, | 2677 void MacroAssembler::Call(Address target, |
| 2566 RelocInfo::Mode rmode, | 2678 RelocInfo::Mode rmode, |
| 2567 Condition cond, | 2679 Condition cond, |
| 2568 Register rs, | 2680 Register rs, |
| 2569 const Operand& rt, | 2681 const Operand& rt, |
| 2570 BranchDelaySlot bd) { | 2682 BranchDelaySlot bd) { |
| 2571 BlockTrampolinePoolScope block_trampoline_pool(this); | 2683 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2572 Label start; | 2684 Label start; |
| 2573 bind(&start); | 2685 bind(&start); |
| 2574 int32_t target_int = reinterpret_cast<int32_t>(target); | 2686 int64_t target_int = reinterpret_cast<int64_t>(target); |
| 2575 // Must record previous source positions before the | 2687 // Must record previous source positions before the |
| 2576 // li() generates a new code target. | 2688 // li() generates a new code target. |
| 2577 positions_recorder()->WriteRecordedPositions(); | 2689 positions_recorder()->WriteRecordedPositions(); |
| 2578 li(t9, Operand(target_int, rmode), CONSTANT_SIZE); | 2690 li(t9, Operand(target_int, rmode), ADDRESS_LOAD); |
| 2579 Call(t9, cond, rs, rt, bd); | 2691 Call(t9, cond, rs, rt, bd); |
| 2580 ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd), | 2692 ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd), |
| 2581 SizeOfCodeGeneratedSince(&start)); | 2693 SizeOfCodeGeneratedSince(&start)); |
| 2582 } | 2694 } |
| 2583 | 2695 |
| 2584 | 2696 |
| 2585 int MacroAssembler::CallSize(Handle<Code> code, | 2697 int MacroAssembler::CallSize(Handle<Code> code, |
| 2586 RelocInfo::Mode rmode, | 2698 RelocInfo::Mode rmode, |
| 2587 TypeFeedbackId ast_id, | 2699 TypeFeedbackId ast_id, |
| 2588 Condition cond, | 2700 Condition cond, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2621 Register rs, | 2733 Register rs, |
| 2622 const Operand& rt, | 2734 const Operand& rt, |
| 2623 BranchDelaySlot bd) { | 2735 BranchDelaySlot bd) { |
| 2624 Jump(ra, cond, rs, rt, bd); | 2736 Jump(ra, cond, rs, rt, bd); |
| 2625 } | 2737 } |
| 2626 | 2738 |
| 2627 | 2739 |
| 2628 void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) { | 2740 void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) { |
| 2629 BlockTrampolinePoolScope block_trampoline_pool(this); | 2741 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2630 | 2742 |
| 2631 uint32_t imm28; | 2743 uint64_t imm28; |
| 2632 imm28 = jump_address(L); | 2744 imm28 = jump_address(L); |
| 2633 imm28 &= kImm28Mask; | 2745 imm28 &= kImm28Mask; |
| 2634 { BlockGrowBufferScope block_buf_growth(this); | 2746 { BlockGrowBufferScope block_buf_growth(this); |
| 2635 // Buffer growth (and relocation) must be blocked for internal references | 2747 // Buffer growth (and relocation) must be blocked for internal references |
| 2636 // until associated instructions are emitted and available to be patched. | 2748 // until associated instructions are emitted and available to be patched. |
| 2637 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); | 2749 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2638 j(imm28); | 2750 j(imm28); |
| 2639 } | 2751 } |
| 2640 // Emit a nop in the branch delay slot if required. | 2752 // Emit a nop in the branch delay slot if required. |
| 2641 if (bdslot == PROTECT) | 2753 if (bdslot == PROTECT) |
| 2642 nop(); | 2754 nop(); |
| 2643 } | 2755 } |
| 2644 | 2756 |
| 2645 | 2757 |
| 2646 void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) { | 2758 void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) { |
| 2647 BlockTrampolinePoolScope block_trampoline_pool(this); | 2759 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2648 | 2760 |
| 2649 uint32_t imm32; | 2761 uint64_t imm64; |
| 2650 imm32 = jump_address(L); | 2762 imm64 = jump_address(L); |
| 2651 { BlockGrowBufferScope block_buf_growth(this); | 2763 { BlockGrowBufferScope block_buf_growth(this); |
| 2652 // Buffer growth (and relocation) must be blocked for internal references | 2764 // Buffer growth (and relocation) must be blocked for internal references |
| 2653 // until associated instructions are emitted and available to be patched. | 2765 // until associated instructions are emitted and available to be patched. |
| 2654 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); | 2766 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2655 lui(at, (imm32 & kHiMask) >> kLuiShift); | 2767 li(at, Operand(imm64), ADDRESS_LOAD); |
| 2656 ori(at, at, (imm32 & kImm16Mask)); | |
| 2657 } | 2768 } |
| 2658 jr(at); | 2769 jr(at); |
| 2659 | 2770 |
| 2660 // Emit a nop in the branch delay slot if required. | 2771 // Emit a nop in the branch delay slot if required. |
| 2661 if (bdslot == PROTECT) | 2772 if (bdslot == PROTECT) |
| 2662 nop(); | 2773 nop(); |
| 2663 } | 2774 } |
| 2664 | 2775 |
| 2665 | 2776 |
| 2666 void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) { | 2777 void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) { |
| 2667 BlockTrampolinePoolScope block_trampoline_pool(this); | 2778 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2668 | 2779 |
| 2669 uint32_t imm32; | 2780 uint64_t imm64; |
| 2670 imm32 = jump_address(L); | 2781 imm64 = jump_address(L); |
| 2671 { BlockGrowBufferScope block_buf_growth(this); | 2782 { BlockGrowBufferScope block_buf_growth(this); |
| 2672 // Buffer growth (and relocation) must be blocked for internal references | 2783 // Buffer growth (and relocation) must be blocked for internal references |
| 2673 // until associated instructions are emitted and available to be patched. | 2784 // until associated instructions are emitted and available to be patched. |
| 2674 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); | 2785 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2675 lui(at, (imm32 & kHiMask) >> kLuiShift); | 2786 li(at, Operand(imm64), ADDRESS_LOAD); |
| 2676 ori(at, at, (imm32 & kImm16Mask)); | |
| 2677 } | 2787 } |
| 2678 jalr(at); | 2788 jalr(at); |
| 2679 | 2789 |
| 2680 // Emit a nop in the branch delay slot if required. | 2790 // Emit a nop in the branch delay slot if required. |
| 2681 if (bdslot == PROTECT) | 2791 if (bdslot == PROTECT) |
| 2682 nop(); | 2792 nop(); |
| 2683 } | 2793 } |
| 2684 | 2794 |
| 2685 | 2795 |
| 2686 void MacroAssembler::DropAndRet(int drop) { | 2796 void MacroAssembler::DropAndRet(int drop) { |
| 2687 Ret(USE_DELAY_SLOT); | 2797 Ret(USE_DELAY_SLOT); |
| 2688 addiu(sp, sp, drop * kPointerSize); | 2798 daddiu(sp, sp, drop * kPointerSize); |
| 2689 } | 2799 } |
| 2690 | 2800 |
| 2691 void MacroAssembler::DropAndRet(int drop, | 2801 void MacroAssembler::DropAndRet(int drop, |
| 2692 Condition cond, | 2802 Condition cond, |
| 2693 Register r1, | 2803 Register r1, |
| 2694 const Operand& r2) { | 2804 const Operand& r2) { |
| 2695 // Both Drop and Ret need to be conditional. | 2805 // Both Drop and Ret need to be conditional. |
| 2696 Label skip; | 2806 Label skip; |
| 2697 if (cond != cc_always) { | 2807 if (cond != cc_always) { |
| 2698 Branch(&skip, NegateCondition(cond), r1, r2); | 2808 Branch(&skip, NegateCondition(cond), r1, r2); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2714 if (count <= 0) { | 2824 if (count <= 0) { |
| 2715 return; | 2825 return; |
| 2716 } | 2826 } |
| 2717 | 2827 |
| 2718 Label skip; | 2828 Label skip; |
| 2719 | 2829 |
| 2720 if (cond != al) { | 2830 if (cond != al) { |
| 2721 Branch(&skip, NegateCondition(cond), reg, op); | 2831 Branch(&skip, NegateCondition(cond), reg, op); |
| 2722 } | 2832 } |
| 2723 | 2833 |
| 2724 addiu(sp, sp, count * kPointerSize); | 2834 daddiu(sp, sp, count * kPointerSize); |
| 2725 | 2835 |
| 2726 if (cond != al) { | 2836 if (cond != al) { |
| 2727 bind(&skip); | 2837 bind(&skip); |
| 2728 } | 2838 } |
| 2729 } | 2839 } |
| 2730 | 2840 |
| 2731 | 2841 |
| 2732 | 2842 |
| 2733 void MacroAssembler::Swap(Register reg1, | 2843 void MacroAssembler::Swap(Register reg1, |
| 2734 Register reg2, | 2844 Register reg2, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2749 BranchAndLink(target); | 2859 BranchAndLink(target); |
| 2750 } | 2860 } |
| 2751 | 2861 |
| 2752 | 2862 |
| 2753 void MacroAssembler::Push(Handle<Object> handle) { | 2863 void MacroAssembler::Push(Handle<Object> handle) { |
| 2754 li(at, Operand(handle)); | 2864 li(at, Operand(handle)); |
| 2755 push(at); | 2865 push(at); |
| 2756 } | 2866 } |
| 2757 | 2867 |
| 2758 | 2868 |
| 2869 void MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) { |
| 2870 ASSERT(!src.is(scratch)); |
| 2871 mov(scratch, src); |
| 2872 dsrl32(src, src, 0); |
| 2873 dsll32(src, src, 0); |
| 2874 push(src); |
| 2875 dsll32(scratch, scratch, 0); |
| 2876 push(scratch); |
| 2877 } |
| 2878 |
| 2879 |
| 2880 void MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) { |
| 2881 ASSERT(!dst.is(scratch)); |
| 2882 pop(scratch); |
| 2883 dsrl32(scratch, scratch, 0); |
| 2884 pop(dst); |
| 2885 dsrl32(dst, dst, 0); |
| 2886 dsll32(dst, dst, 0); |
| 2887 or_(dst, dst, scratch); |
| 2888 } |
| 2889 |
| 2890 |
| 2759 void MacroAssembler::DebugBreak() { | 2891 void MacroAssembler::DebugBreak() { |
| 2760 PrepareCEntryArgs(0); | 2892 PrepareCEntryArgs(0); |
| 2761 PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate())); | 2893 PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate())); |
| 2762 CEntryStub ces(isolate(), 1); | 2894 CEntryStub ces(isolate(), 1); |
| 2763 ASSERT(AllowThisStubCall(&ces)); | 2895 ASSERT(AllowThisStubCall(&ces)); |
| 2764 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 2896 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| 2765 } | 2897 } |
| 2766 | 2898 |
| 2767 | 2899 |
| 2768 // --------------------------------------------------------------------------- | 2900 // --------------------------------------------------------------------------- |
| 2769 // Exception handling. | 2901 // Exception handling. |
| 2770 | 2902 |
| 2771 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, | 2903 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, |
| 2772 int handler_index) { | 2904 int handler_index) { |
| 2773 // Adjust this code if not the case. | 2905 // Adjust this code if not the case. |
| 2774 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2906 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 2775 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 2907 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 2776 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); | 2908 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
| 2777 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); | 2909 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
| 2778 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); | 2910 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
| 2779 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); | 2911 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
| 2780 | 2912 |
| 2781 // For the JSEntry handler, we must preserve a0-a3 and s0. | 2913 // For the JSEntry handler, we must preserve a0-a3 and s0. |
| 2782 // t1-t3 are available. We will build up the handler from the bottom by | 2914 // a5-a7 are available. We will build up the handler from the bottom by |
| 2783 // pushing on the stack. | 2915 // pushing on the stack. |
| 2784 // Set up the code object (t1) and the state (t2) for pushing. | 2916 // Set up the code object (a5) and the state (a6) for pushing. |
| 2785 unsigned state = | 2917 unsigned state = |
| 2786 StackHandler::IndexField::encode(handler_index) | | 2918 StackHandler::IndexField::encode(handler_index) | |
| 2787 StackHandler::KindField::encode(kind); | 2919 StackHandler::KindField::encode(kind); |
| 2788 li(t1, Operand(CodeObject()), CONSTANT_SIZE); | 2920 li(a5, Operand(CodeObject()), CONSTANT_SIZE); |
| 2789 li(t2, Operand(state)); | 2921 li(a6, Operand(state)); |
| 2790 | 2922 |
| 2791 // Push the frame pointer, context, state, and code object. | 2923 // Push the frame pointer, context, state, and code object. |
| 2792 if (kind == StackHandler::JS_ENTRY) { | 2924 if (kind == StackHandler::JS_ENTRY) { |
| 2793 ASSERT_EQ(Smi::FromInt(0), 0); | 2925 ASSERT_EQ(Smi::FromInt(0), 0); |
| 2794 // The second zero_reg indicates no context. | 2926 // The second zero_reg indicates no context. |
| 2795 // The first zero_reg is the NULL frame pointer. | 2927 // The first zero_reg is the NULL frame pointer. |
| 2796 // The operands are reversed to match the order of MultiPush/Pop. | 2928 // The operands are reversed to match the order of MultiPush/Pop. |
| 2797 Push(zero_reg, zero_reg, t2, t1); | 2929 Push(zero_reg, zero_reg, a6, a5); |
| 2798 } else { | 2930 } else { |
| 2799 MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit()); | 2931 MultiPush(a5.bit() | a6.bit() | cp.bit() | fp.bit()); |
| 2800 } | 2932 } |
| 2801 | 2933 |
| 2802 // Link the current handler as the next handler. | 2934 // Link the current handler as the next handler. |
| 2803 li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 2935 li(a6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
| 2804 lw(t1, MemOperand(t2)); | 2936 ld(a5, MemOperand(a6)); |
| 2805 push(t1); | 2937 push(a5); |
| 2806 // Set this new handler as the current one. | 2938 // Set this new handler as the current one. |
| 2807 sw(sp, MemOperand(t2)); | 2939 sd(sp, MemOperand(a6)); |
| 2808 } | 2940 } |
| 2809 | 2941 |
| 2810 | 2942 |
| 2811 void MacroAssembler::PopTryHandler() { | 2943 void MacroAssembler::PopTryHandler() { |
| 2812 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 2944 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 2813 pop(a1); | 2945 pop(a1); |
| 2814 Addu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 2946 Daddu(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
| 2815 li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 2947 li(at, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
| 2816 sw(a1, MemOperand(at)); | 2948 sd(a1, MemOperand(at)); |
| 2817 } | 2949 } |
| 2818 | 2950 |
| 2819 | 2951 |
| 2820 void MacroAssembler::JumpToHandlerEntry() { | 2952 void MacroAssembler::JumpToHandlerEntry() { |
| 2821 // Compute the handler entry address and jump to it. The handler table is | 2953 // Compute the handler entry address and jump to it. The handler table is |
| 2822 // a fixed array of (smi-tagged) code offsets. | 2954 // a fixed array of (smi-tagged) code offsets. |
| 2823 // v0 = exception, a1 = code object, a2 = state. | 2955 // v0 = exception, a1 = code object, a2 = state. |
| 2824 lw(a3, FieldMemOperand(a1, Code::kHandlerTableOffset)); // Handler table. | 2956 Uld(a3, FieldMemOperand(a1, Code::kHandlerTableOffset)); |
| 2825 Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 2957 Daddu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 2826 srl(a2, a2, StackHandler::kKindWidth); // Handler index. | 2958 dsrl(a2, a2, StackHandler::kKindWidth); // Handler index. |
| 2827 sll(a2, a2, kPointerSizeLog2); | 2959 dsll(a2, a2, kPointerSizeLog2); |
| 2828 Addu(a2, a3, a2); | 2960 Daddu(a2, a3, a2); |
| 2829 lw(a2, MemOperand(a2)); // Smi-tagged offset. | 2961 ld(a2, MemOperand(a2)); // Smi-tagged offset. |
| 2830 Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start. | 2962 Daddu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start. |
| 2831 sra(t9, a2, kSmiTagSize); | 2963 dsra32(t9, a2, 0); |
| 2832 Addu(t9, t9, a1); | 2964 Daddu(t9, t9, a1); |
| 2833 Jump(t9); // Jump. | 2965 Jump(t9); // Jump. |
| 2834 } | 2966 } |
| 2835 | 2967 |
| 2836 | 2968 |
| 2837 void MacroAssembler::Throw(Register value) { | 2969 void MacroAssembler::Throw(Register value) { |
| 2838 // Adjust this code if not the case. | 2970 // Adjust this code if not the case. |
| 2839 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2971 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 2840 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); | 2972 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); |
| 2841 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); | 2973 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
| 2842 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); | 2974 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
| 2843 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); | 2975 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
| 2844 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); | 2976 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
| 2845 | 2977 |
| 2846 // The exception is expected in v0. | 2978 // The exception is expected in v0. |
| 2847 Move(v0, value); | 2979 Move(v0, value); |
| 2848 | 2980 |
| 2849 // Drop the stack pointer to the top of the top handler. | 2981 // Drop the stack pointer to the top of the top handler. |
| 2850 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, | 2982 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, |
| 2851 isolate()))); | 2983 isolate()))); |
| 2852 lw(sp, MemOperand(a3)); | 2984 ld(sp, MemOperand(a3)); |
| 2853 | 2985 |
| 2854 // Restore the next handler. | 2986 // Restore the next handler. |
| 2855 pop(a2); | 2987 pop(a2); |
| 2856 sw(a2, MemOperand(a3)); | 2988 sd(a2, MemOperand(a3)); |
| 2857 | 2989 |
| 2858 // Get the code object (a1) and state (a2). Restore the context and frame | 2990 // Get the code object (a1) and state (a2). Restore the context and frame |
| 2859 // pointer. | 2991 // pointer. |
| 2860 MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit()); | 2992 MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit()); |
| 2861 | 2993 |
| 2862 // If the handler is a JS frame, restore the context to the frame. | 2994 // If the handler is a JS frame, restore the context to the frame. |
| 2863 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp | 2995 // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp |
| 2864 // or cp. | 2996 // or cp. |
| 2865 Label done; | 2997 Label done; |
| 2866 Branch(&done, eq, cp, Operand(zero_reg)); | 2998 Branch(&done, eq, cp, Operand(zero_reg)); |
| 2867 sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2999 sd(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2868 bind(&done); | 3000 bind(&done); |
| 2869 | 3001 |
| 2870 JumpToHandlerEntry(); | 3002 JumpToHandlerEntry(); |
| 2871 } | 3003 } |
| 2872 | 3004 |
| 2873 | 3005 |
| 2874 void MacroAssembler::ThrowUncatchable(Register value) { | 3006 void MacroAssembler::ThrowUncatchable(Register value) { |
| 2875 // Adjust this code if not the case. | 3007 // Adjust this code if not the case. |
| 2876 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 3008 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
| 2877 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 3009 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
| 2878 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); | 3010 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
| 2879 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); | 3011 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
| 2880 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); | 3012 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
| 2881 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); | 3013 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
| 2882 | 3014 |
| 2883 // The exception is expected in v0. | 3015 // The exception is expected in v0. |
| 2884 if (!value.is(v0)) { | 3016 if (!value.is(v0)) { |
| 2885 mov(v0, value); | 3017 mov(v0, value); |
| 2886 } | 3018 } |
| 2887 // Drop the stack pointer to the top of the top stack handler. | 3019 // Drop the stack pointer to the top of the top stack handler. |
| 2888 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 3020 li(a3, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
| 2889 lw(sp, MemOperand(a3)); | 3021 ld(sp, MemOperand(a3)); |
| 2890 | 3022 |
| 2891 // Unwind the handlers until the ENTRY handler is found. | 3023 // Unwind the handlers until the ENTRY handler is found. |
| 2892 Label fetch_next, check_kind; | 3024 Label fetch_next, check_kind; |
| 2893 jmp(&check_kind); | 3025 jmp(&check_kind); |
| 2894 bind(&fetch_next); | 3026 bind(&fetch_next); |
| 2895 lw(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); | 3027 ld(sp, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
| 2896 | 3028 |
| 2897 bind(&check_kind); | 3029 bind(&check_kind); |
| 2898 STATIC_ASSERT(StackHandler::JS_ENTRY == 0); | 3030 STATIC_ASSERT(StackHandler::JS_ENTRY == 0); |
| 2899 lw(a2, MemOperand(sp, StackHandlerConstants::kStateOffset)); | 3031 ld(a2, MemOperand(sp, StackHandlerConstants::kStateOffset)); |
| 2900 And(a2, a2, Operand(StackHandler::KindField::kMask)); | 3032 And(a2, a2, Operand(StackHandler::KindField::kMask)); |
| 2901 Branch(&fetch_next, ne, a2, Operand(zero_reg)); | 3033 Branch(&fetch_next, ne, a2, Operand(zero_reg)); |
| 2902 | 3034 |
| 2903 // Set the top handler address to next handler past the top ENTRY handler. | 3035 // Set the top handler address to next handler past the top ENTRY handler. |
| 2904 pop(a2); | 3036 pop(a2); |
| 2905 sw(a2, MemOperand(a3)); | 3037 sd(a2, MemOperand(a3)); |
| 2906 | 3038 |
| 2907 // Get the code object (a1) and state (a2). Clear the context and frame | 3039 // Get the code object (a1) and state (a2). Clear the context and frame |
| 2908 // pointer (0 was saved in the handler). | 3040 // pointer (0 was saved in the handler). |
| 2909 MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit()); | 3041 MultiPop(a1.bit() | a2.bit() | cp.bit() | fp.bit()); |
| 2910 | 3042 |
| 2911 JumpToHandlerEntry(); | 3043 JumpToHandlerEntry(); |
| 2912 } | 3044 } |
| 2913 | 3045 |
| 2914 | 3046 |
| 2915 void MacroAssembler::Allocate(int object_size, | 3047 void MacroAssembler::Allocate(int object_size, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2934 ASSERT(!result.is(scratch2)); | 3066 ASSERT(!result.is(scratch2)); |
| 2935 ASSERT(!scratch1.is(scratch2)); | 3067 ASSERT(!scratch1.is(scratch2)); |
| 2936 ASSERT(!scratch1.is(t9)); | 3068 ASSERT(!scratch1.is(t9)); |
| 2937 ASSERT(!scratch2.is(t9)); | 3069 ASSERT(!scratch2.is(t9)); |
| 2938 ASSERT(!result.is(t9)); | 3070 ASSERT(!result.is(t9)); |
| 2939 | 3071 |
| 2940 // Make object size into bytes. | 3072 // Make object size into bytes. |
| 2941 if ((flags & SIZE_IN_WORDS) != 0) { | 3073 if ((flags & SIZE_IN_WORDS) != 0) { |
| 2942 object_size *= kPointerSize; | 3074 object_size *= kPointerSize; |
| 2943 } | 3075 } |
| 2944 ASSERT_EQ(0, object_size & kObjectAlignmentMask); | 3076 ASSERT(0 == (object_size & kObjectAlignmentMask)); |
| 2945 | 3077 |
| 2946 // Check relative positions of allocation top and limit addresses. | 3078 // Check relative positions of allocation top and limit addresses. |
| 2947 // ARM adds additional checks to make sure the ldm instruction can be | 3079 // ARM adds additional checks to make sure the ldm instruction can be |
| 2948 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3080 // used. On MIPS we don't have ldm so we don't need additional checks either. |
| 2949 ExternalReference allocation_top = | 3081 ExternalReference allocation_top = |
| 2950 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3082 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
| 2951 ExternalReference allocation_limit = | 3083 ExternalReference allocation_limit = |
| 2952 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3084 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
| 2953 | 3085 |
| 2954 intptr_t top = | 3086 intptr_t top = |
| 2955 reinterpret_cast<intptr_t>(allocation_top.address()); | 3087 reinterpret_cast<intptr_t>(allocation_top.address()); |
| 2956 intptr_t limit = | 3088 intptr_t limit = |
| 2957 reinterpret_cast<intptr_t>(allocation_limit.address()); | 3089 reinterpret_cast<intptr_t>(allocation_limit.address()); |
| 2958 ASSERT((limit - top) == kPointerSize); | 3090 ASSERT((limit - top) == kPointerSize); |
| 2959 | 3091 |
| 2960 // Set up allocation top address and object size registers. | 3092 // Set up allocation top address and object size registers. |
| 2961 Register topaddr = scratch1; | 3093 Register topaddr = scratch1; |
| 2962 li(topaddr, Operand(allocation_top)); | 3094 li(topaddr, Operand(allocation_top)); |
| 2963 | 3095 |
| 2964 // This code stores a temporary value in t9. | 3096 // This code stores a temporary value in t9. |
| 2965 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3097 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
| 2966 // Load allocation top into result and allocation limit into t9. | 3098 // Load allocation top into result and allocation limit into t9. |
| 2967 lw(result, MemOperand(topaddr)); | 3099 ld(result, MemOperand(topaddr)); |
| 2968 lw(t9, MemOperand(topaddr, kPointerSize)); | 3100 ld(t9, MemOperand(topaddr, kPointerSize)); |
| 2969 } else { | 3101 } else { |
| 2970 if (emit_debug_code()) { | 3102 if (emit_debug_code()) { |
| 2971 // Assert that result actually contains top on entry. t9 is used | 3103 // Assert that result actually contains top on entry. t9 is used |
| 2972 // immediately below so this use of t9 does not cause difference with | 3104 // immediately below so this use of t9 does not cause difference with |
| 2973 // respect to register content between debug and release mode. | 3105 // respect to register content between debug and release mode. |
| 2974 lw(t9, MemOperand(topaddr)); | 3106 ld(t9, MemOperand(topaddr)); |
| 2975 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | 3107 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); |
| 2976 } | 3108 } |
| 2977 // Load allocation limit into t9. Result already contains allocation top. | 3109 // Load allocation limit into t9. Result already contains allocation top. |
| 2978 lw(t9, MemOperand(topaddr, limit - top)); | 3110 ld(t9, MemOperand(topaddr, limit - top)); |
| 2979 } | 3111 } |
| 2980 | 3112 |
| 2981 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 3113 ASSERT(kPointerSize == kDoubleSize); |
| 2982 // Align the next allocation. Storing the filler map without checking top is | 3114 if (emit_debug_code()) { |
| 2983 // safe in new-space because the limit of the heap is aligned there. | 3115 And(at, result, Operand(kDoubleAlignmentMask)); |
| 2984 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 3116 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); |
| 2985 ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | |
| 2986 And(scratch2, result, Operand(kDoubleAlignmentMask)); | |
| 2987 Label aligned; | |
| 2988 Branch(&aligned, eq, scratch2, Operand(zero_reg)); | |
| 2989 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { | |
| 2990 Branch(gc_required, Ugreater_equal, result, Operand(t9)); | |
| 2991 } | |
| 2992 li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | |
| 2993 sw(scratch2, MemOperand(result)); | |
| 2994 Addu(result, result, Operand(kDoubleSize / 2)); | |
| 2995 bind(&aligned); | |
| 2996 } | 3117 } |
| 2997 | 3118 |
| 2998 // Calculate new top and bail out if new space is exhausted. Use result | 3119 // Calculate new top and bail out if new space is exhausted. Use result |
| 2999 // to calculate the new top. | 3120 // to calculate the new top. |
| 3000 Addu(scratch2, result, Operand(object_size)); | 3121 Daddu(scratch2, result, Operand(object_size)); |
| 3001 Branch(gc_required, Ugreater, scratch2, Operand(t9)); | 3122 Branch(gc_required, Ugreater, scratch2, Operand(t9)); |
| 3002 sw(scratch2, MemOperand(topaddr)); | 3123 sd(scratch2, MemOperand(topaddr)); |
| 3003 | 3124 |
| 3004 // Tag object if requested. | 3125 // Tag object if requested. |
| 3005 if ((flags & TAG_OBJECT) != 0) { | 3126 if ((flags & TAG_OBJECT) != 0) { |
| 3006 Addu(result, result, Operand(kHeapObjectTag)); | 3127 Daddu(result, result, Operand(kHeapObjectTag)); |
| 3007 } | 3128 } |
| 3008 } | 3129 } |
| 3009 | 3130 |
| 3010 | 3131 |
| 3011 void MacroAssembler::Allocate(Register object_size, | 3132 void MacroAssembler::Allocate(Register object_size, |
| 3012 Register result, | 3133 Register result, |
| 3013 Register scratch1, | 3134 Register scratch1, |
| 3014 Register scratch2, | 3135 Register scratch2, |
| 3015 Label* gc_required, | 3136 Label* gc_required, |
| 3016 AllocationFlags flags) { | 3137 AllocationFlags flags) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3044 reinterpret_cast<intptr_t>(allocation_limit.address()); | 3165 reinterpret_cast<intptr_t>(allocation_limit.address()); |
| 3045 ASSERT((limit - top) == kPointerSize); | 3166 ASSERT((limit - top) == kPointerSize); |
| 3046 | 3167 |
| 3047 // Set up allocation top address and object size registers. | 3168 // Set up allocation top address and object size registers. |
| 3048 Register topaddr = scratch1; | 3169 Register topaddr = scratch1; |
| 3049 li(topaddr, Operand(allocation_top)); | 3170 li(topaddr, Operand(allocation_top)); |
| 3050 | 3171 |
| 3051 // This code stores a temporary value in t9. | 3172 // This code stores a temporary value in t9. |
| 3052 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3173 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
| 3053 // Load allocation top into result and allocation limit into t9. | 3174 // Load allocation top into result and allocation limit into t9. |
| 3054 lw(result, MemOperand(topaddr)); | 3175 ld(result, MemOperand(topaddr)); |
| 3055 lw(t9, MemOperand(topaddr, kPointerSize)); | 3176 ld(t9, MemOperand(topaddr, kPointerSize)); |
| 3056 } else { | 3177 } else { |
| 3057 if (emit_debug_code()) { | 3178 if (emit_debug_code()) { |
| 3058 // Assert that result actually contains top on entry. t9 is used | 3179 // Assert that result actually contains top on entry. t9 is used |
| 3059 // immediately below so this use of t9 does not cause difference with | 3180 // immediately below so this use of t9 does not cause difference with |
| 3060 // respect to register content between debug and release mode. | 3181 // respect to register content between debug and release mode. |
| 3061 lw(t9, MemOperand(topaddr)); | 3182 ld(t9, MemOperand(topaddr)); |
| 3062 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | 3183 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); |
| 3063 } | 3184 } |
| 3064 // Load allocation limit into t9. Result already contains allocation top. | 3185 // Load allocation limit into t9. Result already contains allocation top. |
| 3065 lw(t9, MemOperand(topaddr, limit - top)); | 3186 ld(t9, MemOperand(topaddr, limit - top)); |
| 3066 } | 3187 } |
| 3067 | 3188 |
| 3068 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 3189 ASSERT(kPointerSize == kDoubleSize); |
| 3069 // Align the next allocation. Storing the filler map without checking top is | 3190 if (emit_debug_code()) { |
| 3070 // safe in new-space because the limit of the heap is aligned there. | 3191 And(at, result, Operand(kDoubleAlignmentMask)); |
| 3071 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 3192 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); |
| 3072 ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | |
| 3073 And(scratch2, result, Operand(kDoubleAlignmentMask)); | |
| 3074 Label aligned; | |
| 3075 Branch(&aligned, eq, scratch2, Operand(zero_reg)); | |
| 3076 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { | |
| 3077 Branch(gc_required, Ugreater_equal, result, Operand(t9)); | |
| 3078 } | |
| 3079 li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | |
| 3080 sw(scratch2, MemOperand(result)); | |
| 3081 Addu(result, result, Operand(kDoubleSize / 2)); | |
| 3082 bind(&aligned); | |
| 3083 } | 3193 } |
| 3084 | 3194 |
| 3085 // Calculate new top and bail out if new space is exhausted. Use result | 3195 // Calculate new top and bail out if new space is exhausted. Use result |
| 3086 // to calculate the new top. Object size may be in words so a shift is | 3196 // to calculate the new top. Object size may be in words so a shift is |
| 3087 // required to get the number of bytes. | 3197 // required to get the number of bytes. |
| 3088 if ((flags & SIZE_IN_WORDS) != 0) { | 3198 if ((flags & SIZE_IN_WORDS) != 0) { |
| 3089 sll(scratch2, object_size, kPointerSizeLog2); | 3199 dsll(scratch2, object_size, kPointerSizeLog2); |
| 3090 Addu(scratch2, result, scratch2); | 3200 Daddu(scratch2, result, scratch2); |
| 3091 } else { | 3201 } else { |
| 3092 Addu(scratch2, result, Operand(object_size)); | 3202 Daddu(scratch2, result, Operand(object_size)); |
| 3093 } | 3203 } |
| 3094 Branch(gc_required, Ugreater, scratch2, Operand(t9)); | 3204 Branch(gc_required, Ugreater, scratch2, Operand(t9)); |
| 3095 | 3205 |
| 3096 // Update allocation top. result temporarily holds the new top. | 3206 // Update allocation top. result temporarily holds the new top. |
| 3097 if (emit_debug_code()) { | 3207 if (emit_debug_code()) { |
| 3098 And(t9, scratch2, Operand(kObjectAlignmentMask)); | 3208 And(t9, scratch2, Operand(kObjectAlignmentMask)); |
| 3099 Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg)); | 3209 Check(eq, kUnalignedAllocationInNewSpace, t9, Operand(zero_reg)); |
| 3100 } | 3210 } |
| 3101 sw(scratch2, MemOperand(topaddr)); | 3211 sd(scratch2, MemOperand(topaddr)); |
| 3102 | 3212 |
| 3103 // Tag object if requested. | 3213 // Tag object if requested. |
| 3104 if ((flags & TAG_OBJECT) != 0) { | 3214 if ((flags & TAG_OBJECT) != 0) { |
| 3105 Addu(result, result, Operand(kHeapObjectTag)); | 3215 Daddu(result, result, Operand(kHeapObjectTag)); |
| 3106 } | 3216 } |
| 3107 } | 3217 } |
| 3108 | 3218 |
| 3109 | 3219 |
| 3110 void MacroAssembler::UndoAllocationInNewSpace(Register object, | 3220 void MacroAssembler::UndoAllocationInNewSpace(Register object, |
| 3111 Register scratch) { | 3221 Register scratch) { |
| 3112 ExternalReference new_space_allocation_top = | 3222 ExternalReference new_space_allocation_top = |
| 3113 ExternalReference::new_space_allocation_top_address(isolate()); | 3223 ExternalReference::new_space_allocation_top_address(isolate()); |
| 3114 | 3224 |
| 3115 // Make sure the object has no tag before resetting top. | 3225 // Make sure the object has no tag before resetting top. |
| 3116 And(object, object, Operand(~kHeapObjectTagMask)); | 3226 And(object, object, Operand(~kHeapObjectTagMask)); |
| 3117 #ifdef DEBUG | 3227 #ifdef DEBUG |
| 3118 // Check that the object un-allocated is below the current top. | 3228 // Check that the object un-allocated is below the current top. |
| 3119 li(scratch, Operand(new_space_allocation_top)); | 3229 li(scratch, Operand(new_space_allocation_top)); |
| 3120 lw(scratch, MemOperand(scratch)); | 3230 ld(scratch, MemOperand(scratch)); |
| 3121 Check(less, kUndoAllocationOfNonAllocatedMemory, | 3231 Check(less, kUndoAllocationOfNonAllocatedMemory, |
| 3122 object, Operand(scratch)); | 3232 object, Operand(scratch)); |
| 3123 #endif | 3233 #endif |
| 3124 // Write the address of the object to un-allocate as the current top. | 3234 // Write the address of the object to un-allocate as the current top. |
| 3125 li(scratch, Operand(new_space_allocation_top)); | 3235 li(scratch, Operand(new_space_allocation_top)); |
| 3126 sw(object, MemOperand(scratch)); | 3236 sd(object, MemOperand(scratch)); |
| 3127 } | 3237 } |
| 3128 | 3238 |
| 3129 | 3239 |
| 3130 void MacroAssembler::AllocateTwoByteString(Register result, | 3240 void MacroAssembler::AllocateTwoByteString(Register result, |
| 3131 Register length, | 3241 Register length, |
| 3132 Register scratch1, | 3242 Register scratch1, |
| 3133 Register scratch2, | 3243 Register scratch2, |
| 3134 Register scratch3, | 3244 Register scratch3, |
| 3135 Label* gc_required) { | 3245 Label* gc_required) { |
| 3136 // Calculate the number of bytes needed for the characters in the string while | 3246 // Calculate the number of bytes needed for the characters in the string while |
| 3137 // observing object alignment. | 3247 // observing object alignment. |
| 3138 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3248 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
| 3139 sll(scratch1, length, 1); // Length in bytes, not chars. | 3249 dsll(scratch1, length, 1); // Length in bytes, not chars. |
| 3140 addiu(scratch1, scratch1, | 3250 daddiu(scratch1, scratch1, |
| 3141 kObjectAlignmentMask + SeqTwoByteString::kHeaderSize); | 3251 kObjectAlignmentMask + SeqTwoByteString::kHeaderSize); |
| 3142 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); | 3252 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); |
| 3143 | 3253 |
| 3144 // Allocate two-byte string in new space. | 3254 // Allocate two-byte string in new space. |
| 3145 Allocate(scratch1, | 3255 Allocate(scratch1, |
| 3146 result, | 3256 result, |
| 3147 scratch2, | 3257 scratch2, |
| 3148 scratch3, | 3258 scratch3, |
| 3149 gc_required, | 3259 gc_required, |
| 3150 TAG_OBJECT); | 3260 TAG_OBJECT); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3161 void MacroAssembler::AllocateAsciiString(Register result, | 3271 void MacroAssembler::AllocateAsciiString(Register result, |
| 3162 Register length, | 3272 Register length, |
| 3163 Register scratch1, | 3273 Register scratch1, |
| 3164 Register scratch2, | 3274 Register scratch2, |
| 3165 Register scratch3, | 3275 Register scratch3, |
| 3166 Label* gc_required) { | 3276 Label* gc_required) { |
| 3167 // Calculate the number of bytes needed for the characters in the string | 3277 // Calculate the number of bytes needed for the characters in the string |
| 3168 // while observing object alignment. | 3278 // while observing object alignment. |
| 3169 ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3279 ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
| 3170 ASSERT(kCharSize == 1); | 3280 ASSERT(kCharSize == 1); |
| 3171 addiu(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize); | 3281 daddiu(scratch1, length, |
| 3282 kObjectAlignmentMask + SeqOneByteString::kHeaderSize); |
| 3172 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); | 3283 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); |
| 3173 | 3284 |
| 3174 // Allocate ASCII string in new space. | 3285 // Allocate ASCII string in new space. |
| 3175 Allocate(scratch1, | 3286 Allocate(scratch1, |
| 3176 result, | 3287 result, |
| 3177 scratch2, | 3288 scratch2, |
| 3178 scratch3, | 3289 scratch3, |
| 3179 gc_required, | 3290 gc_required, |
| 3180 TAG_OBJECT); | 3291 TAG_OBJECT); |
| 3181 | 3292 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3267 } | 3378 } |
| 3268 | 3379 |
| 3269 | 3380 |
| 3270 // Allocates a heap number or jumps to the label if the young space is full and | 3381 // Allocates a heap number or jumps to the label if the young space is full and |
| 3271 // a scavenge is needed. | 3382 // a scavenge is needed. |
| 3272 void MacroAssembler::AllocateHeapNumber(Register result, | 3383 void MacroAssembler::AllocateHeapNumber(Register result, |
| 3273 Register scratch1, | 3384 Register scratch1, |
| 3274 Register scratch2, | 3385 Register scratch2, |
| 3275 Register heap_number_map, | 3386 Register heap_number_map, |
| 3276 Label* need_gc, | 3387 Label* need_gc, |
| 3277 TaggingMode tagging_mode, | 3388 TaggingMode tagging_mode) { |
| 3278 MutableMode mode) { | |
| 3279 // Allocate an object in the heap for the heap number and tag it as a heap | 3389 // Allocate an object in the heap for the heap number and tag it as a heap |
| 3280 // object. | 3390 // object. |
| 3281 Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc, | 3391 Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc, |
| 3282 tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS); | 3392 tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS); |
| 3283 | 3393 |
| 3284 Heap::RootListIndex map_index = mode == MUTABLE | |
| 3285 ? Heap::kMutableHeapNumberMapRootIndex | |
| 3286 : Heap::kHeapNumberMapRootIndex; | |
| 3287 AssertIsRoot(heap_number_map, map_index); | |
| 3288 | |
| 3289 // Store heap number map in the allocated object. | 3394 // Store heap number map in the allocated object. |
| 3395 AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 3290 if (tagging_mode == TAG_RESULT) { | 3396 if (tagging_mode == TAG_RESULT) { |
| 3291 sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); | 3397 sd(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); |
| 3292 } else { | 3398 } else { |
| 3293 sw(heap_number_map, MemOperand(result, HeapObject::kMapOffset)); | 3399 sd(heap_number_map, MemOperand(result, HeapObject::kMapOffset)); |
| 3294 } | 3400 } |
| 3295 } | 3401 } |
| 3296 | 3402 |
| 3297 | 3403 |
| 3298 void MacroAssembler::AllocateHeapNumberWithValue(Register result, | 3404 void MacroAssembler::AllocateHeapNumberWithValue(Register result, |
| 3299 FPURegister value, | 3405 FPURegister value, |
| 3300 Register scratch1, | 3406 Register scratch1, |
| 3301 Register scratch2, | 3407 Register scratch2, |
| 3302 Label* gc_required) { | 3408 Label* gc_required) { |
| 3303 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | 3409 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3319 // Find a temp register in temps list. | 3425 // Find a temp register in temps list. |
| 3320 for (int i = 0; i < kNumRegisters; i++) { | 3426 for (int i = 0; i < kNumRegisters; i++) { |
| 3321 if ((temps & (1 << i)) != 0) { | 3427 if ((temps & (1 << i)) != 0) { |
| 3322 tmp.code_ = i; | 3428 tmp.code_ = i; |
| 3323 break; | 3429 break; |
| 3324 } | 3430 } |
| 3325 } | 3431 } |
| 3326 ASSERT(!tmp.is(no_reg)); | 3432 ASSERT(!tmp.is(no_reg)); |
| 3327 | 3433 |
| 3328 for (int i = 0; i < field_count; i++) { | 3434 for (int i = 0; i < field_count; i++) { |
| 3329 lw(tmp, FieldMemOperand(src, i * kPointerSize)); | 3435 ld(tmp, FieldMemOperand(src, i * kPointerSize)); |
| 3330 sw(tmp, FieldMemOperand(dst, i * kPointerSize)); | 3436 sd(tmp, FieldMemOperand(dst, i * kPointerSize)); |
| 3331 } | 3437 } |
| 3332 } | 3438 } |
| 3333 | 3439 |
| 3334 | 3440 |
| 3335 void MacroAssembler::CopyBytes(Register src, | 3441 void MacroAssembler::CopyBytes(Register src, |
| 3336 Register dst, | 3442 Register dst, |
| 3337 Register length, | 3443 Register length, |
| 3338 Register scratch) { | 3444 Register scratch) { |
| 3339 Label align_loop_1, word_loop, byte_loop, byte_loop_1, done; | 3445 Label align_loop_1, word_loop, byte_loop, byte_loop_1, done; |
| 3340 | 3446 |
| 3341 // Align src before copying in word size chunks. | 3447 // Align src before copying in word size chunks. |
| 3342 Branch(&byte_loop, le, length, Operand(kPointerSize)); | 3448 Branch(&byte_loop, le, length, Operand(kPointerSize)); |
| 3343 bind(&align_loop_1); | 3449 bind(&align_loop_1); |
| 3344 And(scratch, src, kPointerSize - 1); | 3450 And(scratch, src, kPointerSize - 1); |
| 3345 Branch(&word_loop, eq, scratch, Operand(zero_reg)); | 3451 Branch(&word_loop, eq, scratch, Operand(zero_reg)); |
| 3346 lbu(scratch, MemOperand(src)); | 3452 lbu(scratch, MemOperand(src)); |
| 3347 Addu(src, src, 1); | 3453 Daddu(src, src, 1); |
| 3348 sb(scratch, MemOperand(dst)); | 3454 sb(scratch, MemOperand(dst)); |
| 3349 Addu(dst, dst, 1); | 3455 Daddu(dst, dst, 1); |
| 3350 Subu(length, length, Operand(1)); | 3456 Dsubu(length, length, Operand(1)); |
| 3351 Branch(&align_loop_1, ne, length, Operand(zero_reg)); | 3457 Branch(&align_loop_1, ne, length, Operand(zero_reg)); |
| 3352 | 3458 |
| 3353 // Copy bytes in word size chunks. | 3459 // Copy bytes in word size chunks. |
| 3354 bind(&word_loop); | 3460 bind(&word_loop); |
| 3355 if (emit_debug_code()) { | 3461 if (emit_debug_code()) { |
| 3356 And(scratch, src, kPointerSize - 1); | 3462 And(scratch, src, kPointerSize - 1); |
| 3357 Assert(eq, kExpectingAlignmentForCopyBytes, | 3463 Assert(eq, kExpectingAlignmentForCopyBytes, |
| 3358 scratch, Operand(zero_reg)); | 3464 scratch, Operand(zero_reg)); |
| 3359 } | 3465 } |
| 3360 Branch(&byte_loop, lt, length, Operand(kPointerSize)); | 3466 Branch(&byte_loop, lt, length, Operand(kPointerSize)); |
| 3361 lw(scratch, MemOperand(src)); | 3467 ld(scratch, MemOperand(src)); |
| 3362 Addu(src, src, kPointerSize); | 3468 Daddu(src, src, kPointerSize); |
| 3363 | 3469 |
| 3364 // TODO(kalmard) check if this can be optimized to use sw in most cases. | 3470 // TODO(kalmard) check if this can be optimized to use sw in most cases. |
| 3365 // Can't use unaligned access - copy byte by byte. | 3471 // Can't use unaligned access - copy byte by byte. |
| 3366 if (kArchEndian == kLittle) { | 3472 sb(scratch, MemOperand(dst, 0)); |
| 3367 sb(scratch, MemOperand(dst, 0)); | 3473 dsrl(scratch, scratch, 8); |
| 3368 srl(scratch, scratch, 8); | 3474 sb(scratch, MemOperand(dst, 1)); |
| 3369 sb(scratch, MemOperand(dst, 1)); | 3475 dsrl(scratch, scratch, 8); |
| 3370 srl(scratch, scratch, 8); | 3476 sb(scratch, MemOperand(dst, 2)); |
| 3371 sb(scratch, MemOperand(dst, 2)); | 3477 dsrl(scratch, scratch, 8); |
| 3372 srl(scratch, scratch, 8); | 3478 sb(scratch, MemOperand(dst, 3)); |
| 3373 sb(scratch, MemOperand(dst, 3)); | 3479 dsrl(scratch, scratch, 8); |
| 3374 } else { | 3480 sb(scratch, MemOperand(dst, 4)); |
| 3375 sb(scratch, MemOperand(dst, 3)); | 3481 dsrl(scratch, scratch, 8); |
| 3376 srl(scratch, scratch, 8); | 3482 sb(scratch, MemOperand(dst, 5)); |
| 3377 sb(scratch, MemOperand(dst, 2)); | 3483 dsrl(scratch, scratch, 8); |
| 3378 srl(scratch, scratch, 8); | 3484 sb(scratch, MemOperand(dst, 6)); |
| 3379 sb(scratch, MemOperand(dst, 1)); | 3485 dsrl(scratch, scratch, 8); |
| 3380 srl(scratch, scratch, 8); | 3486 sb(scratch, MemOperand(dst, 7)); |
| 3381 sb(scratch, MemOperand(dst, 0)); | 3487 Daddu(dst, dst, 8); |
| 3382 } | |
| 3383 | 3488 |
| 3384 Addu(dst, dst, 4); | 3489 Dsubu(length, length, Operand(kPointerSize)); |
| 3385 | |
| 3386 Subu(length, length, Operand(kPointerSize)); | |
| 3387 Branch(&word_loop); | 3490 Branch(&word_loop); |
| 3388 | 3491 |
| 3389 // Copy the last bytes if any left. | 3492 // Copy the last bytes if any left. |
| 3390 bind(&byte_loop); | 3493 bind(&byte_loop); |
| 3391 Branch(&done, eq, length, Operand(zero_reg)); | 3494 Branch(&done, eq, length, Operand(zero_reg)); |
| 3392 bind(&byte_loop_1); | 3495 bind(&byte_loop_1); |
| 3393 lbu(scratch, MemOperand(src)); | 3496 lbu(scratch, MemOperand(src)); |
| 3394 Addu(src, src, 1); | 3497 Daddu(src, src, 1); |
| 3395 sb(scratch, MemOperand(dst)); | 3498 sb(scratch, MemOperand(dst)); |
| 3396 Addu(dst, dst, 1); | 3499 Daddu(dst, dst, 1); |
| 3397 Subu(length, length, Operand(1)); | 3500 Dsubu(length, length, Operand(1)); |
| 3398 Branch(&byte_loop_1, ne, length, Operand(zero_reg)); | 3501 Branch(&byte_loop_1, ne, length, Operand(zero_reg)); |
| 3399 bind(&done); | 3502 bind(&done); |
| 3400 } | 3503 } |
| 3401 | 3504 |
| 3402 | 3505 |
| 3403 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, | 3506 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, |
| 3404 Register end_offset, | 3507 Register end_offset, |
| 3405 Register filler) { | 3508 Register filler) { |
| 3406 Label loop, entry; | 3509 Label loop, entry; |
| 3407 Branch(&entry); | 3510 Branch(&entry); |
| 3408 bind(&loop); | 3511 bind(&loop); |
| 3409 sw(filler, MemOperand(start_offset)); | 3512 sd(filler, MemOperand(start_offset)); |
| 3410 Addu(start_offset, start_offset, kPointerSize); | 3513 Daddu(start_offset, start_offset, kPointerSize); |
| 3411 bind(&entry); | 3514 bind(&entry); |
| 3412 Branch(&loop, lt, start_offset, Operand(end_offset)); | 3515 Branch(&loop, lt, start_offset, Operand(end_offset)); |
| 3413 } | 3516 } |
| 3414 | 3517 |
| 3415 | 3518 |
| 3416 void MacroAssembler::CheckFastElements(Register map, | 3519 void MacroAssembler::CheckFastElements(Register map, |
| 3417 Register scratch, | 3520 Register scratch, |
| 3418 Label* fail) { | 3521 Label* fail) { |
| 3419 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | 3522 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); |
| 3420 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 3523 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3473 Heap::kHeapNumberMapRootIndex, | 3576 Heap::kHeapNumberMapRootIndex, |
| 3474 fail, | 3577 fail, |
| 3475 DONT_DO_SMI_CHECK); | 3578 DONT_DO_SMI_CHECK); |
| 3476 | 3579 |
| 3477 // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000 | 3580 // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000 |
| 3478 // in the exponent. | 3581 // in the exponent. |
| 3479 li(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32)); | 3582 li(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32)); |
| 3480 lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset)); | 3583 lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset)); |
| 3481 Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1)); | 3584 Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1)); |
| 3482 | 3585 |
| 3483 lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); | 3586 lwu(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); |
| 3484 | 3587 |
| 3485 bind(&have_double_value); | 3588 bind(&have_double_value); |
| 3486 sll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize); | 3589 // dsll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize); |
| 3487 Addu(scratch1, scratch1, elements_reg); | 3590 dsra(scratch1, key_reg, 32 - kDoubleSizeLog2); |
| 3488 sw(mantissa_reg, | 3591 Daddu(scratch1, scratch1, elements_reg); |
| 3489 FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset | 3592 sw(mantissa_reg, FieldMemOperand( |
| 3490 + kHoleNanLower32Offset)); | 3593 scratch1, FixedDoubleArray::kHeaderSize - elements_offset)); |
| 3491 sw(exponent_reg, | 3594 uint32_t offset = FixedDoubleArray::kHeaderSize - elements_offset + |
| 3492 FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize - elements_offset | 3595 sizeof(kHoleNanLower32); |
| 3493 + kHoleNanUpper32Offset)); | 3596 sw(exponent_reg, FieldMemOperand(scratch1, offset)); |
| 3494 jmp(&done); | 3597 jmp(&done); |
| 3495 | 3598 |
| 3496 bind(&maybe_nan); | 3599 bind(&maybe_nan); |
| 3497 // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise | 3600 // Could be NaN, Infinity or -Infinity. If fraction is not zero, it's NaN, |
| 3498 // it's an Infinity, and the non-NaN code path applies. | 3601 // otherwise it's Infinity or -Infinity, and the non-NaN code path applies. |
| 3499 Branch(&is_nan, gt, exponent_reg, Operand(scratch1)); | |
| 3500 lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); | 3602 lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); |
| 3501 Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg)); | 3603 Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg)); |
| 3502 bind(&is_nan); | 3604 bind(&is_nan); |
| 3503 // Load canonical NaN for storing into the double array. | 3605 // Load canonical NaN for storing into the double array. |
| 3504 LoadRoot(at, Heap::kNanValueRootIndex); | 3606 LoadRoot(at, Heap::kNanValueRootIndex); |
| 3505 lw(mantissa_reg, FieldMemOperand(at, HeapNumber::kMantissaOffset)); | 3607 lw(mantissa_reg, FieldMemOperand(at, HeapNumber::kMantissaOffset)); |
| 3506 lw(exponent_reg, FieldMemOperand(at, HeapNumber::kExponentOffset)); | 3608 lw(exponent_reg, FieldMemOperand(at, HeapNumber::kExponentOffset)); |
| 3507 jmp(&have_double_value); | 3609 jmp(&have_double_value); |
| 3508 | 3610 |
| 3509 bind(&smi_value); | 3611 bind(&smi_value); |
| 3510 Addu(scratch1, elements_reg, | 3612 Daddu(scratch1, elements_reg, |
| 3511 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag - | 3613 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag - |
| 3512 elements_offset)); | 3614 elements_offset)); |
| 3513 sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize); | 3615 // dsll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize); |
| 3514 Addu(scratch1, scratch1, scratch2); | 3616 dsra(scratch2, key_reg, 32 - kDoubleSizeLog2); |
| 3617 Daddu(scratch1, scratch1, scratch2); |
| 3515 // scratch1 is now effective address of the double element | 3618 // scratch1 is now effective address of the double element |
| 3516 | 3619 |
| 3517 Register untagged_value = elements_reg; | 3620 Register untagged_value = elements_reg; |
| 3518 SmiUntag(untagged_value, value_reg); | 3621 SmiUntag(untagged_value, value_reg); |
| 3519 mtc1(untagged_value, f2); | 3622 mtc1(untagged_value, f2); |
| 3520 cvt_d_w(f0, f2); | 3623 cvt_d_w(f0, f2); |
| 3521 sdc1(f0, MemOperand(scratch1, 0)); | 3624 sdc1(f0, MemOperand(scratch1, 0)); |
| 3522 bind(&done); | 3625 bind(&done); |
| 3523 } | 3626 } |
| 3524 | 3627 |
| 3525 | 3628 |
| 3526 void MacroAssembler::CompareMapAndBranch(Register obj, | 3629 void MacroAssembler::CompareMapAndBranch(Register obj, |
| 3527 Register scratch, | 3630 Register scratch, |
| 3528 Handle<Map> map, | 3631 Handle<Map> map, |
| 3529 Label* early_success, | 3632 Label* early_success, |
| 3530 Condition cond, | 3633 Condition cond, |
| 3531 Label* branch_to) { | 3634 Label* branch_to) { |
| 3532 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 3635 ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 3533 CompareMapAndBranch(scratch, map, early_success, cond, branch_to); | 3636 CompareMapAndBranch(scratch, map, early_success, cond, branch_to); |
| 3534 } | 3637 } |
| 3535 | 3638 |
| 3536 | 3639 |
| 3537 void MacroAssembler::CompareMapAndBranch(Register obj_map, | 3640 void MacroAssembler::CompareMapAndBranch(Register obj_map, |
| 3538 Handle<Map> map, | 3641 Handle<Map> map, |
| 3539 Label* early_success, | 3642 Label* early_success, |
| 3540 Condition cond, | 3643 Condition cond, |
| 3541 Label* branch_to) { | 3644 Label* branch_to) { |
| 3542 Branch(branch_to, cond, obj_map, Operand(map)); | 3645 Branch(branch_to, cond, obj_map, Operand(map)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3559 | 3662 |
| 3560 void MacroAssembler::DispatchMap(Register obj, | 3663 void MacroAssembler::DispatchMap(Register obj, |
| 3561 Register scratch, | 3664 Register scratch, |
| 3562 Handle<Map> map, | 3665 Handle<Map> map, |
| 3563 Handle<Code> success, | 3666 Handle<Code> success, |
| 3564 SmiCheckType smi_check_type) { | 3667 SmiCheckType smi_check_type) { |
| 3565 Label fail; | 3668 Label fail; |
| 3566 if (smi_check_type == DO_SMI_CHECK) { | 3669 if (smi_check_type == DO_SMI_CHECK) { |
| 3567 JumpIfSmi(obj, &fail); | 3670 JumpIfSmi(obj, &fail); |
| 3568 } | 3671 } |
| 3569 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 3672 ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 3570 Jump(success, RelocInfo::CODE_TARGET, eq, scratch, Operand(map)); | 3673 Jump(success, RelocInfo::CODE_TARGET, eq, scratch, Operand(map)); |
| 3571 bind(&fail); | 3674 bind(&fail); |
| 3572 } | 3675 } |
| 3573 | 3676 |
| 3574 | 3677 |
| 3575 void MacroAssembler::CheckMap(Register obj, | 3678 void MacroAssembler::CheckMap(Register obj, |
| 3576 Register scratch, | 3679 Register scratch, |
| 3577 Heap::RootListIndex index, | 3680 Heap::RootListIndex index, |
| 3578 Label* fail, | 3681 Label* fail, |
| 3579 SmiCheckType smi_check_type) { | 3682 SmiCheckType smi_check_type) { |
| 3580 if (smi_check_type == DO_SMI_CHECK) { | 3683 if (smi_check_type == DO_SMI_CHECK) { |
| 3581 JumpIfSmi(obj, fail); | 3684 JumpIfSmi(obj, fail); |
| 3582 } | 3685 } |
| 3583 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 3686 ld(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 3584 LoadRoot(at, index); | 3687 LoadRoot(at, index); |
| 3585 Branch(fail, ne, scratch, Operand(at)); | 3688 Branch(fail, ne, scratch, Operand(at)); |
| 3586 } | 3689 } |
| 3587 | 3690 |
| 3588 | 3691 |
| 3589 void MacroAssembler::MovFromFloatResult(DoubleRegister dst) { | 3692 void MacroAssembler::MovFromFloatResult(const DoubleRegister dst) { |
| 3590 if (IsMipsSoftFloatABI) { | 3693 if (IsMipsSoftFloatABI) { |
| 3591 if (kArchEndian == kLittle) { | 3694 Move(dst, v0, v1); |
| 3592 Move(dst, v0, v1); | |
| 3593 } else { | |
| 3594 Move(dst, v1, v0); | |
| 3595 } | |
| 3596 } else { | 3695 } else { |
| 3597 Move(dst, f0); // Reg f0 is o32 ABI FP return value. | 3696 Move(dst, f0); // Reg f0 is o32 ABI FP return value. |
| 3598 } | 3697 } |
| 3599 } | 3698 } |
| 3600 | 3699 |
| 3601 | 3700 |
| 3602 void MacroAssembler::MovFromFloatParameter(DoubleRegister dst) { | 3701 void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) { |
| 3603 if (IsMipsSoftFloatABI) { | 3702 if (IsMipsSoftFloatABI) { |
| 3604 if (kArchEndian == kLittle) { | 3703 Move(dst, a0, a1); |
| 3605 Move(dst, a0, a1); | |
| 3606 } else { | |
| 3607 Move(dst, a1, a0); | |
| 3608 } | |
| 3609 } else { | 3704 } else { |
| 3610 Move(dst, f12); // Reg f12 is o32 ABI FP first argument value. | 3705 Move(dst, f12); // Reg f12 is o32 ABI FP first argument value. |
| 3611 } | 3706 } |
| 3612 } | 3707 } |
| 3613 | 3708 |
| 3614 | 3709 |
| 3615 void MacroAssembler::MovToFloatParameter(DoubleRegister src) { | 3710 void MacroAssembler::MovToFloatParameter(DoubleRegister src) { |
| 3616 if (!IsMipsSoftFloatABI) { | 3711 if (!IsMipsSoftFloatABI) { |
| 3617 Move(f12, src); | 3712 Move(f12, src); |
| 3618 } else { | 3713 } else { |
| 3619 if (kArchEndian == kLittle) { | 3714 Move(a0, a1, src); |
| 3620 Move(a0, a1, src); | |
| 3621 } else { | |
| 3622 Move(a1, a0, src); | |
| 3623 } | |
| 3624 } | 3715 } |
| 3625 } | 3716 } |
| 3626 | 3717 |
| 3627 | 3718 |
| 3628 void MacroAssembler::MovToFloatResult(DoubleRegister src) { | 3719 void MacroAssembler::MovToFloatResult(DoubleRegister src) { |
| 3629 if (!IsMipsSoftFloatABI) { | 3720 if (!IsMipsSoftFloatABI) { |
| 3630 Move(f0, src); | 3721 Move(f0, src); |
| 3631 } else { | 3722 } else { |
| 3632 if (kArchEndian == kLittle) { | 3723 Move(v0, v1, src); |
| 3633 Move(v0, v1, src); | |
| 3634 } else { | |
| 3635 Move(v1, v0, src); | |
| 3636 } | |
| 3637 } | 3724 } |
| 3638 } | 3725 } |
| 3639 | 3726 |
| 3640 | 3727 |
| 3641 void MacroAssembler::MovToFloatParameters(DoubleRegister src1, | 3728 void MacroAssembler::MovToFloatParameters(DoubleRegister src1, |
| 3642 DoubleRegister src2) { | 3729 DoubleRegister src2) { |
| 3643 if (!IsMipsSoftFloatABI) { | 3730 if (!IsMipsSoftFloatABI) { |
| 3731 const DoubleRegister fparg2 = (kMipsAbi == kN64) ? f13 : f14; |
| 3644 if (src2.is(f12)) { | 3732 if (src2.is(f12)) { |
| 3645 ASSERT(!src1.is(f14)); | 3733 ASSERT(!src1.is(fparg2)); |
| 3646 Move(f14, src2); | 3734 Move(fparg2, src2); |
| 3647 Move(f12, src1); | 3735 Move(f12, src1); |
| 3648 } else { | 3736 } else { |
| 3649 Move(f12, src1); | 3737 Move(f12, src1); |
| 3650 Move(f14, src2); | 3738 Move(fparg2, src2); |
| 3651 } | 3739 } |
| 3652 } else { | 3740 } else { |
| 3653 if (kArchEndian == kLittle) { | 3741 Move(a0, a1, src1); |
| 3654 Move(a0, a1, src1); | 3742 Move(a2, a3, src2); |
| 3655 Move(a2, a3, src2); | |
| 3656 } else { | |
| 3657 Move(a1, a0, src1); | |
| 3658 Move(a3, a2, src2); | |
| 3659 } | |
| 3660 } | 3743 } |
| 3661 } | 3744 } |
| 3662 | 3745 |
| 3663 | 3746 |
| 3664 // ----------------------------------------------------------------------------- | 3747 // ----------------------------------------------------------------------------- |
| 3665 // JavaScript invokes. | 3748 // JavaScript invokes. |
| 3666 | 3749 |
| 3667 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 3750 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
| 3668 const ParameterCount& actual, | 3751 const ParameterCount& actual, |
| 3669 Handle<Code> code_constant, | 3752 Handle<Code> code_constant, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3710 } else if (actual.is_immediate()) { | 3793 } else if (actual.is_immediate()) { |
| 3711 Branch(®ular_invoke, eq, expected.reg(), Operand(actual.immediate())); | 3794 Branch(®ular_invoke, eq, expected.reg(), Operand(actual.immediate())); |
| 3712 li(a0, Operand(actual.immediate())); | 3795 li(a0, Operand(actual.immediate())); |
| 3713 } else { | 3796 } else { |
| 3714 Branch(®ular_invoke, eq, expected.reg(), Operand(actual.reg())); | 3797 Branch(®ular_invoke, eq, expected.reg(), Operand(actual.reg())); |
| 3715 } | 3798 } |
| 3716 | 3799 |
| 3717 if (!definitely_matches) { | 3800 if (!definitely_matches) { |
| 3718 if (!code_constant.is_null()) { | 3801 if (!code_constant.is_null()) { |
| 3719 li(a3, Operand(code_constant)); | 3802 li(a3, Operand(code_constant)); |
| 3720 addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag); | 3803 daddiu(a3, a3, Code::kHeaderSize - kHeapObjectTag); |
| 3721 } | 3804 } |
| 3722 | 3805 |
| 3723 Handle<Code> adaptor = | 3806 Handle<Code> adaptor = |
| 3724 isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3807 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3725 if (flag == CALL_FUNCTION) { | 3808 if (flag == CALL_FUNCTION) { |
| 3726 call_wrapper.BeforeCall(CallSize(adaptor)); | 3809 call_wrapper.BeforeCall(CallSize(adaptor)); |
| 3727 Call(adaptor); | 3810 Call(adaptor); |
| 3728 call_wrapper.AfterCall(); | 3811 call_wrapper.AfterCall(); |
| 3729 if (!*definitely_mismatches) { | 3812 if (!*definitely_mismatches) { |
| 3730 Branch(done); | 3813 Branch(done); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3771 const ParameterCount& actual, | 3854 const ParameterCount& actual, |
| 3772 InvokeFlag flag, | 3855 InvokeFlag flag, |
| 3773 const CallWrapper& call_wrapper) { | 3856 const CallWrapper& call_wrapper) { |
| 3774 // You can't call a function without a valid frame. | 3857 // You can't call a function without a valid frame. |
| 3775 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3858 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
| 3776 | 3859 |
| 3777 // Contract with called JS functions requires that function is passed in a1. | 3860 // Contract with called JS functions requires that function is passed in a1. |
| 3778 ASSERT(function.is(a1)); | 3861 ASSERT(function.is(a1)); |
| 3779 Register expected_reg = a2; | 3862 Register expected_reg = a2; |
| 3780 Register code_reg = a3; | 3863 Register code_reg = a3; |
| 3781 | 3864 ld(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 3782 lw(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 3865 ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 3783 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 3866 // The argument count is stored as int32_t on 64-bit platforms. |
| 3867 // TODO(plind): Smi on 32-bit platforms. |
| 3784 lw(expected_reg, | 3868 lw(expected_reg, |
| 3785 FieldMemOperand(code_reg, | 3869 FieldMemOperand(code_reg, |
| 3786 SharedFunctionInfo::kFormalParameterCountOffset)); | 3870 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 3787 sra(expected_reg, expected_reg, kSmiTagSize); | 3871 ld(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 3788 lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | |
| 3789 | |
| 3790 ParameterCount expected(expected_reg); | 3872 ParameterCount expected(expected_reg); |
| 3791 InvokeCode(code_reg, expected, actual, flag, call_wrapper); | 3873 InvokeCode(code_reg, expected, actual, flag, call_wrapper); |
| 3792 } | 3874 } |
| 3793 | 3875 |
| 3794 | 3876 |
| 3795 void MacroAssembler::InvokeFunction(Register function, | 3877 void MacroAssembler::InvokeFunction(Register function, |
| 3796 const ParameterCount& expected, | 3878 const ParameterCount& expected, |
| 3797 const ParameterCount& actual, | 3879 const ParameterCount& actual, |
| 3798 InvokeFlag flag, | 3880 InvokeFlag flag, |
| 3799 const CallWrapper& call_wrapper) { | 3881 const CallWrapper& call_wrapper) { |
| 3800 // You can't call a function without a valid frame. | 3882 // You can't call a function without a valid frame. |
| 3801 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3883 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
| 3802 | 3884 |
| 3803 // Contract with called JS functions requires that function is passed in a1. | 3885 // Contract with called JS functions requires that function is passed in a1. |
| 3804 ASSERT(function.is(a1)); | 3886 ASSERT(function.is(a1)); |
| 3805 | 3887 |
| 3806 // Get the function and setup the context. | 3888 // Get the function and setup the context. |
| 3807 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 3889 ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 3808 | 3890 |
| 3809 // We call indirectly through the code field in the function to | 3891 // We call indirectly through the code field in the function to |
| 3810 // allow recompilation to take effect without changing any of the | 3892 // allow recompilation to take effect without changing any of the |
| 3811 // call sites. | 3893 // call sites. |
| 3812 lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 3894 ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 3813 InvokeCode(a3, expected, actual, flag, call_wrapper); | 3895 InvokeCode(a3, expected, actual, flag, call_wrapper); |
| 3814 } | 3896 } |
| 3815 | 3897 |
| 3816 | 3898 |
| 3817 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 3899 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
| 3818 const ParameterCount& expected, | 3900 const ParameterCount& expected, |
| 3819 const ParameterCount& actual, | 3901 const ParameterCount& actual, |
| 3820 InvokeFlag flag, | 3902 InvokeFlag flag, |
| 3821 const CallWrapper& call_wrapper) { | 3903 const CallWrapper& call_wrapper) { |
| 3822 li(a1, function); | 3904 li(a1, function); |
| 3823 InvokeFunction(a1, expected, actual, flag, call_wrapper); | 3905 InvokeFunction(a1, expected, actual, flag, call_wrapper); |
| 3824 } | 3906 } |
| 3825 | 3907 |
| 3826 | 3908 |
| 3827 void MacroAssembler::IsObjectJSObjectType(Register heap_object, | 3909 void MacroAssembler::IsObjectJSObjectType(Register heap_object, |
| 3828 Register map, | 3910 Register map, |
| 3829 Register scratch, | 3911 Register scratch, |
| 3830 Label* fail) { | 3912 Label* fail) { |
| 3831 lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); | 3913 ld(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); |
| 3832 IsInstanceJSObjectType(map, scratch, fail); | 3914 IsInstanceJSObjectType(map, scratch, fail); |
| 3833 } | 3915 } |
| 3834 | 3916 |
| 3835 | 3917 |
| 3836 void MacroAssembler::IsInstanceJSObjectType(Register map, | 3918 void MacroAssembler::IsInstanceJSObjectType(Register map, |
| 3837 Register scratch, | 3919 Register scratch, |
| 3838 Label* fail) { | 3920 Label* fail) { |
| 3839 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 3921 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 3840 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 3922 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 3841 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 3923 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 3842 } | 3924 } |
| 3843 | 3925 |
| 3844 | 3926 |
| 3845 void MacroAssembler::IsObjectJSStringType(Register object, | 3927 void MacroAssembler::IsObjectJSStringType(Register object, |
| 3846 Register scratch, | 3928 Register scratch, |
| 3847 Label* fail) { | 3929 Label* fail) { |
| 3848 ASSERT(kNotStringTag != 0); | 3930 ASSERT(kNotStringTag != 0); |
| 3849 | 3931 |
| 3850 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3932 ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 3851 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3933 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 3852 And(scratch, scratch, Operand(kIsNotStringMask)); | 3934 And(scratch, scratch, Operand(kIsNotStringMask)); |
| 3853 Branch(fail, ne, scratch, Operand(zero_reg)); | 3935 Branch(fail, ne, scratch, Operand(zero_reg)); |
| 3854 } | 3936 } |
| 3855 | 3937 |
| 3856 | 3938 |
| 3857 void MacroAssembler::IsObjectNameType(Register object, | 3939 void MacroAssembler::IsObjectNameType(Register object, |
| 3858 Register scratch, | 3940 Register scratch, |
| 3859 Label* fail) { | 3941 Label* fail) { |
| 3860 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3942 ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 3861 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3943 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 3862 Branch(fail, hi, scratch, Operand(LAST_NAME_TYPE)); | 3944 Branch(fail, hi, scratch, Operand(LAST_NAME_TYPE)); |
| 3863 } | 3945 } |
| 3864 | 3946 |
| 3865 | 3947 |
| 3866 // --------------------------------------------------------------------------- | 3948 // --------------------------------------------------------------------------- |
| 3867 // Support functions. | 3949 // Support functions. |
| 3868 | 3950 |
| 3869 | 3951 |
| 3870 void MacroAssembler::TryGetFunctionPrototype(Register function, | 3952 void MacroAssembler::TryGetFunctionPrototype(Register function, |
| 3871 Register result, | 3953 Register result, |
| 3872 Register scratch, | 3954 Register scratch, |
| 3873 Label* miss, | 3955 Label* miss, |
| 3874 bool miss_on_bound_function) { | 3956 bool miss_on_bound_function) { |
| 3875 // Check that the receiver isn't a smi. | 3957 // Check that the receiver isn't a smi. |
| 3876 JumpIfSmi(function, miss); | 3958 JumpIfSmi(function, miss); |
| 3877 | 3959 |
| 3878 // Check that the function really is a function. Load map into result reg. | 3960 // Check that the function really is a function. Load map into result reg. |
| 3879 GetObjectType(function, result, scratch); | 3961 GetObjectType(function, result, scratch); |
| 3880 Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE)); | 3962 Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE)); |
| 3881 | 3963 |
| 3882 if (miss_on_bound_function) { | 3964 if (miss_on_bound_function) { |
| 3883 lw(scratch, | 3965 ld(scratch, |
| 3884 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3966 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3885 lw(scratch, | 3967 // ld(scratch, |
| 3886 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); | 3968 // FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); |
| 3969 // And(scratch, scratch, |
| 3970 // Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction))); |
| 3971 lwu(scratch, |
| 3972 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); |
| 3887 And(scratch, scratch, | 3973 And(scratch, scratch, |
| 3888 Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction))); | 3974 Operand(1 << SharedFunctionInfo::kBoundFunction)); |
| 3889 Branch(miss, ne, scratch, Operand(zero_reg)); | 3975 Branch(miss, ne, scratch, Operand(zero_reg)); |
| 3890 } | 3976 } |
| 3891 | 3977 |
| 3892 // Make sure that the function has an instance prototype. | 3978 // Make sure that the function has an instance prototype. |
| 3893 Label non_instance; | 3979 Label non_instance; |
| 3894 lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); | 3980 lbu(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); |
| 3895 And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype)); | 3981 And(scratch, scratch, Operand(1 << Map::kHasNonInstancePrototype)); |
| 3896 Branch(&non_instance, ne, scratch, Operand(zero_reg)); | 3982 Branch(&non_instance, ne, scratch, Operand(zero_reg)); |
| 3897 | 3983 |
| 3898 // Get the prototype or initial map from the function. | 3984 // Get the prototype or initial map from the function. |
| 3899 lw(result, | 3985 ld(result, |
| 3900 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3986 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3901 | 3987 |
| 3902 // If the prototype or initial map is the hole, don't return it and | 3988 // If the prototype or initial map is the hole, don't return it and |
| 3903 // simply miss the cache instead. This will allow us to allocate a | 3989 // simply miss the cache instead. This will allow us to allocate a |
| 3904 // prototype object on-demand in the runtime system. | 3990 // prototype object on-demand in the runtime system. |
| 3905 LoadRoot(t8, Heap::kTheHoleValueRootIndex); | 3991 LoadRoot(t8, Heap::kTheHoleValueRootIndex); |
| 3906 Branch(miss, eq, result, Operand(t8)); | 3992 Branch(miss, eq, result, Operand(t8)); |
| 3907 | 3993 |
| 3908 // If the function does not have an initial map, we're done. | 3994 // If the function does not have an initial map, we're done. |
| 3909 Label done; | 3995 Label done; |
| 3910 GetObjectType(result, scratch, scratch); | 3996 GetObjectType(result, scratch, scratch); |
| 3911 Branch(&done, ne, scratch, Operand(MAP_TYPE)); | 3997 Branch(&done, ne, scratch, Operand(MAP_TYPE)); |
| 3912 | 3998 |
| 3913 // Get the prototype from the initial map. | 3999 // Get the prototype from the initial map. |
| 3914 lw(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 4000 ld(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 3915 jmp(&done); | 4001 jmp(&done); |
| 3916 | 4002 |
| 3917 // Non-instance prototype: Fetch prototype from constructor field | 4003 // Non-instance prototype: Fetch prototype from constructor field |
| 3918 // in initial map. | 4004 // in initial map. |
| 3919 bind(&non_instance); | 4005 bind(&non_instance); |
| 3920 lw(result, FieldMemOperand(result, Map::kConstructorOffset)); | 4006 ld(result, FieldMemOperand(result, Map::kConstructorOffset)); |
| 3921 | 4007 |
| 3922 // All done. | 4008 // All done. |
| 3923 bind(&done); | 4009 bind(&done); |
| 3924 } | 4010 } |
| 3925 | 4011 |
| 3926 | 4012 |
| 3927 void MacroAssembler::GetObjectType(Register object, | 4013 void MacroAssembler::GetObjectType(Register object, |
| 3928 Register map, | 4014 Register map, |
| 3929 Register type_reg) { | 4015 Register type_reg) { |
| 3930 lw(map, FieldMemOperand(object, HeapObject::kMapOffset)); | 4016 ld(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 3931 lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 4017 lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 3932 } | 4018 } |
| 3933 | 4019 |
| 3934 | 4020 |
| 3935 // ----------------------------------------------------------------------------- | 4021 // ----------------------------------------------------------------------------- |
| 3936 // Runtime calls. | 4022 // Runtime calls. |
| 3937 | 4023 |
| 3938 void MacroAssembler::CallStub(CodeStub* stub, | 4024 void MacroAssembler::CallStub(CodeStub* stub, |
| 3939 TypeFeedbackId ast_id, | 4025 TypeFeedbackId ast_id, |
| 3940 Condition cond, | 4026 Condition cond, |
| 3941 Register r1, | 4027 Register r1, |
| 3942 const Operand& r2, | 4028 const Operand& r2, |
| 3943 BranchDelaySlot bd) { | 4029 BranchDelaySlot bd) { |
| 3944 ASSERT(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. | 4030 ASSERT(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. |
| 3945 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, | 4031 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, |
| 3946 cond, r1, r2, bd); | 4032 cond, r1, r2, bd); |
| 3947 } | 4033 } |
| 3948 | 4034 |
| 3949 | 4035 |
| 3950 void MacroAssembler::TailCallStub(CodeStub* stub, | 4036 void MacroAssembler::TailCallStub(CodeStub* stub, |
| 3951 Condition cond, | 4037 Condition cond, |
| 3952 Register r1, | 4038 Register r1, |
| 3953 const Operand& r2, | 4039 const Operand& r2, |
| 3954 BranchDelaySlot bd) { | 4040 BranchDelaySlot bd) { |
| 3955 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd); | 4041 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd); |
| 3956 } | 4042 } |
| 3957 | 4043 |
| 3958 | 4044 |
| 3959 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 4045 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 3960 return ref0.address() - ref1.address(); | 4046 int64_t offset = (ref0.address() - ref1.address()); |
| 4047 ASSERT(static_cast<int>(offset) == offset); |
| 4048 return static_cast<int>(offset); |
| 3961 } | 4049 } |
| 3962 | 4050 |
| 3963 | 4051 |
| 3964 void MacroAssembler::CallApiFunctionAndReturn( | 4052 void MacroAssembler::CallApiFunctionAndReturn( |
| 3965 Register function_address, | 4053 Register function_address, |
| 3966 ExternalReference thunk_ref, | 4054 ExternalReference thunk_ref, |
| 3967 int stack_space, | 4055 int stack_space, |
| 3968 MemOperand return_value_operand, | 4056 MemOperand return_value_operand, |
| 3969 MemOperand* context_restore_operand) { | 4057 MemOperand* context_restore_operand) { |
| 3970 ExternalReference next_address = | 4058 ExternalReference next_address = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3988 // Additional parameter is the address of the actual callback. | 4076 // Additional parameter is the address of the actual callback. |
| 3989 li(t9, Operand(thunk_ref)); | 4077 li(t9, Operand(thunk_ref)); |
| 3990 jmp(&end_profiler_check); | 4078 jmp(&end_profiler_check); |
| 3991 | 4079 |
| 3992 bind(&profiler_disabled); | 4080 bind(&profiler_disabled); |
| 3993 mov(t9, function_address); | 4081 mov(t9, function_address); |
| 3994 bind(&end_profiler_check); | 4082 bind(&end_profiler_check); |
| 3995 | 4083 |
| 3996 // Allocate HandleScope in callee-save registers. | 4084 // Allocate HandleScope in callee-save registers. |
| 3997 li(s3, Operand(next_address)); | 4085 li(s3, Operand(next_address)); |
| 3998 lw(s0, MemOperand(s3, kNextOffset)); | 4086 ld(s0, MemOperand(s3, kNextOffset)); |
| 3999 lw(s1, MemOperand(s3, kLimitOffset)); | 4087 ld(s1, MemOperand(s3, kLimitOffset)); |
| 4000 lw(s2, MemOperand(s3, kLevelOffset)); | 4088 ld(s2, MemOperand(s3, kLevelOffset)); |
| 4001 Addu(s2, s2, Operand(1)); | 4089 Daddu(s2, s2, Operand(1)); |
| 4002 sw(s2, MemOperand(s3, kLevelOffset)); | 4090 sd(s2, MemOperand(s3, kLevelOffset)); |
| 4003 | 4091 |
| 4004 if (FLAG_log_timer_events) { | 4092 if (FLAG_log_timer_events) { |
| 4005 FrameScope frame(this, StackFrame::MANUAL); | 4093 FrameScope frame(this, StackFrame::MANUAL); |
| 4006 PushSafepointRegisters(); | 4094 PushSafepointRegisters(); |
| 4007 PrepareCallCFunction(1, a0); | 4095 PrepareCallCFunction(1, a0); |
| 4008 li(a0, Operand(ExternalReference::isolate_address(isolate()))); | 4096 li(a0, Operand(ExternalReference::isolate_address(isolate()))); |
| 4009 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); | 4097 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); |
| 4010 PopSafepointRegisters(); | 4098 PopSafepointRegisters(); |
| 4011 } | 4099 } |
| 4012 | 4100 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4025 PopSafepointRegisters(); | 4113 PopSafepointRegisters(); |
| 4026 } | 4114 } |
| 4027 | 4115 |
| 4028 Label promote_scheduled_exception; | 4116 Label promote_scheduled_exception; |
| 4029 Label exception_handled; | 4117 Label exception_handled; |
| 4030 Label delete_allocated_handles; | 4118 Label delete_allocated_handles; |
| 4031 Label leave_exit_frame; | 4119 Label leave_exit_frame; |
| 4032 Label return_value_loaded; | 4120 Label return_value_loaded; |
| 4033 | 4121 |
| 4034 // Load value from ReturnValue. | 4122 // Load value from ReturnValue. |
| 4035 lw(v0, return_value_operand); | 4123 ld(v0, return_value_operand); |
| 4036 bind(&return_value_loaded); | 4124 bind(&return_value_loaded); |
| 4037 | 4125 |
| 4038 // No more valid handles (the result handle was the last one). Restore | 4126 // No more valid handles (the result handle was the last one). Restore |
| 4039 // previous handle scope. | 4127 // previous handle scope. |
| 4040 sw(s0, MemOperand(s3, kNextOffset)); | 4128 sd(s0, MemOperand(s3, kNextOffset)); |
| 4041 if (emit_debug_code()) { | 4129 if (emit_debug_code()) { |
| 4042 lw(a1, MemOperand(s3, kLevelOffset)); | 4130 ld(a1, MemOperand(s3, kLevelOffset)); |
| 4043 Check(eq, kUnexpectedLevelAfterReturnFromApiCall, a1, Operand(s2)); | 4131 Check(eq, kUnexpectedLevelAfterReturnFromApiCall, a1, Operand(s2)); |
| 4044 } | 4132 } |
| 4045 Subu(s2, s2, Operand(1)); | 4133 Dsubu(s2, s2, Operand(1)); |
| 4046 sw(s2, MemOperand(s3, kLevelOffset)); | 4134 sd(s2, MemOperand(s3, kLevelOffset)); |
| 4047 lw(at, MemOperand(s3, kLimitOffset)); | 4135 ld(at, MemOperand(s3, kLimitOffset)); |
| 4048 Branch(&delete_allocated_handles, ne, s1, Operand(at)); | 4136 Branch(&delete_allocated_handles, ne, s1, Operand(at)); |
| 4049 | 4137 |
| 4050 // Check if the function scheduled an exception. | 4138 // Check if the function scheduled an exception. |
| 4051 bind(&leave_exit_frame); | 4139 bind(&leave_exit_frame); |
| 4052 LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 4140 LoadRoot(a4, Heap::kTheHoleValueRootIndex); |
| 4053 li(at, Operand(ExternalReference::scheduled_exception_address(isolate()))); | 4141 li(at, Operand(ExternalReference::scheduled_exception_address(isolate()))); |
| 4054 lw(t1, MemOperand(at)); | 4142 ld(a5, MemOperand(at)); |
| 4055 Branch(&promote_scheduled_exception, ne, t0, Operand(t1)); | 4143 Branch(&promote_scheduled_exception, ne, a4, Operand(a5)); |
| 4056 bind(&exception_handled); | 4144 bind(&exception_handled); |
| 4057 | 4145 |
| 4058 bool restore_context = context_restore_operand != NULL; | 4146 bool restore_context = context_restore_operand != NULL; |
| 4059 if (restore_context) { | 4147 if (restore_context) { |
| 4060 lw(cp, *context_restore_operand); | 4148 ld(cp, *context_restore_operand); |
| 4061 } | 4149 } |
| 4062 li(s0, Operand(stack_space)); | 4150 li(s0, Operand(stack_space)); |
| 4063 LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN); | 4151 LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN); |
| 4064 | 4152 |
| 4065 bind(&promote_scheduled_exception); | 4153 bind(&promote_scheduled_exception); |
| 4066 { | 4154 { |
| 4067 FrameScope frame(this, StackFrame::INTERNAL); | 4155 FrameScope frame(this, StackFrame::INTERNAL); |
| 4068 CallExternalReference( | 4156 CallExternalReference( |
| 4069 ExternalReference(Runtime::kPromoteScheduledException, isolate()), | 4157 ExternalReference(Runtime::kPromoteScheduledException, isolate()), |
| 4070 0); | 4158 0); |
| 4071 } | 4159 } |
| 4072 jmp(&exception_handled); | 4160 jmp(&exception_handled); |
| 4073 | 4161 |
| 4074 // HandleScope limit has changed. Delete allocated extensions. | 4162 // HandleScope limit has changed. Delete allocated extensions. |
| 4075 bind(&delete_allocated_handles); | 4163 bind(&delete_allocated_handles); |
| 4076 sw(s1, MemOperand(s3, kLimitOffset)); | 4164 sd(s1, MemOperand(s3, kLimitOffset)); |
| 4077 mov(s0, v0); | 4165 mov(s0, v0); |
| 4078 mov(a0, v0); | 4166 mov(a0, v0); |
| 4079 PrepareCallCFunction(1, s1); | 4167 PrepareCallCFunction(1, s1); |
| 4080 li(a0, Operand(ExternalReference::isolate_address(isolate()))); | 4168 li(a0, Operand(ExternalReference::isolate_address(isolate()))); |
| 4081 CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate()), | 4169 CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate()), |
| 4082 1); | 4170 1); |
| 4083 mov(v0, s0); | 4171 mov(v0, s0); |
| 4084 jmp(&leave_exit_frame); | 4172 jmp(&leave_exit_frame); |
| 4085 } | 4173 } |
| 4086 | 4174 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4106 Register scratch1, | 4194 Register scratch1, |
| 4107 Register scratch2, | 4195 Register scratch2, |
| 4108 Register heap_number_map, | 4196 Register heap_number_map, |
| 4109 Label* not_number, | 4197 Label* not_number, |
| 4110 ObjectToDoubleFlags flags) { | 4198 ObjectToDoubleFlags flags) { |
| 4111 Label done; | 4199 Label done; |
| 4112 if ((flags & OBJECT_NOT_SMI) == 0) { | 4200 if ((flags & OBJECT_NOT_SMI) == 0) { |
| 4113 Label not_smi; | 4201 Label not_smi; |
| 4114 JumpIfNotSmi(object, ¬_smi); | 4202 JumpIfNotSmi(object, ¬_smi); |
| 4115 // Remove smi tag and convert to double. | 4203 // Remove smi tag and convert to double. |
| 4116 sra(scratch1, object, kSmiTagSize); | 4204 // dsra(scratch1, object, kSmiTagSize); |
| 4205 dsra32(scratch1, object, 0); |
| 4117 mtc1(scratch1, result); | 4206 mtc1(scratch1, result); |
| 4118 cvt_d_w(result, result); | 4207 cvt_d_w(result, result); |
| 4119 Branch(&done); | 4208 Branch(&done); |
| 4120 bind(¬_smi); | 4209 bind(¬_smi); |
| 4121 } | 4210 } |
| 4122 // Check for heap number and load double value from it. | 4211 // Check for heap number and load double value from it. |
| 4123 lw(scratch1, FieldMemOperand(object, HeapObject::kMapOffset)); | 4212 ld(scratch1, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4124 Branch(not_number, ne, scratch1, Operand(heap_number_map)); | 4213 Branch(not_number, ne, scratch1, Operand(heap_number_map)); |
| 4125 | 4214 |
| 4126 if ((flags & AVOID_NANS_AND_INFINITIES) != 0) { | 4215 if ((flags & AVOID_NANS_AND_INFINITIES) != 0) { |
| 4127 // If exponent is all ones the number is either a NaN or +/-Infinity. | 4216 // If exponent is all ones the number is either a NaN or +/-Infinity. |
| 4128 Register exponent = scratch1; | 4217 Register exponent = scratch1; |
| 4129 Register mask_reg = scratch2; | 4218 Register mask_reg = scratch2; |
| 4130 lw(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 4219 lwu(exponent, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 4131 li(mask_reg, HeapNumber::kExponentMask); | 4220 li(mask_reg, HeapNumber::kExponentMask); |
| 4132 | 4221 |
| 4133 And(exponent, exponent, mask_reg); | 4222 And(exponent, exponent, mask_reg); |
| 4134 Branch(not_number, eq, exponent, Operand(mask_reg)); | 4223 Branch(not_number, eq, exponent, Operand(mask_reg)); |
| 4135 } | 4224 } |
| 4136 ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset)); | 4225 ldc1(result, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 4137 bind(&done); | 4226 bind(&done); |
| 4138 } | 4227 } |
| 4139 | 4228 |
| 4140 | 4229 |
| 4141 void MacroAssembler::SmiToDoubleFPURegister(Register smi, | 4230 void MacroAssembler::SmiToDoubleFPURegister(Register smi, |
| 4142 FPURegister value, | 4231 FPURegister value, |
| 4143 Register scratch1) { | 4232 Register scratch1) { |
| 4144 sra(scratch1, smi, kSmiTagSize); | 4233 // dsra(scratch1, smi, kSmiTagSize); |
| 4234 dsra32(scratch1, smi, 0); |
| 4145 mtc1(scratch1, value); | 4235 mtc1(scratch1, value); |
| 4146 cvt_d_w(value, value); | 4236 cvt_d_w(value, value); |
| 4147 } | 4237 } |
| 4148 | 4238 |
| 4149 | 4239 |
| 4150 void MacroAssembler::AdduAndCheckForOverflow(Register dst, | 4240 void MacroAssembler::AdduAndCheckForOverflow(Register dst, |
| 4151 Register left, | 4241 Register left, |
| 4152 Register right, | 4242 Register right, |
| 4153 Register overflow_dst, | 4243 Register overflow_dst, |
| 4154 Register scratch) { | 4244 Register scratch) { |
| 4155 ASSERT(!dst.is(overflow_dst)); | 4245 ASSERT(!dst.is(overflow_dst)); |
| 4156 ASSERT(!dst.is(scratch)); | 4246 ASSERT(!dst.is(scratch)); |
| 4157 ASSERT(!overflow_dst.is(scratch)); | 4247 ASSERT(!overflow_dst.is(scratch)); |
| 4158 ASSERT(!overflow_dst.is(left)); | 4248 ASSERT(!overflow_dst.is(left)); |
| 4159 ASSERT(!overflow_dst.is(right)); | 4249 ASSERT(!overflow_dst.is(right)); |
| 4160 | 4250 |
| 4161 if (left.is(right) && dst.is(left)) { | 4251 if (left.is(right) && dst.is(left)) { |
| 4162 ASSERT(!dst.is(t9)); | 4252 ASSERT(!dst.is(t9)); |
| 4163 ASSERT(!scratch.is(t9)); | 4253 ASSERT(!scratch.is(t9)); |
| 4164 ASSERT(!left.is(t9)); | 4254 ASSERT(!left.is(t9)); |
| 4165 ASSERT(!right.is(t9)); | 4255 ASSERT(!right.is(t9)); |
| 4166 ASSERT(!overflow_dst.is(t9)); | 4256 ASSERT(!overflow_dst.is(t9)); |
| 4167 mov(t9, right); | 4257 mov(t9, right); |
| 4168 right = t9; | 4258 right = t9; |
| 4169 } | 4259 } |
| 4170 | 4260 |
| 4171 if (dst.is(left)) { | 4261 if (dst.is(left)) { |
| 4172 mov(scratch, left); // Preserve left. | 4262 mov(scratch, left); // Preserve left. |
| 4173 addu(dst, left, right); // Left is overwritten. | 4263 daddu(dst, left, right); // Left is overwritten. |
| 4174 xor_(scratch, dst, scratch); // Original left. | 4264 xor_(scratch, dst, scratch); // Original left. |
| 4175 xor_(overflow_dst, dst, right); | 4265 xor_(overflow_dst, dst, right); |
| 4176 and_(overflow_dst, overflow_dst, scratch); | 4266 and_(overflow_dst, overflow_dst, scratch); |
| 4177 } else if (dst.is(right)) { | 4267 } else if (dst.is(right)) { |
| 4178 mov(scratch, right); // Preserve right. | 4268 mov(scratch, right); // Preserve right. |
| 4179 addu(dst, left, right); // Right is overwritten. | 4269 daddu(dst, left, right); // Right is overwritten. |
| 4180 xor_(scratch, dst, scratch); // Original right. | 4270 xor_(scratch, dst, scratch); // Original right. |
| 4181 xor_(overflow_dst, dst, left); | 4271 xor_(overflow_dst, dst, left); |
| 4182 and_(overflow_dst, overflow_dst, scratch); | 4272 and_(overflow_dst, overflow_dst, scratch); |
| 4183 } else { | 4273 } else { |
| 4184 addu(dst, left, right); | 4274 daddu(dst, left, right); |
| 4185 xor_(overflow_dst, dst, left); | 4275 xor_(overflow_dst, dst, left); |
| 4186 xor_(scratch, dst, right); | 4276 xor_(scratch, dst, right); |
| 4187 and_(overflow_dst, scratch, overflow_dst); | 4277 and_(overflow_dst, scratch, overflow_dst); |
| 4188 } | 4278 } |
| 4189 } | 4279 } |
| 4190 | 4280 |
| 4191 | 4281 |
| 4192 void MacroAssembler::SubuAndCheckForOverflow(Register dst, | 4282 void MacroAssembler::SubuAndCheckForOverflow(Register dst, |
| 4193 Register left, | 4283 Register left, |
| 4194 Register right, | 4284 Register right, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4205 // This happens with some crankshaft code. Since Subu works fine if | 4295 // This happens with some crankshaft code. Since Subu works fine if |
| 4206 // left == right, let's not make that restriction here. | 4296 // left == right, let's not make that restriction here. |
| 4207 if (left.is(right)) { | 4297 if (left.is(right)) { |
| 4208 mov(dst, zero_reg); | 4298 mov(dst, zero_reg); |
| 4209 mov(overflow_dst, zero_reg); | 4299 mov(overflow_dst, zero_reg); |
| 4210 return; | 4300 return; |
| 4211 } | 4301 } |
| 4212 | 4302 |
| 4213 if (dst.is(left)) { | 4303 if (dst.is(left)) { |
| 4214 mov(scratch, left); // Preserve left. | 4304 mov(scratch, left); // Preserve left. |
| 4215 subu(dst, left, right); // Left is overwritten. | 4305 dsubu(dst, left, right); // Left is overwritten. |
| 4216 xor_(overflow_dst, dst, scratch); // scratch is original left. | 4306 xor_(overflow_dst, dst, scratch); // scratch is original left. |
| 4217 xor_(scratch, scratch, right); // scratch is original left. | 4307 xor_(scratch, scratch, right); // scratch is original left. |
| 4218 and_(overflow_dst, scratch, overflow_dst); | 4308 and_(overflow_dst, scratch, overflow_dst); |
| 4219 } else if (dst.is(right)) { | 4309 } else if (dst.is(right)) { |
| 4220 mov(scratch, right); // Preserve right. | 4310 mov(scratch, right); // Preserve right. |
| 4221 subu(dst, left, right); // Right is overwritten. | 4311 dsubu(dst, left, right); // Right is overwritten. |
| 4222 xor_(overflow_dst, dst, left); | 4312 xor_(overflow_dst, dst, left); |
| 4223 xor_(scratch, left, scratch); // Original right. | 4313 xor_(scratch, left, scratch); // Original right. |
| 4224 and_(overflow_dst, scratch, overflow_dst); | 4314 and_(overflow_dst, scratch, overflow_dst); |
| 4225 } else { | 4315 } else { |
| 4226 subu(dst, left, right); | 4316 dsubu(dst, left, right); |
| 4227 xor_(overflow_dst, dst, left); | 4317 xor_(overflow_dst, dst, left); |
| 4228 xor_(scratch, left, right); | 4318 xor_(scratch, left, right); |
| 4229 and_(overflow_dst, scratch, overflow_dst); | 4319 and_(overflow_dst, scratch, overflow_dst); |
| 4230 } | 4320 } |
| 4231 } | 4321 } |
| 4232 | 4322 |
| 4233 | 4323 |
| 4234 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 4324 void MacroAssembler::CallRuntime(const Runtime::Function* f, |
| 4235 int num_arguments, | 4325 int num_arguments, |
| 4236 SaveFPRegsMode save_doubles) { | 4326 SaveFPRegsMode save_doubles) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4311 } else { | 4401 } else { |
| 4312 ASSERT(flag == JUMP_FUNCTION); | 4402 ASSERT(flag == JUMP_FUNCTION); |
| 4313 Jump(t9); | 4403 Jump(t9); |
| 4314 } | 4404 } |
| 4315 } | 4405 } |
| 4316 | 4406 |
| 4317 | 4407 |
| 4318 void MacroAssembler::GetBuiltinFunction(Register target, | 4408 void MacroAssembler::GetBuiltinFunction(Register target, |
| 4319 Builtins::JavaScript id) { | 4409 Builtins::JavaScript id) { |
| 4320 // Load the builtins object into target register. | 4410 // Load the builtins object into target register. |
| 4321 lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4411 ld(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 4322 lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); | 4412 ld(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); |
| 4323 // Load the JavaScript builtin function from the builtins object. | 4413 // Load the JavaScript builtin function from the builtins object. |
| 4324 lw(target, FieldMemOperand(target, | 4414 ld(target, FieldMemOperand(target, |
| 4325 JSBuiltinsObject::OffsetOfFunctionWithId(id))); | 4415 JSBuiltinsObject::OffsetOfFunctionWithId(id))); |
| 4326 } | 4416 } |
| 4327 | 4417 |
| 4328 | 4418 |
| 4329 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { | 4419 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |
| 4330 ASSERT(!target.is(a1)); | 4420 ASSERT(!target.is(a1)); |
| 4331 GetBuiltinFunction(a1, id); | 4421 GetBuiltinFunction(a1, id); |
| 4332 // Load the code entry point from the builtins object. | 4422 // Load the code entry point from the builtins object. |
| 4333 lw(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 4423 ld(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 4334 } | 4424 } |
| 4335 | 4425 |
| 4336 | 4426 |
| 4337 void MacroAssembler::SetCounter(StatsCounter* counter, int value, | 4427 void MacroAssembler::SetCounter(StatsCounter* counter, int value, |
| 4338 Register scratch1, Register scratch2) { | 4428 Register scratch1, Register scratch2) { |
| 4339 if (FLAG_native_code_counters && counter->Enabled()) { | 4429 if (FLAG_native_code_counters && counter->Enabled()) { |
| 4340 li(scratch1, Operand(value)); | 4430 li(scratch1, Operand(value)); |
| 4341 li(scratch2, Operand(ExternalReference(counter))); | 4431 li(scratch2, Operand(ExternalReference(counter))); |
| 4342 sw(scratch1, MemOperand(scratch2)); | 4432 sd(scratch1, MemOperand(scratch2)); |
| 4343 } | 4433 } |
| 4344 } | 4434 } |
| 4345 | 4435 |
| 4346 | 4436 |
| 4347 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, | 4437 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, |
| 4348 Register scratch1, Register scratch2) { | 4438 Register scratch1, Register scratch2) { |
| 4349 ASSERT(value > 0); | 4439 ASSERT(value > 0); |
| 4350 if (FLAG_native_code_counters && counter->Enabled()) { | 4440 if (FLAG_native_code_counters && counter->Enabled()) { |
| 4351 li(scratch2, Operand(ExternalReference(counter))); | 4441 li(scratch2, Operand(ExternalReference(counter))); |
| 4352 lw(scratch1, MemOperand(scratch2)); | 4442 ld(scratch1, MemOperand(scratch2)); |
| 4353 Addu(scratch1, scratch1, Operand(value)); | 4443 Daddu(scratch1, scratch1, Operand(value)); |
| 4354 sw(scratch1, MemOperand(scratch2)); | 4444 sd(scratch1, MemOperand(scratch2)); |
| 4355 } | 4445 } |
| 4356 } | 4446 } |
| 4357 | 4447 |
| 4358 | 4448 |
| 4359 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, | 4449 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, |
| 4360 Register scratch1, Register scratch2) { | 4450 Register scratch1, Register scratch2) { |
| 4361 ASSERT(value > 0); | 4451 ASSERT(value > 0); |
| 4362 if (FLAG_native_code_counters && counter->Enabled()) { | 4452 if (FLAG_native_code_counters && counter->Enabled()) { |
| 4363 li(scratch2, Operand(ExternalReference(counter))); | 4453 li(scratch2, Operand(ExternalReference(counter))); |
| 4364 lw(scratch1, MemOperand(scratch2)); | 4454 ld(scratch1, MemOperand(scratch2)); |
| 4365 Subu(scratch1, scratch1, Operand(value)); | 4455 Dsubu(scratch1, scratch1, Operand(value)); |
| 4366 sw(scratch1, MemOperand(scratch2)); | 4456 sd(scratch1, MemOperand(scratch2)); |
| 4367 } | 4457 } |
| 4368 } | 4458 } |
| 4369 | 4459 |
| 4370 | 4460 |
| 4371 // ----------------------------------------------------------------------------- | 4461 // ----------------------------------------------------------------------------- |
| 4372 // Debugging. | 4462 // Debugging. |
| 4373 | 4463 |
| 4374 void MacroAssembler::Assert(Condition cc, BailoutReason reason, | 4464 void MacroAssembler::Assert(Condition cc, BailoutReason reason, |
| 4375 Register rs, Operand rt) { | 4465 Register rs, Operand rt) { |
| 4376 if (emit_debug_code()) | 4466 if (emit_debug_code()) |
| 4377 Check(cc, reason, rs, rt); | 4467 Check(cc, reason, rs, rt); |
| 4378 } | 4468 } |
| 4379 | 4469 |
| 4380 | 4470 |
| 4381 void MacroAssembler::AssertFastElements(Register elements) { | 4471 void MacroAssembler::AssertFastElements(Register elements) { |
| 4382 if (emit_debug_code()) { | 4472 if (emit_debug_code()) { |
| 4383 ASSERT(!elements.is(at)); | 4473 ASSERT(!elements.is(at)); |
| 4384 Label ok; | 4474 Label ok; |
| 4385 push(elements); | 4475 push(elements); |
| 4386 lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); | 4476 ld(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); |
| 4387 LoadRoot(at, Heap::kFixedArrayMapRootIndex); | 4477 LoadRoot(at, Heap::kFixedArrayMapRootIndex); |
| 4388 Branch(&ok, eq, elements, Operand(at)); | 4478 Branch(&ok, eq, elements, Operand(at)); |
| 4389 LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); | 4479 LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); |
| 4390 Branch(&ok, eq, elements, Operand(at)); | 4480 Branch(&ok, eq, elements, Operand(at)); |
| 4391 LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); | 4481 LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); |
| 4392 Branch(&ok, eq, elements, Operand(at)); | 4482 Branch(&ok, eq, elements, Operand(at)); |
| 4393 Abort(kJSObjectWithFastElementsMapHasSlowElements); | 4483 Abort(kJSObjectWithFastElementsMapHasSlowElements); |
| 4394 bind(&ok); | 4484 bind(&ok); |
| 4395 pop(elements); | 4485 pop(elements); |
| 4396 } | 4486 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4447 while (abort_instructions++ < kExpectedAbortInstructions) { | 4537 while (abort_instructions++ < kExpectedAbortInstructions) { |
| 4448 nop(); | 4538 nop(); |
| 4449 } | 4539 } |
| 4450 } | 4540 } |
| 4451 } | 4541 } |
| 4452 | 4542 |
| 4453 | 4543 |
| 4454 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 4544 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
| 4455 if (context_chain_length > 0) { | 4545 if (context_chain_length > 0) { |
| 4456 // Move up the chain of contexts to the context containing the slot. | 4546 // Move up the chain of contexts to the context containing the slot. |
| 4457 lw(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 4547 ld(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 4458 for (int i = 1; i < context_chain_length; i++) { | 4548 for (int i = 1; i < context_chain_length; i++) { |
| 4459 lw(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 4549 ld(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 4460 } | 4550 } |
| 4461 } else { | 4551 } else { |
| 4462 // Slot is in the current function context. Move it into the | 4552 // Slot is in the current function context. Move it into the |
| 4463 // destination register in case we store into it (the write barrier | 4553 // destination register in case we store into it (the write barrier |
| 4464 // cannot be allowed to destroy the context in esi). | 4554 // cannot be allowed to destroy the context in esi). |
| 4465 Move(dst, cp); | 4555 Move(dst, cp); |
| 4466 } | 4556 } |
| 4467 } | 4557 } |
| 4468 | 4558 |
| 4469 | 4559 |
| 4470 void MacroAssembler::LoadTransitionedArrayMapConditional( | 4560 void MacroAssembler::LoadTransitionedArrayMapConditional( |
| 4471 ElementsKind expected_kind, | 4561 ElementsKind expected_kind, |
| 4472 ElementsKind transitioned_kind, | 4562 ElementsKind transitioned_kind, |
| 4473 Register map_in_out, | 4563 Register map_in_out, |
| 4474 Register scratch, | 4564 Register scratch, |
| 4475 Label* no_map_match) { | 4565 Label* no_map_match) { |
| 4476 // Load the global or builtins object from the current context. | 4566 // Load the global or builtins object from the current context. |
| 4477 lw(scratch, | 4567 ld(scratch, |
| 4478 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4568 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 4479 lw(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 4569 ld(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 4480 | 4570 |
| 4481 // Check that the function's map is the same as the expected cached map. | 4571 // Check that the function's map is the same as the expected cached map. |
| 4482 lw(scratch, | 4572 ld(scratch, |
| 4483 MemOperand(scratch, | 4573 MemOperand(scratch, |
| 4484 Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX))); | 4574 Context::SlotOffset(Context::JS_ARRAY_MAPS_INDEX))); |
| 4485 size_t offset = expected_kind * kPointerSize + | 4575 size_t offset = expected_kind * kPointerSize + |
| 4486 FixedArrayBase::kHeaderSize; | 4576 FixedArrayBase::kHeaderSize; |
| 4487 lw(at, FieldMemOperand(scratch, offset)); | 4577 ld(at, FieldMemOperand(scratch, offset)); |
| 4488 Branch(no_map_match, ne, map_in_out, Operand(at)); | 4578 Branch(no_map_match, ne, map_in_out, Operand(at)); |
| 4489 | 4579 |
| 4490 // Use the transitioned cached map. | 4580 // Use the transitioned cached map. |
| 4491 offset = transitioned_kind * kPointerSize + | 4581 offset = transitioned_kind * kPointerSize + |
| 4492 FixedArrayBase::kHeaderSize; | 4582 FixedArrayBase::kHeaderSize; |
| 4493 lw(map_in_out, FieldMemOperand(scratch, offset)); | 4583 ld(map_in_out, FieldMemOperand(scratch, offset)); |
| 4494 } | 4584 } |
| 4495 | 4585 |
| 4496 | 4586 |
| 4497 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 4587 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 4498 // Load the global or builtins object from the current context. | 4588 // Load the global or builtins object from the current context. |
| 4499 lw(function, | 4589 ld(function, |
| 4500 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4590 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 4501 // Load the native context from the global or builtins object. | 4591 // Load the native context from the global or builtins object. |
| 4502 lw(function, FieldMemOperand(function, | 4592 ld(function, FieldMemOperand(function, |
| 4503 GlobalObject::kNativeContextOffset)); | 4593 GlobalObject::kNativeContextOffset)); |
| 4504 // Load the function from the native context. | 4594 // Load the function from the native context. |
| 4505 lw(function, MemOperand(function, Context::SlotOffset(index))); | 4595 ld(function, MemOperand(function, Context::SlotOffset(index))); |
| 4506 } | 4596 } |
| 4507 | 4597 |
| 4508 | 4598 |
| 4509 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 4599 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 4510 Register map, | 4600 Register map, |
| 4511 Register scratch) { | 4601 Register scratch) { |
| 4512 // Load the initial map. The global functions all have initial maps. | 4602 // Load the initial map. The global functions all have initial maps. |
| 4513 lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 4603 ld(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 4514 if (emit_debug_code()) { | 4604 if (emit_debug_code()) { |
| 4515 Label ok, fail; | 4605 Label ok, fail; |
| 4516 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); | 4606 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); |
| 4517 Branch(&ok); | 4607 Branch(&ok); |
| 4518 bind(&fail); | 4608 bind(&fail); |
| 4519 Abort(kGlobalFunctionsMustHaveInitialMap); | 4609 Abort(kGlobalFunctionsMustHaveInitialMap); |
| 4520 bind(&ok); | 4610 bind(&ok); |
| 4521 } | 4611 } |
| 4522 } | 4612 } |
| 4523 | 4613 |
| 4524 | 4614 |
| 4525 void MacroAssembler::StubPrologue() { | 4615 void MacroAssembler::StubPrologue() { |
| 4526 Push(ra, fp, cp); | 4616 Push(ra, fp, cp); |
| 4527 Push(Smi::FromInt(StackFrame::STUB)); | 4617 Push(Smi::FromInt(StackFrame::STUB)); |
| 4528 // Adjust FP to point to saved FP. | 4618 // Adjust FP to point to saved FP. |
| 4529 Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | 4619 Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 4530 } | 4620 } |
| 4531 | 4621 |
| 4532 | 4622 |
| 4533 void MacroAssembler::Prologue(bool code_pre_aging) { | 4623 void MacroAssembler::Prologue(bool code_pre_aging) { |
| 4534 PredictableCodeSizeScope predictible_code_size_scope( | 4624 PredictableCodeSizeScope predictible_code_size_scope( |
| 4535 this, kNoCodeAgeSequenceLength); | 4625 this, kNoCodeAgeSequenceLength); |
| 4536 // The following three instructions must remain together and unmodified | 4626 // The following three instructions must remain together and unmodified |
| 4537 // for code aging to work properly. | 4627 // for code aging to work properly. |
| 4538 if (code_pre_aging) { | 4628 if (code_pre_aging) { |
| 4539 // Pre-age the code. | 4629 // Pre-age the code. |
| 4540 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 4630 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
| 4541 nop(Assembler::CODE_AGE_MARKER_NOP); | 4631 nop(Assembler::CODE_AGE_MARKER_NOP); |
| 4542 // Load the stub address to t9 and call it, | 4632 // Load the stub address to t9 and call it, |
| 4543 // GetCodeAgeAndParity() extracts the stub address from this instruction. | 4633 // GetCodeAgeAndParity() extracts the stub address from this instruction. |
| 4544 li(t9, | 4634 li(t9, |
| 4545 Operand(reinterpret_cast<uint32_t>(stub->instruction_start())), | 4635 Operand(reinterpret_cast<uint64_t>(stub->instruction_start())), |
| 4546 CONSTANT_SIZE); | 4636 ADDRESS_LOAD); |
| 4547 nop(); // Prevent jalr to jal optimization. | 4637 nop(); // Prevent jalr to jal optimization. |
| 4548 jalr(t9, a0); | 4638 jalr(t9, a0); |
| 4549 nop(); // Branch delay slot nop. | 4639 nop(); // Branch delay slot nop. |
| 4550 nop(); // Pad the empty space. | 4640 nop(); // Pad the empty space. |
| 4551 } else { | 4641 } else { |
| 4552 Push(ra, fp, cp, a1); | 4642 Push(ra, fp, cp, a1); |
| 4553 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 4643 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 4644 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 4645 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 4554 // Adjust fp to point to caller's fp. | 4646 // Adjust fp to point to caller's fp. |
| 4555 Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | 4647 Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
| 4556 } | 4648 } |
| 4557 } | 4649 } |
| 4558 | 4650 |
| 4559 | 4651 |
| 4560 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 4652 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 4561 addiu(sp, sp, -5 * kPointerSize); | 4653 daddiu(sp, sp, -5 * kPointerSize); |
| 4562 li(t8, Operand(Smi::FromInt(type))); | 4654 li(t8, Operand(Smi::FromInt(type))); |
| 4563 li(t9, Operand(CodeObject()), CONSTANT_SIZE); | 4655 li(t9, Operand(CodeObject()), CONSTANT_SIZE); |
| 4564 sw(ra, MemOperand(sp, 4 * kPointerSize)); | 4656 sd(ra, MemOperand(sp, 4 * kPointerSize)); |
| 4565 sw(fp, MemOperand(sp, 3 * kPointerSize)); | 4657 sd(fp, MemOperand(sp, 3 * kPointerSize)); |
| 4566 sw(cp, MemOperand(sp, 2 * kPointerSize)); | 4658 sd(cp, MemOperand(sp, 2 * kPointerSize)); |
| 4567 sw(t8, MemOperand(sp, 1 * kPointerSize)); | 4659 sd(t8, MemOperand(sp, 1 * kPointerSize)); |
| 4568 sw(t9, MemOperand(sp, 0 * kPointerSize)); | 4660 sd(t9, MemOperand(sp, 0 * kPointerSize)); |
| 4569 // Adjust FP to point to saved FP. | 4661 // Adjust FP to point to saved FP. |
| 4570 Addu(fp, sp, | 4662 Daddu(fp, sp, |
| 4571 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); | 4663 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); |
| 4572 } | 4664 } |
| 4573 | 4665 |
| 4574 | 4666 |
| 4575 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 4667 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 4576 mov(sp, fp); | 4668 mov(sp, fp); |
| 4577 lw(fp, MemOperand(sp, 0 * kPointerSize)); | 4669 ld(fp, MemOperand(sp, 0 * kPointerSize)); |
| 4578 lw(ra, MemOperand(sp, 1 * kPointerSize)); | 4670 ld(ra, MemOperand(sp, 1 * kPointerSize)); |
| 4579 addiu(sp, sp, 2 * kPointerSize); | 4671 daddiu(sp, sp, 2 * kPointerSize); |
| 4580 } | 4672 } |
| 4581 | 4673 |
| 4582 | 4674 |
| 4583 void MacroAssembler::EnterExitFrame(bool save_doubles, | 4675 void MacroAssembler::EnterExitFrame(bool save_doubles, |
| 4584 int stack_space) { | 4676 int stack_space) { |
| 4585 // Set up the frame structure on the stack. | 4677 // Set up the frame structure on the stack. |
| 4586 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); | 4678 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); |
| 4587 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); | 4679 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); |
| 4588 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); | 4680 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); |
| 4589 | 4681 |
| 4590 // This is how the stack will look: | 4682 // This is how the stack will look: |
| 4591 // fp + 2 (==kCallerSPDisplacement) - old stack's end | 4683 // fp + 2 (==kCallerSPDisplacement) - old stack's end |
| 4592 // [fp + 1 (==kCallerPCOffset)] - saved old ra | 4684 // [fp + 1 (==kCallerPCOffset)] - saved old ra |
| 4593 // [fp + 0 (==kCallerFPOffset)] - saved old fp | 4685 // [fp + 0 (==kCallerFPOffset)] - saved old fp |
| 4594 // [fp - 1 (==kSPOffset)] - sp of the called function | 4686 // [fp - 1 (==kSPOffset)] - sp of the called function |
| 4595 // [fp - 2 (==kCodeOffset)] - CodeObject | 4687 // [fp - 2 (==kCodeOffset)] - CodeObject |
| 4596 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the | 4688 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the |
| 4597 // new stack (will contain saved ra) | 4689 // new stack (will contain saved ra) |
| 4598 | 4690 |
| 4599 // Save registers. | 4691 // Save registers. |
| 4600 addiu(sp, sp, -4 * kPointerSize); | 4692 daddiu(sp, sp, -4 * kPointerSize); |
| 4601 sw(ra, MemOperand(sp, 3 * kPointerSize)); | 4693 sd(ra, MemOperand(sp, 3 * kPointerSize)); |
| 4602 sw(fp, MemOperand(sp, 2 * kPointerSize)); | 4694 sd(fp, MemOperand(sp, 2 * kPointerSize)); |
| 4603 addiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer. | 4695 daddiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer. |
| 4604 | 4696 |
| 4605 if (emit_debug_code()) { | 4697 if (emit_debug_code()) { |
| 4606 sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 4698 sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
| 4607 } | 4699 } |
| 4608 | 4700 |
| 4609 // Accessed from ExitFrame::code_slot. | 4701 // Accessed from ExitFrame::code_slot. |
| 4610 li(t8, Operand(CodeObject()), CONSTANT_SIZE); | 4702 li(t8, Operand(CodeObject()), CONSTANT_SIZE); |
| 4611 sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 4703 sd(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
| 4612 | 4704 |
| 4613 // Save the frame pointer and the context in top. | 4705 // Save the frame pointer and the context in top. |
| 4614 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 4706 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
| 4615 sw(fp, MemOperand(t8)); | 4707 sd(fp, MemOperand(t8)); |
| 4616 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 4708 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
| 4617 sw(cp, MemOperand(t8)); | 4709 sd(cp, MemOperand(t8)); |
| 4618 | 4710 |
| 4619 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); | 4711 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
| 4620 if (save_doubles) { | 4712 if (save_doubles) { |
| 4621 // The stack must be allign to 0 modulo 8 for stores with sdc1. | 4713 // The stack is already aligned to 0 modulo 8 for stores with sdc1. |
| 4622 ASSERT(kDoubleSize == frame_alignment); | 4714 int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2; |
| 4623 if (frame_alignment > 0) { | 4715 int space = kNumOfSavedRegisters * kDoubleSize ; |
| 4624 ASSERT(IsPowerOf2(frame_alignment)); | 4716 Dsubu(sp, sp, Operand(space)); |
| 4625 And(sp, sp, Operand(-frame_alignment)); // Align stack. | |
| 4626 } | |
| 4627 int space = FPURegister::kMaxNumRegisters * kDoubleSize; | |
| 4628 Subu(sp, sp, Operand(space)); | |
| 4629 // Remember: we only need to save every 2nd double FPU value. | 4717 // Remember: we only need to save every 2nd double FPU value. |
| 4630 for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) { | 4718 for (int i = 0; i < kNumOfSavedRegisters; i++) { |
| 4631 FPURegister reg = FPURegister::from_code(i); | 4719 FPURegister reg = FPURegister::from_code(2 * i); |
| 4632 sdc1(reg, MemOperand(sp, i * kDoubleSize)); | 4720 sdc1(reg, MemOperand(sp, i * kDoubleSize)); |
| 4633 } | 4721 } |
| 4634 } | 4722 } |
| 4635 | 4723 |
| 4636 // Reserve place for the return address, stack space and an optional slot | 4724 // Reserve place for the return address, stack space and an optional slot |
| 4637 // (used by the DirectCEntryStub to hold the return value if a struct is | 4725 // (used by the DirectCEntryStub to hold the return value if a struct is |
| 4638 // returned) and align the frame preparing for calling the runtime function. | 4726 // returned) and align the frame preparing for calling the runtime function. |
| 4639 ASSERT(stack_space >= 0); | 4727 ASSERT(stack_space >= 0); |
| 4640 Subu(sp, sp, Operand((stack_space + 2) * kPointerSize)); | 4728 Dsubu(sp, sp, Operand((stack_space + 2) * kPointerSize)); |
| 4641 if (frame_alignment > 0) { | 4729 if (frame_alignment > 0) { |
| 4642 ASSERT(IsPowerOf2(frame_alignment)); | 4730 ASSERT(IsPowerOf2(frame_alignment)); |
| 4643 And(sp, sp, Operand(-frame_alignment)); // Align stack. | 4731 And(sp, sp, Operand(-frame_alignment)); // Align stack. |
| 4644 } | 4732 } |
| 4645 | 4733 |
| 4646 // Set the exit frame sp value to point just before the return address | 4734 // Set the exit frame sp value to point just before the return address |
| 4647 // location. | 4735 // location. |
| 4648 addiu(at, sp, kPointerSize); | 4736 daddiu(at, sp, kPointerSize); |
| 4649 sw(at, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 4737 sd(at, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
| 4650 } | 4738 } |
| 4651 | 4739 |
| 4652 | 4740 |
| 4653 void MacroAssembler::LeaveExitFrame(bool save_doubles, | 4741 void MacroAssembler::LeaveExitFrame(bool save_doubles, |
| 4654 Register argument_count, | 4742 Register argument_count, |
| 4655 bool restore_context, | 4743 bool restore_context, |
| 4656 bool do_return) { | 4744 bool do_return) { |
| 4657 // Optionally restore all double registers. | 4745 // Optionally restore all double registers. |
| 4658 if (save_doubles) { | 4746 if (save_doubles) { |
| 4659 // Remember: we only need to restore every 2nd double FPU value. | 4747 // Remember: we only need to restore every 2nd double FPU value. |
| 4660 lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 4748 int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2; |
| 4661 for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) { | 4749 Dsubu(t8, fp, Operand(ExitFrameConstants::kFrameSize + |
| 4662 FPURegister reg = FPURegister::from_code(i); | 4750 kNumOfSavedRegisters * kDoubleSize)); |
| 4663 ldc1(reg, MemOperand(t8, i * kDoubleSize + kPointerSize)); | 4751 for (int i = 0; i < kNumOfSavedRegisters; i++) { |
| 4752 FPURegister reg = FPURegister::from_code(2 * i); |
| 4753 ldc1(reg, MemOperand(t8, i * kDoubleSize)); |
| 4664 } | 4754 } |
| 4665 } | 4755 } |
| 4666 | 4756 |
| 4667 // Clear top frame. | 4757 // Clear top frame. |
| 4668 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 4758 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
| 4669 sw(zero_reg, MemOperand(t8)); | 4759 sd(zero_reg, MemOperand(t8)); |
| 4670 | 4760 |
| 4671 // Restore current context from top and clear it in debug mode. | 4761 // Restore current context from top and clear it in debug mode. |
| 4672 if (restore_context) { | 4762 if (restore_context) { |
| 4673 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 4763 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
| 4674 lw(cp, MemOperand(t8)); | 4764 ld(cp, MemOperand(t8)); |
| 4675 } | 4765 } |
| 4676 #ifdef DEBUG | 4766 #ifdef DEBUG |
| 4677 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 4767 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
| 4678 sw(a3, MemOperand(t8)); | 4768 sd(a3, MemOperand(t8)); |
| 4679 #endif | 4769 #endif |
| 4680 | 4770 |
| 4681 // Pop the arguments, restore registers, and return. | 4771 // Pop the arguments, restore registers, and return. |
| 4682 mov(sp, fp); // Respect ABI stack constraint. | 4772 mov(sp, fp); // Respect ABI stack constraint. |
| 4683 lw(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset)); | 4773 ld(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset)); |
| 4684 lw(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset)); | 4774 ld(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset)); |
| 4685 | 4775 |
| 4686 if (argument_count.is_valid()) { | 4776 if (argument_count.is_valid()) { |
| 4687 sll(t8, argument_count, kPointerSizeLog2); | 4777 dsll(t8, argument_count, kPointerSizeLog2); |
| 4688 addu(sp, sp, t8); | 4778 daddu(sp, sp, t8); |
| 4689 } | 4779 } |
| 4690 | 4780 |
| 4691 if (do_return) { | 4781 if (do_return) { |
| 4692 Ret(USE_DELAY_SLOT); | 4782 Ret(USE_DELAY_SLOT); |
| 4693 // If returning, the instruction in the delay slot will be the addiu below. | 4783 // If returning, the instruction in the delay slot will be the addiu below. |
| 4694 } | 4784 } |
| 4695 addiu(sp, sp, 8); | 4785 daddiu(sp, sp, 2 * kPointerSize); |
| 4696 } | 4786 } |
| 4697 | 4787 |
| 4698 | 4788 |
| 4699 void MacroAssembler::InitializeNewString(Register string, | 4789 void MacroAssembler::InitializeNewString(Register string, |
| 4700 Register length, | 4790 Register length, |
| 4701 Heap::RootListIndex map_index, | 4791 Heap::RootListIndex map_index, |
| 4702 Register scratch1, | 4792 Register scratch1, |
| 4703 Register scratch2) { | 4793 Register scratch2) { |
| 4704 sll(scratch1, length, kSmiTagSize); | 4794 // dsll(scratch1, length, kSmiTagSize); |
| 4795 dsll32(scratch1, length, 0); |
| 4705 LoadRoot(scratch2, map_index); | 4796 LoadRoot(scratch2, map_index); |
| 4706 sw(scratch1, FieldMemOperand(string, String::kLengthOffset)); | 4797 sd(scratch1, FieldMemOperand(string, String::kLengthOffset)); |
| 4707 li(scratch1, Operand(String::kEmptyHashField)); | 4798 li(scratch1, Operand(String::kEmptyHashField)); |
| 4708 sw(scratch2, FieldMemOperand(string, HeapObject::kMapOffset)); | 4799 sd(scratch2, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 4709 sw(scratch1, FieldMemOperand(string, String::kHashFieldOffset)); | 4800 sd(scratch1, FieldMemOperand(string, String::kHashFieldOffset)); |
| 4710 } | 4801 } |
| 4711 | 4802 |
| 4712 | 4803 |
| 4713 int MacroAssembler::ActivationFrameAlignment() { | 4804 int MacroAssembler::ActivationFrameAlignment() { |
| 4714 #if V8_HOST_ARCH_MIPS | 4805 #if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 |
| 4715 // Running on the real platform. Use the alignment as mandated by the local | 4806 // Running on the real platform. Use the alignment as mandated by the local |
| 4716 // environment. | 4807 // environment. |
| 4717 // Note: This will break if we ever start generating snapshots on one Mips | 4808 // Note: This will break if we ever start generating snapshots on one Mips |
| 4718 // platform for another Mips platform with a different alignment. | 4809 // platform for another Mips platform with a different alignment. |
| 4719 return base::OS::ActivationFrameAlignment(); | 4810 return base::OS::ActivationFrameAlignment(); |
| 4720 #else // V8_HOST_ARCH_MIPS | 4811 #else // V8_HOST_ARCH_MIPS |
| 4721 // If we are using the simulator then we should always align to the expected | 4812 // If we are using the simulator then we should always align to the expected |
| 4722 // alignment. As the simulator is used to generate snapshots we do not know | 4813 // alignment. As the simulator is used to generate snapshots we do not know |
| 4723 // if the target platform will need alignment, so this is controlled from a | 4814 // if the target platform will need alignment, so this is controlled from a |
| 4724 // flag. | 4815 // flag. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4742 bind(&alignment_as_expected); | 4833 bind(&alignment_as_expected); |
| 4743 } | 4834 } |
| 4744 } | 4835 } |
| 4745 } | 4836 } |
| 4746 | 4837 |
| 4747 | 4838 |
| 4748 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( | 4839 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( |
| 4749 Register reg, | 4840 Register reg, |
| 4750 Register scratch, | 4841 Register scratch, |
| 4751 Label* not_power_of_two_or_zero) { | 4842 Label* not_power_of_two_or_zero) { |
| 4752 Subu(scratch, reg, Operand(1)); | 4843 Dsubu(scratch, reg, Operand(1)); |
| 4753 Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt, | 4844 Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt, |
| 4754 scratch, Operand(zero_reg)); | 4845 scratch, Operand(zero_reg)); |
| 4755 and_(at, scratch, reg); // In the delay slot. | 4846 and_(at, scratch, reg); // In the delay slot. |
| 4756 Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg)); | 4847 Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg)); |
| 4757 } | 4848 } |
| 4758 | 4849 |
| 4759 | 4850 |
| 4760 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) { | 4851 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) { |
| 4761 ASSERT(!reg.is(overflow)); | 4852 ASSERT(!reg.is(overflow)); |
| 4762 mov(overflow, reg); // Save original value. | 4853 mov(overflow, reg); // Save original value. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4774 } else { | 4865 } else { |
| 4775 ASSERT(!dst.is(src)); | 4866 ASSERT(!dst.is(src)); |
| 4776 ASSERT(!dst.is(overflow)); | 4867 ASSERT(!dst.is(overflow)); |
| 4777 ASSERT(!src.is(overflow)); | 4868 ASSERT(!src.is(overflow)); |
| 4778 SmiTag(dst, src); | 4869 SmiTag(dst, src); |
| 4779 xor_(overflow, dst, src); // Overflow if (value ^ 2 * value) < 0. | 4870 xor_(overflow, dst, src); // Overflow if (value ^ 2 * value) < 0. |
| 4780 } | 4871 } |
| 4781 } | 4872 } |
| 4782 | 4873 |
| 4783 | 4874 |
| 4875 void MacroAssembler::SmiLoadUntag(Register dst, MemOperand src) { |
| 4876 if (SmiValuesAre32Bits()) { |
| 4877 lw(dst, UntagSmiMemOperand(src.rm(), src.offset())); |
| 4878 } else { |
| 4879 lw(dst, src); |
| 4880 SmiUntag(dst); |
| 4881 } |
| 4882 } |
| 4883 |
| 4884 |
| 4885 void MacroAssembler::SmiLoadScale(Register dst, MemOperand src, int scale) { |
| 4886 if (SmiValuesAre32Bits()) { |
| 4887 // TODO(plind): not clear if lw or ld faster here, need micro-benchmark. |
| 4888 lw(dst, UntagSmiMemOperand(src.rm(), src.offset())); |
| 4889 dsll(dst, dst, scale); |
| 4890 } else { |
| 4891 lw(dst, src); |
| 4892 ASSERT(scale >= kSmiTagSize); |
| 4893 sll(dst, dst, scale - kSmiTagSize); |
| 4894 } |
| 4895 } |
| 4896 |
| 4897 |
| 4898 // Returns 2 values: the Smi and a scaled version of the int within the Smi. |
| 4899 void MacroAssembler::SmiLoadWithScale(Register d_smi, |
| 4900 Register d_scaled, |
| 4901 MemOperand src, |
| 4902 int scale) { |
| 4903 if (SmiValuesAre32Bits()) { |
| 4904 ld(d_smi, src); |
| 4905 dsra(d_scaled, d_smi, kSmiShift - scale); |
| 4906 } else { |
| 4907 lw(d_smi, src); |
| 4908 ASSERT(scale >= kSmiTagSize); |
| 4909 sll(d_scaled, d_smi, scale - kSmiTagSize); |
| 4910 } |
| 4911 } |
| 4912 |
| 4913 |
| 4914 // Returns 2 values: the untagged Smi (int32) and scaled version of that int. |
| 4915 void MacroAssembler::SmiLoadUntagWithScale(Register d_int, |
| 4916 Register d_scaled, |
| 4917 MemOperand src, |
| 4918 int scale) { |
| 4919 if (SmiValuesAre32Bits()) { |
| 4920 lw(d_int, UntagSmiMemOperand(src.rm(), src.offset())); |
| 4921 dsll(d_scaled, d_int, scale); |
| 4922 } else { |
| 4923 lw(d_int, src); |
| 4924 // Need both the int and the scaled in, so use two instructions. |
| 4925 SmiUntag(d_int); |
| 4926 sll(d_scaled, d_int, scale); |
| 4927 } |
| 4928 } |
| 4929 |
| 4930 |
| 4784 void MacroAssembler::UntagAndJumpIfSmi(Register dst, | 4931 void MacroAssembler::UntagAndJumpIfSmi(Register dst, |
| 4785 Register src, | 4932 Register src, |
| 4786 Label* smi_case) { | 4933 Label* smi_case) { |
| 4934 // ASSERT(!dst.is(src)); |
| 4787 JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT); | 4935 JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT); |
| 4788 SmiUntag(dst, src); | 4936 SmiUntag(dst, src); |
| 4789 } | 4937 } |
| 4790 | 4938 |
| 4791 | 4939 |
| 4792 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, | 4940 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, |
| 4793 Register src, | 4941 Register src, |
| 4794 Label* non_smi_case) { | 4942 Label* non_smi_case) { |
| 4943 // ASSERT(!dst.is(src)); |
| 4795 JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT); | 4944 JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT); |
| 4796 SmiUntag(dst, src); | 4945 SmiUntag(dst, src); |
| 4797 } | 4946 } |
| 4798 | 4947 |
| 4799 void MacroAssembler::JumpIfSmi(Register value, | 4948 void MacroAssembler::JumpIfSmi(Register value, |
| 4800 Label* smi_label, | 4949 Label* smi_label, |
| 4801 Register scratch, | 4950 Register scratch, |
| 4802 BranchDelaySlot bd) { | 4951 BranchDelaySlot bd) { |
| 4803 ASSERT_EQ(0, kSmiTag); | 4952 ASSERT_EQ(0, kSmiTag); |
| 4804 andi(scratch, value, kSmiTagMask); | 4953 andi(scratch, value, kSmiTagMask); |
| 4805 Branch(bd, smi_label, eq, scratch, Operand(zero_reg)); | 4954 Branch(bd, smi_label, eq, scratch, Operand(zero_reg)); |
| 4806 } | 4955 } |
| 4807 | 4956 |
| 4808 void MacroAssembler::JumpIfNotSmi(Register value, | 4957 void MacroAssembler::JumpIfNotSmi(Register value, |
| 4809 Label* not_smi_label, | 4958 Label* not_smi_label, |
| 4810 Register scratch, | 4959 Register scratch, |
| 4811 BranchDelaySlot bd) { | 4960 BranchDelaySlot bd) { |
| 4812 ASSERT_EQ(0, kSmiTag); | 4961 ASSERT_EQ(0, kSmiTag); |
| 4813 andi(scratch, value, kSmiTagMask); | 4962 andi(scratch, value, kSmiTagMask); |
| 4814 Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg)); | 4963 Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg)); |
| 4815 } | 4964 } |
| 4816 | 4965 |
| 4817 | 4966 |
| 4818 void MacroAssembler::JumpIfNotBothSmi(Register reg1, | 4967 void MacroAssembler::JumpIfNotBothSmi(Register reg1, |
| 4819 Register reg2, | 4968 Register reg2, |
| 4820 Label* on_not_both_smi) { | 4969 Label* on_not_both_smi) { |
| 4821 STATIC_ASSERT(kSmiTag == 0); | 4970 STATIC_ASSERT(kSmiTag == 0); |
| 4971 // TODO(plind): Find some better to fix this assert issue. |
| 4972 #if defined(__APPLE__) |
| 4822 ASSERT_EQ(1, kSmiTagMask); | 4973 ASSERT_EQ(1, kSmiTagMask); |
| 4974 #else |
| 4975 ASSERT_EQ((uint64_t)1, kSmiTagMask); |
| 4976 #endif |
| 4823 or_(at, reg1, reg2); | 4977 or_(at, reg1, reg2); |
| 4824 JumpIfNotSmi(at, on_not_both_smi); | 4978 JumpIfNotSmi(at, on_not_both_smi); |
| 4825 } | 4979 } |
| 4826 | 4980 |
| 4827 | 4981 |
| 4828 void MacroAssembler::JumpIfEitherSmi(Register reg1, | 4982 void MacroAssembler::JumpIfEitherSmi(Register reg1, |
| 4829 Register reg2, | 4983 Register reg2, |
| 4830 Label* on_either_smi) { | 4984 Label* on_either_smi) { |
| 4831 STATIC_ASSERT(kSmiTag == 0); | 4985 STATIC_ASSERT(kSmiTag == 0); |
| 4986 // TODO(plind): Find some better to fix this assert issue. |
| 4987 #if defined(__APPLE__) |
| 4832 ASSERT_EQ(1, kSmiTagMask); | 4988 ASSERT_EQ(1, kSmiTagMask); |
| 4989 #else |
| 4990 ASSERT_EQ((uint64_t)1, kSmiTagMask); |
| 4991 #endif |
| 4833 // Both Smi tags must be 1 (not Smi). | 4992 // Both Smi tags must be 1 (not Smi). |
| 4834 and_(at, reg1, reg2); | 4993 and_(at, reg1, reg2); |
| 4835 JumpIfSmi(at, on_either_smi); | 4994 JumpIfSmi(at, on_either_smi); |
| 4836 } | 4995 } |
| 4837 | 4996 |
| 4838 | 4997 |
| 4839 void MacroAssembler::AssertNotSmi(Register object) { | 4998 void MacroAssembler::AssertNotSmi(Register object) { |
| 4840 if (emit_debug_code()) { | 4999 if (emit_debug_code()) { |
| 4841 STATIC_ASSERT(kSmiTag == 0); | 5000 STATIC_ASSERT(kSmiTag == 0); |
| 4842 andi(at, object, kSmiTagMask); | 5001 andi(at, object, kSmiTagMask); |
| 4843 Check(ne, kOperandIsASmi, at, Operand(zero_reg)); | 5002 Check(ne, kOperandIsASmi, at, Operand(zero_reg)); |
| 4844 } | 5003 } |
| 4845 } | 5004 } |
| 4846 | 5005 |
| 4847 | 5006 |
| 4848 void MacroAssembler::AssertSmi(Register object) { | 5007 void MacroAssembler::AssertSmi(Register object) { |
| 4849 if (emit_debug_code()) { | 5008 if (emit_debug_code()) { |
| 4850 STATIC_ASSERT(kSmiTag == 0); | 5009 STATIC_ASSERT(kSmiTag == 0); |
| 4851 andi(at, object, kSmiTagMask); | 5010 andi(at, object, kSmiTagMask); |
| 4852 Check(eq, kOperandIsASmi, at, Operand(zero_reg)); | 5011 Check(eq, kOperandIsASmi, at, Operand(zero_reg)); |
| 4853 } | 5012 } |
| 4854 } | 5013 } |
| 4855 | 5014 |
| 4856 | 5015 |
| 4857 void MacroAssembler::AssertString(Register object) { | 5016 void MacroAssembler::AssertString(Register object) { |
| 4858 if (emit_debug_code()) { | 5017 if (emit_debug_code()) { |
| 4859 STATIC_ASSERT(kSmiTag == 0); | 5018 STATIC_ASSERT(kSmiTag == 0); |
| 4860 SmiTst(object, t0); | 5019 SmiTst(object, a4); |
| 4861 Check(ne, kOperandIsASmiAndNotAString, t0, Operand(zero_reg)); | 5020 Check(ne, kOperandIsASmiAndNotAString, a4, Operand(zero_reg)); |
| 4862 push(object); | 5021 push(object); |
| 4863 lw(object, FieldMemOperand(object, HeapObject::kMapOffset)); | 5022 ld(object, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4864 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); | 5023 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); |
| 4865 Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE)); | 5024 Check(lo, kOperandIsNotAString, object, Operand(FIRST_NONSTRING_TYPE)); |
| 4866 pop(object); | 5025 pop(object); |
| 4867 } | 5026 } |
| 4868 } | 5027 } |
| 4869 | 5028 |
| 4870 | 5029 |
| 4871 void MacroAssembler::AssertName(Register object) { | 5030 void MacroAssembler::AssertName(Register object) { |
| 4872 if (emit_debug_code()) { | 5031 if (emit_debug_code()) { |
| 4873 STATIC_ASSERT(kSmiTag == 0); | 5032 STATIC_ASSERT(kSmiTag == 0); |
| 4874 SmiTst(object, t0); | 5033 SmiTst(object, a4); |
| 4875 Check(ne, kOperandIsASmiAndNotAName, t0, Operand(zero_reg)); | 5034 Check(ne, kOperandIsASmiAndNotAName, a4, Operand(zero_reg)); |
| 4876 push(object); | 5035 push(object); |
| 4877 lw(object, FieldMemOperand(object, HeapObject::kMapOffset)); | 5036 ld(object, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4878 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); | 5037 lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset)); |
| 4879 Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE)); | 5038 Check(le, kOperandIsNotAName, object, Operand(LAST_NAME_TYPE)); |
| 4880 pop(object); | 5039 pop(object); |
| 4881 } | 5040 } |
| 4882 } | 5041 } |
| 4883 | 5042 |
| 4884 | 5043 |
| 4885 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object, | 5044 void MacroAssembler::AssertUndefinedOrAllocationSite(Register object, |
| 4886 Register scratch) { | 5045 Register scratch) { |
| 4887 if (emit_debug_code()) { | 5046 if (emit_debug_code()) { |
| 4888 Label done_checking; | 5047 Label done_checking; |
| 4889 AssertNotSmi(object); | 5048 AssertNotSmi(object); |
| 4890 LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 5049 LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 4891 Branch(&done_checking, eq, object, Operand(scratch)); | 5050 Branch(&done_checking, eq, object, Operand(scratch)); |
| 4892 push(object); | 5051 push(object); |
| 4893 lw(object, FieldMemOperand(object, HeapObject::kMapOffset)); | 5052 ld(object, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4894 LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex); | 5053 LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex); |
| 4895 Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch)); | 5054 Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch)); |
| 4896 pop(object); | 5055 pop(object); |
| 4897 bind(&done_checking); | 5056 bind(&done_checking); |
| 4898 } | 5057 } |
| 4899 } | 5058 } |
| 4900 | 5059 |
| 4901 | 5060 |
| 4902 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { | 5061 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { |
| 4903 if (emit_debug_code()) { | 5062 if (emit_debug_code()) { |
| 4904 ASSERT(!reg.is(at)); | 5063 ASSERT(!reg.is(at)); |
| 4905 LoadRoot(at, index); | 5064 LoadRoot(at, index); |
| 4906 Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at)); | 5065 Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at)); |
| 4907 } | 5066 } |
| 4908 } | 5067 } |
| 4909 | 5068 |
| 4910 | 5069 |
| 4911 void MacroAssembler::JumpIfNotHeapNumber(Register object, | 5070 void MacroAssembler::JumpIfNotHeapNumber(Register object, |
| 4912 Register heap_number_map, | 5071 Register heap_number_map, |
| 4913 Register scratch, | 5072 Register scratch, |
| 4914 Label* on_not_heap_number) { | 5073 Label* on_not_heap_number) { |
| 4915 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 5074 ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4916 AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 5075 AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 4917 Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map)); | 5076 Branch(on_not_heap_number, ne, scratch, Operand(heap_number_map)); |
| 4918 } | 5077 } |
| 4919 | 5078 |
| 4920 | 5079 |
| 4921 void MacroAssembler::LookupNumberStringCache(Register object, | 5080 void MacroAssembler::LookupNumberStringCache(Register object, |
| 4922 Register result, | 5081 Register result, |
| 4923 Register scratch1, | 5082 Register scratch1, |
| 4924 Register scratch2, | 5083 Register scratch2, |
| 4925 Register scratch3, | 5084 Register scratch3, |
| 4926 Label* not_found) { | 5085 Label* not_found) { |
| 4927 // Use of registers. Register result is used as a temporary. | 5086 // Use of registers. Register result is used as a temporary. |
| 4928 Register number_string_cache = result; | 5087 Register number_string_cache = result; |
| 4929 Register mask = scratch3; | 5088 Register mask = scratch3; |
| 4930 | 5089 |
| 4931 // Load the number string cache. | 5090 // Load the number string cache. |
| 4932 LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); | 5091 LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
| 4933 | 5092 |
| 4934 // Make the hash mask from the length of the number string cache. It | 5093 // Make the hash mask from the length of the number string cache. It |
| 4935 // contains two elements (number and string) for each cache entry. | 5094 // contains two elements (number and string) for each cache entry. |
| 4936 lw(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); | 5095 ld(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 4937 // Divide length by two (length is a smi). | 5096 // Divide length by two (length is a smi). |
| 4938 sra(mask, mask, kSmiTagSize + 1); | 5097 // dsra(mask, mask, kSmiTagSize + 1); |
| 4939 Addu(mask, mask, -1); // Make mask. | 5098 dsra32(mask, mask, 1); |
| 5099 Daddu(mask, mask, -1); // Make mask. |
| 4940 | 5100 |
| 4941 // Calculate the entry in the number string cache. The hash value in the | 5101 // Calculate the entry in the number string cache. The hash value in the |
| 4942 // number string cache for smis is just the smi value, and the hash for | 5102 // number string cache for smis is just the smi value, and the hash for |
| 4943 // doubles is the xor of the upper and lower words. See | 5103 // doubles is the xor of the upper and lower words. See |
| 4944 // Heap::GetNumberStringCache. | 5104 // Heap::GetNumberStringCache. |
| 4945 Label is_smi; | 5105 Label is_smi; |
| 4946 Label load_result_from_cache; | 5106 Label load_result_from_cache; |
| 4947 JumpIfSmi(object, &is_smi); | 5107 JumpIfSmi(object, &is_smi); |
| 4948 CheckMap(object, | 5108 CheckMap(object, |
| 4949 scratch1, | 5109 scratch1, |
| 4950 Heap::kHeapNumberMapRootIndex, | 5110 Heap::kHeapNumberMapRootIndex, |
| 4951 not_found, | 5111 not_found, |
| 4952 DONT_DO_SMI_CHECK); | 5112 DONT_DO_SMI_CHECK); |
| 4953 | 5113 |
| 4954 STATIC_ASSERT(8 == kDoubleSize); | 5114 STATIC_ASSERT(8 == kDoubleSize); |
| 4955 Addu(scratch1, | 5115 Daddu(scratch1, |
| 4956 object, | 5116 object, |
| 4957 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); | 5117 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); |
| 4958 lw(scratch2, MemOperand(scratch1, kPointerSize)); | 5118 ld(scratch2, MemOperand(scratch1, kPointerSize)); |
| 4959 lw(scratch1, MemOperand(scratch1, 0)); | 5119 ld(scratch1, MemOperand(scratch1, 0)); |
| 4960 Xor(scratch1, scratch1, Operand(scratch2)); | 5120 Xor(scratch1, scratch1, Operand(scratch2)); |
| 4961 And(scratch1, scratch1, Operand(mask)); | 5121 And(scratch1, scratch1, Operand(mask)); |
| 4962 | 5122 |
| 4963 // Calculate address of entry in string cache: each entry consists | 5123 // Calculate address of entry in string cache: each entry consists |
| 4964 // of two pointer sized fields. | 5124 // of two pointer sized fields. |
| 4965 sll(scratch1, scratch1, kPointerSizeLog2 + 1); | 5125 dsll(scratch1, scratch1, kPointerSizeLog2 + 1); |
| 4966 Addu(scratch1, number_string_cache, scratch1); | 5126 Daddu(scratch1, number_string_cache, scratch1); |
| 4967 | 5127 |
| 4968 Register probe = mask; | 5128 Register probe = mask; |
| 4969 lw(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); | 5129 ld(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); |
| 4970 JumpIfSmi(probe, not_found); | 5130 JumpIfSmi(probe, not_found); |
| 4971 ldc1(f12, FieldMemOperand(object, HeapNumber::kValueOffset)); | 5131 ldc1(f12, FieldMemOperand(object, HeapNumber::kValueOffset)); |
| 4972 ldc1(f14, FieldMemOperand(probe, HeapNumber::kValueOffset)); | 5132 ldc1(f14, FieldMemOperand(probe, HeapNumber::kValueOffset)); |
| 4973 BranchF(&load_result_from_cache, NULL, eq, f12, f14); | 5133 BranchF(&load_result_from_cache, NULL, eq, f12, f14); |
| 4974 Branch(not_found); | 5134 Branch(not_found); |
| 4975 | 5135 |
| 4976 bind(&is_smi); | 5136 bind(&is_smi); |
| 4977 Register scratch = scratch1; | 5137 Register scratch = scratch1; |
| 4978 sra(scratch, object, 1); // Shift away the tag. | 5138 // dsra(scratch, object, 1); // Shift away the tag. |
| 5139 dsra32(scratch, scratch, 0); |
| 4979 And(scratch, mask, Operand(scratch)); | 5140 And(scratch, mask, Operand(scratch)); |
| 4980 | 5141 |
| 4981 // Calculate address of entry in string cache: each entry consists | 5142 // Calculate address of entry in string cache: each entry consists |
| 4982 // of two pointer sized fields. | 5143 // of two pointer sized fields. |
| 4983 sll(scratch, scratch, kPointerSizeLog2 + 1); | 5144 dsll(scratch, scratch, kPointerSizeLog2 + 1); |
| 4984 Addu(scratch, number_string_cache, scratch); | 5145 Daddu(scratch, number_string_cache, scratch); |
| 4985 | 5146 |
| 4986 // Check if the entry is the smi we are looking for. | 5147 // Check if the entry is the smi we are looking for. |
| 4987 lw(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 5148 ld(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
| 4988 Branch(not_found, ne, object, Operand(probe)); | 5149 Branch(not_found, ne, object, Operand(probe)); |
| 4989 | 5150 |
| 4990 // Get the result from the cache. | 5151 // Get the result from the cache. |
| 4991 bind(&load_result_from_cache); | 5152 bind(&load_result_from_cache); |
| 4992 lw(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); | 5153 ld(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); |
| 4993 | 5154 |
| 4994 IncrementCounter(isolate()->counters()->number_to_string_native(), | 5155 IncrementCounter(isolate()->counters()->number_to_string_native(), |
| 4995 1, | 5156 1, |
| 4996 scratch1, | 5157 scratch1, |
| 4997 scratch2); | 5158 scratch2); |
| 4998 } | 5159 } |
| 4999 | 5160 |
| 5000 | 5161 |
| 5001 void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings( | 5162 void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings( |
| 5002 Register first, | 5163 Register first, |
| 5003 Register second, | 5164 Register second, |
| 5004 Register scratch1, | 5165 Register scratch1, |
| 5005 Register scratch2, | 5166 Register scratch2, |
| 5006 Label* failure) { | 5167 Label* failure) { |
| 5007 // Test that both first and second are sequential ASCII strings. | 5168 // Test that both first and second are sequential ASCII strings. |
| 5008 // Assume that they are non-smis. | 5169 // Assume that they are non-smis. |
| 5009 lw(scratch1, FieldMemOperand(first, HeapObject::kMapOffset)); | 5170 ld(scratch1, FieldMemOperand(first, HeapObject::kMapOffset)); |
| 5010 lw(scratch2, FieldMemOperand(second, HeapObject::kMapOffset)); | 5171 ld(scratch2, FieldMemOperand(second, HeapObject::kMapOffset)); |
| 5011 lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); | 5172 lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); |
| 5012 lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset)); | 5173 lbu(scratch2, FieldMemOperand(scratch2, Map::kInstanceTypeOffset)); |
| 5013 | 5174 |
| 5014 JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1, | 5175 JumpIfBothInstanceTypesAreNotSequentialAscii(scratch1, |
| 5015 scratch2, | 5176 scratch2, |
| 5016 scratch1, | 5177 scratch1, |
| 5017 scratch2, | 5178 scratch2, |
| 5018 failure); | 5179 failure); |
| 5019 } | 5180 } |
| 5020 | 5181 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5059 Label* failure) { | 5220 Label* failure) { |
| 5060 const int kFlatAsciiStringMask = | 5221 const int kFlatAsciiStringMask = |
| 5061 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 5222 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
| 5062 const int kFlatAsciiStringTag = | 5223 const int kFlatAsciiStringTag = |
| 5063 kStringTag | kOneByteStringTag | kSeqStringTag; | 5224 kStringTag | kOneByteStringTag | kSeqStringTag; |
| 5064 And(scratch, type, Operand(kFlatAsciiStringMask)); | 5225 And(scratch, type, Operand(kFlatAsciiStringMask)); |
| 5065 Branch(failure, ne, scratch, Operand(kFlatAsciiStringTag)); | 5226 Branch(failure, ne, scratch, Operand(kFlatAsciiStringTag)); |
| 5066 } | 5227 } |
| 5067 | 5228 |
| 5068 | 5229 |
| 5069 static const int kRegisterPassedArguments = 4; | 5230 static const int kRegisterPassedArguments = (kMipsAbi == kN64) ? 8 : 4; |
| 5070 | 5231 |
| 5071 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments, | 5232 int MacroAssembler::CalculateStackPassedWords(int num_reg_arguments, |
| 5072 int num_double_arguments) { | 5233 int num_double_arguments) { |
| 5073 int stack_passed_words = 0; | 5234 int stack_passed_words = 0; |
| 5074 num_reg_arguments += 2 * num_double_arguments; | 5235 num_reg_arguments += 2 * num_double_arguments; |
| 5075 | 5236 |
| 5076 // Up to four simple arguments are passed in registers a0..a3. | 5237 // O32: Up to four simple arguments are passed in registers a0..a3. |
| 5238 // N64: Up to eight simple arguments are passed in registers a0..a7. |
| 5077 if (num_reg_arguments > kRegisterPassedArguments) { | 5239 if (num_reg_arguments > kRegisterPassedArguments) { |
| 5078 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; | 5240 stack_passed_words += num_reg_arguments - kRegisterPassedArguments; |
| 5079 } | 5241 } |
| 5080 stack_passed_words += kCArgSlotCount; | 5242 stack_passed_words += kCArgSlotCount; |
| 5081 return stack_passed_words; | 5243 return stack_passed_words; |
| 5082 } | 5244 } |
| 5083 | 5245 |
| 5084 | 5246 |
| 5085 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, | 5247 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, |
| 5086 Register index, | 5248 Register index, |
| 5087 Register value, | 5249 Register value, |
| 5088 Register scratch, | 5250 Register scratch, |
| 5089 uint32_t encoding_mask) { | 5251 uint32_t encoding_mask) { |
| 5090 Label is_object; | 5252 Label is_object; |
| 5091 SmiTst(string, at); | 5253 SmiTst(string, at); |
| 5092 Check(ne, kNonObject, at, Operand(zero_reg)); | 5254 Check(ne, kNonObject, at, Operand(zero_reg)); |
| 5093 | 5255 |
| 5094 lw(at, FieldMemOperand(string, HeapObject::kMapOffset)); | 5256 ld(at, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 5095 lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset)); | 5257 lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset)); |
| 5096 | 5258 |
| 5097 andi(at, at, kStringRepresentationMask | kStringEncodingMask); | 5259 andi(at, at, kStringRepresentationMask | kStringEncodingMask); |
| 5098 li(scratch, Operand(encoding_mask)); | 5260 li(scratch, Operand(encoding_mask)); |
| 5099 Check(eq, kUnexpectedStringType, at, Operand(scratch)); | 5261 Check(eq, kUnexpectedStringType, at, Operand(scratch)); |
| 5100 | 5262 |
| 5101 // The index is assumed to be untagged coming in, tag it to compare with the | 5263 // TODO(plind): requires Smi size check code for mips32. |
| 5102 // string length without using a temp register, it is restored at the end of | |
| 5103 // this function. | |
| 5104 Label index_tag_ok, index_tag_bad; | |
| 5105 TrySmiTag(index, scratch, &index_tag_bad); | |
| 5106 Branch(&index_tag_ok); | |
| 5107 bind(&index_tag_bad); | |
| 5108 Abort(kIndexIsTooLarge); | |
| 5109 bind(&index_tag_ok); | |
| 5110 | 5264 |
| 5111 lw(at, FieldMemOperand(string, String::kLengthOffset)); | 5265 ld(at, FieldMemOperand(string, String::kLengthOffset)); |
| 5112 Check(lt, kIndexIsTooLarge, index, Operand(at)); | 5266 Check(lt, kIndexIsTooLarge, index, Operand(at)); |
| 5113 | 5267 |
| 5114 ASSERT(Smi::FromInt(0) == 0); | 5268 ASSERT(Smi::FromInt(0) == 0); |
| 5115 Check(ge, kIndexIsNegative, index, Operand(zero_reg)); | 5269 Check(ge, kIndexIsNegative, index, Operand(zero_reg)); |
| 5116 | |
| 5117 SmiUntag(index, index); | |
| 5118 } | 5270 } |
| 5119 | 5271 |
| 5120 | 5272 |
| 5121 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5273 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
| 5122 int num_double_arguments, | 5274 int num_double_arguments, |
| 5123 Register scratch) { | 5275 Register scratch) { |
| 5124 int frame_alignment = ActivationFrameAlignment(); | 5276 int frame_alignment = ActivationFrameAlignment(); |
| 5125 | 5277 |
| 5126 // Up to four simple arguments are passed in registers a0..a3. | 5278 // n64: Up to eight simple arguments in a0..a3, a4..a7, No argument slots. |
| 5279 // O32: Up to four simple arguments are passed in registers a0..a3. |
| 5127 // Those four arguments must have reserved argument slots on the stack for | 5280 // Those four arguments must have reserved argument slots on the stack for |
| 5128 // mips, even though those argument slots are not normally used. | 5281 // mips, even though those argument slots are not normally used. |
| 5129 // Remaining arguments are pushed on the stack, above (higher address than) | 5282 // Both ABIs: Remaining arguments are pushed on the stack, above (higher |
| 5130 // the argument slots. | 5283 // address than) the (O32) argument slots. (arg slot calculation handled by |
| 5284 // CalculateStackPassedWords()). |
| 5131 int stack_passed_arguments = CalculateStackPassedWords( | 5285 int stack_passed_arguments = CalculateStackPassedWords( |
| 5132 num_reg_arguments, num_double_arguments); | 5286 num_reg_arguments, num_double_arguments); |
| 5133 if (frame_alignment > kPointerSize) { | 5287 if (frame_alignment > kPointerSize) { |
| 5134 // Make stack end at alignment and make room for num_arguments - 4 words | 5288 // Make stack end at alignment and make room for num_arguments - 4 words |
| 5135 // and the original value of sp. | 5289 // and the original value of sp. |
| 5136 mov(scratch, sp); | 5290 mov(scratch, sp); |
| 5137 Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); | 5291 Dsubu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); |
| 5138 ASSERT(IsPowerOf2(frame_alignment)); | 5292 ASSERT(IsPowerOf2(frame_alignment)); |
| 5139 And(sp, sp, Operand(-frame_alignment)); | 5293 And(sp, sp, Operand(-frame_alignment)); |
| 5140 sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 5294 sd(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
| 5141 } else { | 5295 } else { |
| 5142 Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); | 5296 Dsubu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); |
| 5143 } | 5297 } |
| 5144 } | 5298 } |
| 5145 | 5299 |
| 5146 | 5300 |
| 5147 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5301 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
| 5148 Register scratch) { | 5302 Register scratch) { |
| 5149 PrepareCallCFunction(num_reg_arguments, 0, scratch); | 5303 PrepareCallCFunction(num_reg_arguments, 0, scratch); |
| 5150 } | 5304 } |
| 5151 | 5305 |
| 5152 | 5306 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 5180 void MacroAssembler::CallCFunctionHelper(Register function, | 5334 void MacroAssembler::CallCFunctionHelper(Register function, |
| 5181 int num_reg_arguments, | 5335 int num_reg_arguments, |
| 5182 int num_double_arguments) { | 5336 int num_double_arguments) { |
| 5183 ASSERT(has_frame()); | 5337 ASSERT(has_frame()); |
| 5184 // Make sure that the stack is aligned before calling a C function unless | 5338 // Make sure that the stack is aligned before calling a C function unless |
| 5185 // running in the simulator. The simulator has its own alignment check which | 5339 // running in the simulator. The simulator has its own alignment check which |
| 5186 // provides more information. | 5340 // provides more information. |
| 5187 // The argument stots are presumed to have been set up by | 5341 // The argument stots are presumed to have been set up by |
| 5188 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. | 5342 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. |
| 5189 | 5343 |
| 5190 #if V8_HOST_ARCH_MIPS | 5344 #if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 |
| 5191 if (emit_debug_code()) { | 5345 if (emit_debug_code()) { |
| 5192 int frame_alignment = base::OS::ActivationFrameAlignment(); | 5346 int frame_alignment = base::OS::ActivationFrameAlignment(); |
| 5193 int frame_alignment_mask = frame_alignment - 1; | 5347 int frame_alignment_mask = frame_alignment - 1; |
| 5194 if (frame_alignment > kPointerSize) { | 5348 if (frame_alignment > kPointerSize) { |
| 5195 ASSERT(IsPowerOf2(frame_alignment)); | 5349 ASSERT(IsPowerOf2(frame_alignment)); |
| 5196 Label alignment_as_expected; | 5350 Label alignment_as_expected; |
| 5197 And(at, sp, Operand(frame_alignment_mask)); | 5351 And(at, sp, Operand(frame_alignment_mask)); |
| 5198 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); | 5352 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); |
| 5199 // Don't use Check here, as it will call Runtime_Abort possibly | 5353 // Don't use Check here, as it will call Runtime_Abort possibly |
| 5200 // re-entering here. | 5354 // re-entering here. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5212 mov(t9, function); | 5366 mov(t9, function); |
| 5213 function = t9; | 5367 function = t9; |
| 5214 } | 5368 } |
| 5215 | 5369 |
| 5216 Call(function); | 5370 Call(function); |
| 5217 | 5371 |
| 5218 int stack_passed_arguments = CalculateStackPassedWords( | 5372 int stack_passed_arguments = CalculateStackPassedWords( |
| 5219 num_reg_arguments, num_double_arguments); | 5373 num_reg_arguments, num_double_arguments); |
| 5220 | 5374 |
| 5221 if (base::OS::ActivationFrameAlignment() > kPointerSize) { | 5375 if (base::OS::ActivationFrameAlignment() > kPointerSize) { |
| 5222 lw(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 5376 ld(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
| 5223 } else { | 5377 } else { |
| 5224 Addu(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); | 5378 Daddu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); |
| 5225 } | 5379 } |
| 5226 } | 5380 } |
| 5227 | 5381 |
| 5228 | 5382 |
| 5229 #undef BRANCH_ARGS_CHECK | 5383 #undef BRANCH_ARGS_CHECK |
| 5230 | 5384 |
| 5231 | 5385 |
| 5232 void MacroAssembler::PatchRelocatedValue(Register li_location, | 5386 void MacroAssembler::PatchRelocatedValue(Register li_location, |
| 5233 Register scratch, | 5387 Register scratch, |
| 5234 Register new_value) { | 5388 Register new_value) { |
| 5235 lw(scratch, MemOperand(li_location)); | 5389 lwu(scratch, MemOperand(li_location)); |
| 5236 // At this point scratch is a lui(at, ...) instruction. | 5390 // At this point scratch is a lui(at, ...) instruction. |
| 5237 if (emit_debug_code()) { | 5391 if (emit_debug_code()) { |
| 5238 And(scratch, scratch, kOpcodeMask); | 5392 And(scratch, scratch, kOpcodeMask); |
| 5239 Check(eq, kTheInstructionToPatchShouldBeALui, | 5393 Check(eq, kTheInstructionToPatchShouldBeALui, |
| 5240 scratch, Operand(LUI)); | 5394 scratch, Operand(LUI)); |
| 5241 lw(scratch, MemOperand(li_location)); | 5395 lwu(scratch, MemOperand(li_location)); |
| 5242 } | 5396 } |
| 5243 srl(t9, new_value, kImm16Bits); | 5397 dsrl32(t9, new_value, 0); |
| 5244 Ins(scratch, t9, 0, kImm16Bits); | 5398 Ins(scratch, t9, 0, kImm16Bits); |
| 5245 sw(scratch, MemOperand(li_location)); | 5399 sw(scratch, MemOperand(li_location)); |
| 5246 | 5400 |
| 5247 lw(scratch, MemOperand(li_location, kInstrSize)); | 5401 lwu(scratch, MemOperand(li_location, kInstrSize)); |
| 5248 // scratch is now ori(at, ...). | 5402 // scratch is now ori(at, ...). |
| 5249 if (emit_debug_code()) { | 5403 if (emit_debug_code()) { |
| 5250 And(scratch, scratch, kOpcodeMask); | 5404 And(scratch, scratch, kOpcodeMask); |
| 5251 Check(eq, kTheInstructionToPatchShouldBeAnOri, | 5405 Check(eq, kTheInstructionToPatchShouldBeAnOri, |
| 5252 scratch, Operand(ORI)); | 5406 scratch, Operand(ORI)); |
| 5253 lw(scratch, MemOperand(li_location, kInstrSize)); | 5407 lwu(scratch, MemOperand(li_location, kInstrSize)); |
| 5254 } | 5408 } |
| 5255 Ins(scratch, new_value, 0, kImm16Bits); | 5409 dsrl(t9, new_value, kImm16Bits); |
| 5410 Ins(scratch, t9, 0, kImm16Bits); |
| 5256 sw(scratch, MemOperand(li_location, kInstrSize)); | 5411 sw(scratch, MemOperand(li_location, kInstrSize)); |
| 5257 | 5412 |
| 5413 lwu(scratch, MemOperand(li_location, kInstrSize * 3)); |
| 5414 // scratch is now ori(at, ...). |
| 5415 if (emit_debug_code()) { |
| 5416 And(scratch, scratch, kOpcodeMask); |
| 5417 Check(eq, kTheInstructionToPatchShouldBeAnOri, |
| 5418 scratch, Operand(ORI)); |
| 5419 lwu(scratch, MemOperand(li_location, kInstrSize * 3)); |
| 5420 } |
| 5421 |
| 5422 Ins(scratch, new_value, 0, kImm16Bits); |
| 5423 sw(scratch, MemOperand(li_location, kInstrSize * 3)); |
| 5424 |
| 5258 // Update the I-cache so the new lui and ori can be executed. | 5425 // Update the I-cache so the new lui and ori can be executed. |
| 5259 FlushICache(li_location, 2); | 5426 FlushICache(li_location, 4); |
| 5260 } | 5427 } |
| 5261 | 5428 |
| 5262 void MacroAssembler::GetRelocatedValue(Register li_location, | 5429 void MacroAssembler::GetRelocatedValue(Register li_location, |
| 5263 Register value, | 5430 Register value, |
| 5264 Register scratch) { | 5431 Register scratch) { |
| 5265 lw(value, MemOperand(li_location)); | 5432 lwu(value, MemOperand(li_location)); |
| 5266 if (emit_debug_code()) { | 5433 if (emit_debug_code()) { |
| 5267 And(value, value, kOpcodeMask); | 5434 And(value, value, kOpcodeMask); |
| 5268 Check(eq, kTheInstructionShouldBeALui, | 5435 Check(eq, kTheInstructionShouldBeALui, |
| 5269 value, Operand(LUI)); | 5436 value, Operand(LUI)); |
| 5270 lw(value, MemOperand(li_location)); | 5437 lwu(value, MemOperand(li_location)); |
| 5271 } | 5438 } |
| 5272 | 5439 |
| 5273 // value now holds a lui instruction. Extract the immediate. | 5440 // value now holds a lui instruction. Extract the immediate. |
| 5274 sll(value, value, kImm16Bits); | 5441 andi(value, value, kImm16Mask); |
| 5442 dsll32(value, value, kImm16Bits); |
| 5275 | 5443 |
| 5276 lw(scratch, MemOperand(li_location, kInstrSize)); | 5444 lwu(scratch, MemOperand(li_location, kInstrSize)); |
| 5277 if (emit_debug_code()) { | 5445 if (emit_debug_code()) { |
| 5278 And(scratch, scratch, kOpcodeMask); | 5446 And(scratch, scratch, kOpcodeMask); |
| 5279 Check(eq, kTheInstructionShouldBeAnOri, | 5447 Check(eq, kTheInstructionShouldBeAnOri, |
| 5280 scratch, Operand(ORI)); | 5448 scratch, Operand(ORI)); |
| 5281 lw(scratch, MemOperand(li_location, kInstrSize)); | 5449 lwu(scratch, MemOperand(li_location, kInstrSize)); |
| 5282 } | 5450 } |
| 5283 // "scratch" now holds an ori instruction. Extract the immediate. | 5451 // "scratch" now holds an ori instruction. Extract the immediate. |
| 5284 andi(scratch, scratch, kImm16Mask); | 5452 andi(scratch, scratch, kImm16Mask); |
| 5453 dsll32(scratch, scratch, 0); |
| 5285 | 5454 |
| 5286 // Merge the results. | |
| 5287 or_(value, value, scratch); | 5455 or_(value, value, scratch); |
| 5456 |
| 5457 lwu(scratch, MemOperand(li_location, kInstrSize * 3)); |
| 5458 if (emit_debug_code()) { |
| 5459 And(scratch, scratch, kOpcodeMask); |
| 5460 Check(eq, kTheInstructionShouldBeAnOri, |
| 5461 scratch, Operand(ORI)); |
| 5462 lwu(scratch, MemOperand(li_location, kInstrSize * 3)); |
| 5463 } |
| 5464 // "scratch" now holds an ori instruction. Extract the immediate. |
| 5465 andi(scratch, scratch, kImm16Mask); |
| 5466 dsll(scratch, scratch, kImm16Bits); |
| 5467 |
| 5468 or_(value, value, scratch); |
| 5469 // Sign extend extracted address. |
| 5470 dsra(value, value, kImm16Bits); |
| 5288 } | 5471 } |
| 5289 | 5472 |
| 5290 | 5473 |
| 5291 void MacroAssembler::CheckPageFlag( | 5474 void MacroAssembler::CheckPageFlag( |
| 5292 Register object, | 5475 Register object, |
| 5293 Register scratch, | 5476 Register scratch, |
| 5294 int mask, | 5477 int mask, |
| 5295 Condition cc, | 5478 Condition cc, |
| 5296 Label* condition_met) { | 5479 Label* condition_met) { |
| 5297 And(scratch, object, Operand(~Page::kPageAlignmentMask)); | 5480 // TODO(plind): Fix li() so we can use constant embedded inside And(). |
| 5298 lw(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); | 5481 // And(scratch, object, Operand(~Page::kPageAlignmentMask)); |
| 5482 li(at, Operand(~Page::kPageAlignmentMask), CONSTANT_SIZE); // plind HACK |
| 5483 And(scratch, object, at); |
| 5484 ld(scratch, MemOperand(scratch, MemoryChunk::kFlagsOffset)); |
| 5299 And(scratch, scratch, Operand(mask)); | 5485 And(scratch, scratch, Operand(mask)); |
| 5300 Branch(condition_met, cc, scratch, Operand(zero_reg)); | 5486 Branch(condition_met, cc, scratch, Operand(zero_reg)); |
| 5301 } | 5487 } |
| 5302 | 5488 |
| 5303 | 5489 |
| 5304 void MacroAssembler::CheckMapDeprecated(Handle<Map> map, | 5490 void MacroAssembler::CheckMapDeprecated(Handle<Map> map, |
| 5305 Register scratch, | 5491 Register scratch, |
| 5306 Label* if_deprecated) { | 5492 Label* if_deprecated) { |
| 5307 if (map->CanBeDeprecated()) { | 5493 if (map->CanBeDeprecated()) { |
| 5308 li(scratch, Operand(map)); | 5494 li(scratch, Operand(map)); |
| 5309 lw(scratch, FieldMemOperand(scratch, Map::kBitField3Offset)); | 5495 ld(scratch, FieldMemOperand(scratch, Map::kBitField3Offset)); |
| 5310 And(scratch, scratch, Operand(Map::Deprecated::kMask)); | 5496 And(scratch, scratch, Operand(Map::Deprecated::kMask)); |
| 5311 Branch(if_deprecated, ne, scratch, Operand(zero_reg)); | 5497 Branch(if_deprecated, ne, scratch, Operand(zero_reg)); |
| 5312 } | 5498 } |
| 5313 } | 5499 } |
| 5314 | 5500 |
| 5315 | 5501 |
| 5316 void MacroAssembler::JumpIfBlack(Register object, | 5502 void MacroAssembler::JumpIfBlack(Register object, |
| 5317 Register scratch0, | 5503 Register scratch0, |
| 5318 Register scratch1, | 5504 Register scratch1, |
| 5319 Label* on_black) { | 5505 Label* on_black) { |
| 5320 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. | 5506 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. |
| 5321 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5507 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 5322 } | 5508 } |
| 5323 | 5509 |
| 5324 | 5510 |
| 5325 void MacroAssembler::HasColor(Register object, | 5511 void MacroAssembler::HasColor(Register object, |
| 5326 Register bitmap_scratch, | 5512 Register bitmap_scratch, |
| 5327 Register mask_scratch, | 5513 Register mask_scratch, |
| 5328 Label* has_color, | 5514 Label* has_color, |
| 5329 int first_bit, | 5515 int first_bit, |
| 5330 int second_bit) { | 5516 int second_bit) { |
| 5331 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t8)); | 5517 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t8)); |
| 5332 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t9)); | 5518 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t9)); |
| 5333 | 5519 |
| 5334 GetMarkBits(object, bitmap_scratch, mask_scratch); | 5520 GetMarkBits(object, bitmap_scratch, mask_scratch); |
| 5335 | 5521 |
| 5336 Label other_color, word_boundary; | 5522 Label other_color; |
| 5337 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5523 // Note that we are using a 4-byte aligned 8-byte load. |
| 5524 Uld(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 5338 And(t8, t9, Operand(mask_scratch)); | 5525 And(t8, t9, Operand(mask_scratch)); |
| 5339 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); | 5526 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); |
| 5340 // Shift left 1 by adding. | 5527 // Shift left 1 by adding. |
| 5341 Addu(mask_scratch, mask_scratch, Operand(mask_scratch)); | 5528 Daddu(mask_scratch, mask_scratch, Operand(mask_scratch)); |
| 5342 Branch(&word_boundary, eq, mask_scratch, Operand(zero_reg)); | |
| 5343 And(t8, t9, Operand(mask_scratch)); | 5529 And(t8, t9, Operand(mask_scratch)); |
| 5344 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); | 5530 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); |
| 5345 jmp(&other_color); | |
| 5346 | 5531 |
| 5347 bind(&word_boundary); | |
| 5348 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); | |
| 5349 And(t9, t9, Operand(1)); | |
| 5350 Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg)); | |
| 5351 bind(&other_color); | 5532 bind(&other_color); |
| 5352 } | 5533 } |
| 5353 | 5534 |
| 5354 | 5535 |
| 5355 // Detect some, but not all, common pointer-free objects. This is used by the | 5536 // Detect some, but not all, common pointer-free objects. This is used by the |
| 5356 // incremental write barrier which doesn't care about oddballs (they are always | 5537 // incremental write barrier which doesn't care about oddballs (they are always |
| 5357 // marked black immediately so this code is not hit). | 5538 // marked black immediately so this code is not hit). |
| 5358 void MacroAssembler::JumpIfDataObject(Register value, | 5539 void MacroAssembler::JumpIfDataObject(Register value, |
| 5359 Register scratch, | 5540 Register scratch, |
| 5360 Label* not_data_object) { | 5541 Label* not_data_object) { |
| 5361 ASSERT(!AreAliased(value, scratch, t8, no_reg)); | 5542 ASSERT(!AreAliased(value, scratch, t8, no_reg)); |
| 5362 Label is_data_object; | 5543 Label is_data_object; |
| 5363 lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | 5544 ld(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); |
| 5364 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | 5545 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
| 5365 Branch(&is_data_object, eq, t8, Operand(scratch)); | 5546 Branch(&is_data_object, eq, t8, Operand(scratch)); |
| 5366 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | 5547 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); |
| 5367 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | 5548 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); |
| 5368 // If it's a string and it's not a cons string then it's an object containing | 5549 // If it's a string and it's not a cons string then it's an object containing |
| 5369 // no GC pointers. | 5550 // no GC pointers. |
| 5370 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 5551 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 5371 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); | 5552 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); |
| 5372 Branch(not_data_object, ne, t8, Operand(zero_reg)); | 5553 Branch(not_data_object, ne, t8, Operand(zero_reg)); |
| 5373 bind(&is_data_object); | 5554 bind(&is_data_object); |
| 5374 } | 5555 } |
| 5375 | 5556 |
| 5376 | 5557 |
| 5377 void MacroAssembler::GetMarkBits(Register addr_reg, | 5558 void MacroAssembler::GetMarkBits(Register addr_reg, |
| 5378 Register bitmap_reg, | 5559 Register bitmap_reg, |
| 5379 Register mask_reg) { | 5560 Register mask_reg) { |
| 5380 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); | 5561 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); |
| 5562 // addr_reg is divided into fields: |
| 5563 // |63 page base 20|19 high 8|7 shift 3|2 0| |
| 5564 // 'high' gives the index of the cell holding color bits for the object. |
| 5565 // 'shift' gives the offset in the cell for this object's color. |
| 5381 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); | 5566 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); |
| 5382 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); | 5567 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); |
| 5383 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; | 5568 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
| 5384 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); | 5569 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); |
| 5385 sll(t8, t8, kPointerSizeLog2); | 5570 dsll(t8, t8, Bitmap::kBytesPerCellLog2); |
| 5386 Addu(bitmap_reg, bitmap_reg, t8); | 5571 Daddu(bitmap_reg, bitmap_reg, t8); |
| 5387 li(t8, Operand(1)); | 5572 li(t8, Operand(1)); |
| 5388 sllv(mask_reg, t8, mask_reg); | 5573 dsllv(mask_reg, t8, mask_reg); |
| 5389 } | 5574 } |
| 5390 | 5575 |
| 5391 | 5576 |
| 5392 void MacroAssembler::EnsureNotWhite( | 5577 void MacroAssembler::EnsureNotWhite( |
| 5393 Register value, | 5578 Register value, |
| 5394 Register bitmap_scratch, | 5579 Register bitmap_scratch, |
| 5395 Register mask_scratch, | 5580 Register mask_scratch, |
| 5396 Register load_scratch, | 5581 Register load_scratch, |
| 5397 Label* value_is_white_and_not_data) { | 5582 Label* value_is_white_and_not_data) { |
| 5398 ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); | 5583 ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); |
| 5399 GetMarkBits(value, bitmap_scratch, mask_scratch); | 5584 GetMarkBits(value, bitmap_scratch, mask_scratch); |
| 5400 | 5585 |
| 5401 // If the value is black or grey we don't need to do anything. | 5586 // If the value is black or grey we don't need to do anything. |
| 5402 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 5587 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 5403 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5588 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
| 5404 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 5589 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); |
| 5405 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 5590 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 5406 | 5591 |
| 5407 Label done; | 5592 Label done; |
| 5408 | 5593 |
| 5409 // Since both black and grey have a 1 in the first position and white does | 5594 // Since both black and grey have a 1 in the first position and white does |
| 5410 // not have a 1 there we only need to check one bit. | 5595 // not have a 1 there we only need to check one bit. |
| 5411 lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5596 // Note that we are using a 4-byte aligned 8-byte load. |
| 5597 Uld(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 5412 And(t8, mask_scratch, load_scratch); | 5598 And(t8, mask_scratch, load_scratch); |
| 5413 Branch(&done, ne, t8, Operand(zero_reg)); | 5599 Branch(&done, ne, t8, Operand(zero_reg)); |
| 5414 | 5600 |
| 5415 if (emit_debug_code()) { | 5601 if (emit_debug_code()) { |
| 5416 // Check for impossible bit pattern. | 5602 // Check for impossible bit pattern. |
| 5417 Label ok; | 5603 Label ok; |
| 5418 // sll may overflow, making the check conservative. | 5604 // sll may overflow, making the check conservative. |
| 5419 sll(t8, mask_scratch, 1); | 5605 dsll(t8, mask_scratch, 1); |
| 5420 And(t8, load_scratch, t8); | 5606 And(t8, load_scratch, t8); |
| 5421 Branch(&ok, eq, t8, Operand(zero_reg)); | 5607 Branch(&ok, eq, t8, Operand(zero_reg)); |
| 5422 stop("Impossible marking bit pattern"); | 5608 stop("Impossible marking bit pattern"); |
| 5423 bind(&ok); | 5609 bind(&ok); |
| 5424 } | 5610 } |
| 5425 | 5611 |
| 5426 // Value is white. We check whether it is data that doesn't need scanning. | 5612 // Value is white. We check whether it is data that doesn't need scanning. |
| 5427 // Currently only checks for HeapNumber and non-cons strings. | 5613 // Currently only checks for HeapNumber and non-cons strings. |
| 5428 Register map = load_scratch; // Holds map while checking type. | 5614 Register map = load_scratch; // Holds map while checking type. |
| 5429 Register length = load_scratch; // Holds length of object after testing type. | 5615 Register length = load_scratch; // Holds length of object after testing type. |
| 5430 Label is_data_object; | 5616 Label is_data_object; |
| 5431 | 5617 |
| 5432 // Check for heap-number | 5618 // Check for heap-number |
| 5433 lw(map, FieldMemOperand(value, HeapObject::kMapOffset)); | 5619 ld(map, FieldMemOperand(value, HeapObject::kMapOffset)); |
| 5434 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | 5620 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
| 5435 { | 5621 { |
| 5436 Label skip; | 5622 Label skip; |
| 5437 Branch(&skip, ne, t8, Operand(map)); | 5623 Branch(&skip, ne, t8, Operand(map)); |
| 5438 li(length, HeapNumber::kSize); | 5624 li(length, HeapNumber::kSize); |
| 5439 Branch(&is_data_object); | 5625 Branch(&is_data_object); |
| 5440 bind(&skip); | 5626 bind(&skip); |
| 5441 } | 5627 } |
| 5442 | 5628 |
| 5443 // Check for strings. | 5629 // Check for strings. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5464 Branch(&is_data_object); | 5650 Branch(&is_data_object); |
| 5465 bind(&skip); | 5651 bind(&skip); |
| 5466 } | 5652 } |
| 5467 | 5653 |
| 5468 // Sequential string, either ASCII or UC16. | 5654 // Sequential string, either ASCII or UC16. |
| 5469 // For ASCII (char-size of 1) we shift the smi tag away to get the length. | 5655 // For ASCII (char-size of 1) we shift the smi tag away to get the length. |
| 5470 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby | 5656 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby |
| 5471 // getting the length multiplied by 2. | 5657 // getting the length multiplied by 2. |
| 5472 ASSERT(kOneByteStringTag == 4 && kStringEncodingMask == 4); | 5658 ASSERT(kOneByteStringTag == 4 && kStringEncodingMask == 4); |
| 5473 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 5659 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 5474 lw(t9, FieldMemOperand(value, String::kLengthOffset)); | 5660 lw(t9, UntagSmiFieldMemOperand(value, String::kLengthOffset)); |
| 5475 And(t8, instance_type, Operand(kStringEncodingMask)); | 5661 And(t8, instance_type, Operand(kStringEncodingMask)); |
| 5476 { | 5662 { |
| 5477 Label skip; | 5663 Label skip; |
| 5478 Branch(&skip, eq, t8, Operand(zero_reg)); | 5664 Branch(&skip, ne, t8, Operand(zero_reg)); |
| 5479 srl(t9, t9, 1); | 5665 // Adjust length for UC16. |
| 5666 dsll(t9, t9, 1); |
| 5480 bind(&skip); | 5667 bind(&skip); |
| 5481 } | 5668 } |
| 5482 Addu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); | 5669 Daddu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); |
| 5670 ASSERT(!length.is(t8)); |
| 5483 And(length, length, Operand(~kObjectAlignmentMask)); | 5671 And(length, length, Operand(~kObjectAlignmentMask)); |
| 5484 | 5672 |
| 5485 bind(&is_data_object); | 5673 bind(&is_data_object); |
| 5486 // Value is a data object, and it is white. Mark it black. Since we know | 5674 // Value is a data object, and it is white. Mark it black. Since we know |
| 5487 // that the object is white we can make it black by flipping one bit. | 5675 // that the object is white we can make it black by flipping one bit. |
| 5488 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5676 Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 5489 Or(t8, t8, Operand(mask_scratch)); | 5677 Or(t8, t8, Operand(mask_scratch)); |
| 5490 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5678 Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
| 5491 | 5679 |
| 5492 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); | 5680 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); |
| 5493 lw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | 5681 Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); |
| 5494 Addu(t8, t8, Operand(length)); | 5682 Daddu(t8, t8, Operand(length)); |
| 5495 sw(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); | 5683 Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kLiveBytesOffset)); |
| 5496 | 5684 |
| 5497 bind(&done); | 5685 bind(&done); |
| 5498 } | 5686 } |
| 5499 | 5687 |
| 5500 | 5688 |
| 5501 void MacroAssembler::LoadInstanceDescriptors(Register map, | 5689 void MacroAssembler::LoadInstanceDescriptors(Register map, |
| 5502 Register descriptors) { | 5690 Register descriptors) { |
| 5503 lw(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); | 5691 ld(descriptors, FieldMemOperand(map, Map::kDescriptorsOffset)); |
| 5504 } | 5692 } |
| 5505 | 5693 |
| 5506 | 5694 |
| 5507 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { | 5695 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { |
| 5508 lw(dst, FieldMemOperand(map, Map::kBitField3Offset)); | 5696 ld(dst, FieldMemOperand(map, Map::kBitField3Offset)); |
| 5509 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); | 5697 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); |
| 5510 } | 5698 } |
| 5511 | 5699 |
| 5512 | 5700 |
| 5513 void MacroAssembler::EnumLength(Register dst, Register map) { | 5701 void MacroAssembler::EnumLength(Register dst, Register map) { |
| 5514 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); | 5702 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); |
| 5515 lw(dst, FieldMemOperand(map, Map::kBitField3Offset)); | 5703 ld(dst, FieldMemOperand(map, Map::kBitField3Offset)); |
| 5516 And(dst, dst, Operand(Map::EnumLengthBits::kMask)); | 5704 And(dst, dst, Operand(Map::EnumLengthBits::kMask)); |
| 5517 SmiTag(dst); | 5705 SmiTag(dst); |
| 5518 } | 5706 } |
| 5519 | 5707 |
| 5520 | 5708 |
| 5521 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { | 5709 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { |
| 5522 Register empty_fixed_array_value = t2; | 5710 Register empty_fixed_array_value = a6; |
| 5523 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 5711 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); |
| 5524 Label next, start; | 5712 Label next, start; |
| 5525 mov(a2, a0); | 5713 mov(a2, a0); |
| 5526 | 5714 |
| 5527 // Check if the enum length field is properly initialized, indicating that | 5715 // Check if the enum length field is properly initialized, indicating that |
| 5528 // there is an enum cache. | 5716 // there is an enum cache. |
| 5529 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); | 5717 ld(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 5530 | 5718 |
| 5531 EnumLength(a3, a1); | 5719 EnumLength(a3, a1); |
| 5532 Branch( | 5720 Branch( |
| 5533 call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel))); | 5721 call_runtime, eq, a3, Operand(Smi::FromInt(kInvalidEnumCacheSentinel))); |
| 5534 | 5722 |
| 5535 jmp(&start); | 5723 jmp(&start); |
| 5536 | 5724 |
| 5537 bind(&next); | 5725 bind(&next); |
| 5538 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); | 5726 ld(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 5539 | 5727 |
| 5540 // For all objects but the receiver, check that the cache is empty. | 5728 // For all objects but the receiver, check that the cache is empty. |
| 5541 EnumLength(a3, a1); | 5729 EnumLength(a3, a1); |
| 5542 Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0))); | 5730 Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0))); |
| 5543 | 5731 |
| 5544 bind(&start); | 5732 bind(&start); |
| 5545 | 5733 |
| 5546 // Check that there are no elements. Register a2 contains the current JS | 5734 // Check that there are no elements. Register a2 contains the current JS |
| 5547 // object we've reached through the prototype chain. | 5735 // object we've reached through the prototype chain. |
| 5548 Label no_elements; | 5736 Label no_elements; |
| 5549 lw(a2, FieldMemOperand(a2, JSObject::kElementsOffset)); | 5737 ld(a2, FieldMemOperand(a2, JSObject::kElementsOffset)); |
| 5550 Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value)); | 5738 Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value)); |
| 5551 | 5739 |
| 5552 // Second chance, the object may be using the empty slow element dictionary. | 5740 // Second chance, the object may be using the empty slow element dictionary. |
| 5553 LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex); | 5741 LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex); |
| 5554 Branch(call_runtime, ne, a2, Operand(at)); | 5742 Branch(call_runtime, ne, a2, Operand(at)); |
| 5555 | 5743 |
| 5556 bind(&no_elements); | 5744 bind(&no_elements); |
| 5557 lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); | 5745 ld(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); |
| 5558 Branch(&next, ne, a2, Operand(null_value)); | 5746 Branch(&next, ne, a2, Operand(null_value)); |
| 5559 } | 5747 } |
| 5560 | 5748 |
| 5561 | 5749 |
| 5562 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { | 5750 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
| 5563 ASSERT(!output_reg.is(input_reg)); | 5751 ASSERT(!output_reg.is(input_reg)); |
| 5564 Label done; | 5752 Label done; |
| 5565 li(output_reg, Operand(255)); | 5753 li(output_reg, Operand(255)); |
| 5566 // Normal branch: nop in delay slot. | 5754 // Normal branch: nop in delay slot. |
| 5567 Branch(&done, gt, input_reg, Operand(output_reg)); | 5755 Branch(&done, gt, input_reg, Operand(output_reg)); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5605 void MacroAssembler::TestJSArrayForAllocationMemento( | 5793 void MacroAssembler::TestJSArrayForAllocationMemento( |
| 5606 Register receiver_reg, | 5794 Register receiver_reg, |
| 5607 Register scratch_reg, | 5795 Register scratch_reg, |
| 5608 Label* no_memento_found, | 5796 Label* no_memento_found, |
| 5609 Condition cond, | 5797 Condition cond, |
| 5610 Label* allocation_memento_present) { | 5798 Label* allocation_memento_present) { |
| 5611 ExternalReference new_space_start = | 5799 ExternalReference new_space_start = |
| 5612 ExternalReference::new_space_start(isolate()); | 5800 ExternalReference::new_space_start(isolate()); |
| 5613 ExternalReference new_space_allocation_top = | 5801 ExternalReference new_space_allocation_top = |
| 5614 ExternalReference::new_space_allocation_top_address(isolate()); | 5802 ExternalReference::new_space_allocation_top_address(isolate()); |
| 5615 Addu(scratch_reg, receiver_reg, | 5803 Daddu(scratch_reg, receiver_reg, |
| 5616 Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag)); | 5804 Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag)); |
| 5617 Branch(no_memento_found, lt, scratch_reg, Operand(new_space_start)); | 5805 Branch(no_memento_found, lt, scratch_reg, Operand(new_space_start)); |
| 5618 li(at, Operand(new_space_allocation_top)); | 5806 li(at, Operand(new_space_allocation_top)); |
| 5619 lw(at, MemOperand(at)); | 5807 ld(at, MemOperand(at)); |
| 5620 Branch(no_memento_found, gt, scratch_reg, Operand(at)); | 5808 Branch(no_memento_found, gt, scratch_reg, Operand(at)); |
| 5621 lw(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize)); | 5809 ld(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize)); |
| 5622 if (allocation_memento_present) { | 5810 if (allocation_memento_present) { |
| 5623 Branch(allocation_memento_present, cond, scratch_reg, | 5811 Branch(allocation_memento_present, cond, scratch_reg, |
| 5624 Operand(isolate()->factory()->allocation_memento_map())); | 5812 Operand(isolate()->factory()->allocation_memento_map())); |
| 5625 } | 5813 } |
| 5626 } | 5814 } |
| 5627 | 5815 |
| 5628 | 5816 |
| 5629 Register GetRegisterThatIsNotOneOf(Register reg1, | 5817 Register GetRegisterThatIsNotOneOf(Register reg1, |
| 5630 Register reg2, | 5818 Register reg2, |
| 5631 Register reg3, | 5819 Register reg3, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5658 ASSERT(!scratch1.is(scratch0)); | 5846 ASSERT(!scratch1.is(scratch0)); |
| 5659 Factory* factory = isolate()->factory(); | 5847 Factory* factory = isolate()->factory(); |
| 5660 Register current = scratch0; | 5848 Register current = scratch0; |
| 5661 Label loop_again; | 5849 Label loop_again; |
| 5662 | 5850 |
| 5663 // Scratch contained elements pointer. | 5851 // Scratch contained elements pointer. |
| 5664 Move(current, object); | 5852 Move(current, object); |
| 5665 | 5853 |
| 5666 // Loop based on the map going up the prototype chain. | 5854 // Loop based on the map going up the prototype chain. |
| 5667 bind(&loop_again); | 5855 bind(&loop_again); |
| 5668 lw(current, FieldMemOperand(current, HeapObject::kMapOffset)); | 5856 ld(current, FieldMemOperand(current, HeapObject::kMapOffset)); |
| 5669 lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset)); | 5857 lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset)); |
| 5670 DecodeField<Map::ElementsKindBits>(scratch1); | 5858 DecodeField<Map::ElementsKindBits>(scratch1); |
| 5671 Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS)); | 5859 Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS)); |
| 5672 lw(current, FieldMemOperand(current, Map::kPrototypeOffset)); | 5860 ld(current, FieldMemOperand(current, Map::kPrototypeOffset)); |
| 5673 Branch(&loop_again, ne, current, Operand(factory->null_value())); | 5861 Branch(&loop_again, ne, current, Operand(factory->null_value())); |
| 5674 } | 5862 } |
| 5675 | 5863 |
| 5676 | 5864 |
| 5677 bool AreAliased(Register r1, Register r2, Register r3, Register r4) { | 5865 bool AreAliased(Register r1, Register r2, Register r3, Register r4) { |
| 5678 if (r1.is(r2)) return true; | 5866 if (r1.is(r2)) return true; |
| 5679 if (r1.is(r3)) return true; | 5867 if (r1.is(r3)) return true; |
| 5680 if (r1.is(r4)) return true; | 5868 if (r1.is(r4)) return true; |
| 5681 if (r2.is(r3)) return true; | 5869 if (r2.is(r3)) return true; |
| 5682 if (r2.is(r4)) return true; | 5870 if (r2.is(r4)) return true; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5697 // bytes of instructions without failing with buffer size constraints. | 5885 // bytes of instructions without failing with buffer size constraints. |
| 5698 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 5886 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 5699 } | 5887 } |
| 5700 | 5888 |
| 5701 | 5889 |
| 5702 CodePatcher::~CodePatcher() { | 5890 CodePatcher::~CodePatcher() { |
| 5703 // Indicate that code has changed. | 5891 // Indicate that code has changed. |
| 5704 if (flush_cache_ == FLUSH) { | 5892 if (flush_cache_ == FLUSH) { |
| 5705 CpuFeatures::FlushICache(address_, size_); | 5893 CpuFeatures::FlushICache(address_, size_); |
| 5706 } | 5894 } |
| 5707 | |
| 5708 // Check that the code was patched as expected. | 5895 // Check that the code was patched as expected. |
| 5709 ASSERT(masm_.pc_ == address_ + size_); | 5896 ASSERT(masm_.pc_ == address_ + size_); |
| 5710 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 5897 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 5711 } | 5898 } |
| 5712 | 5899 |
| 5713 | 5900 |
| 5714 void CodePatcher::Emit(Instr instr) { | 5901 void CodePatcher::Emit(Instr instr) { |
| 5715 masm()->emit(instr); | 5902 masm()->emit(instr); |
| 5716 } | 5903 } |
| 5717 | 5904 |
| 5718 | 5905 |
| 5719 void CodePatcher::Emit(Address addr) { | 5906 void CodePatcher::Emit(Address addr) { |
| 5720 masm()->emit(reinterpret_cast<Instr>(addr)); | 5907 // masm()->emit(reinterpret_cast<Instr>(addr)); |
| 5721 } | 5908 } |
| 5722 | 5909 |
| 5723 | 5910 |
| 5724 void CodePatcher::ChangeBranchCondition(Condition cond) { | 5911 void CodePatcher::ChangeBranchCondition(Condition cond) { |
| 5725 Instr instr = Assembler::instr_at(masm_.pc_); | 5912 Instr instr = Assembler::instr_at(masm_.pc_); |
| 5726 ASSERT(Assembler::IsBranch(instr)); | 5913 ASSERT(Assembler::IsBranch(instr)); |
| 5727 uint32_t opcode = Assembler::GetOpcodeField(instr); | 5914 uint32_t opcode = Assembler::GetOpcodeField(instr); |
| 5728 // Currently only the 'eq' and 'ne' cond values are supported and the simple | 5915 // Currently only the 'eq' and 'ne' cond values are supported and the simple |
| 5729 // branch instructions (with opcode being the branch type). | 5916 // branch instructions (with opcode being the branch type). |
| 5730 // There are some special cases (see Assembler::IsBranch()) so extending this | 5917 // There are some special cases (see Assembler::IsBranch()) so extending this |
| (...skipping 29 matching lines...) Expand all Loading... |
| 5760 Subu(result, result, Operand(dividend)); | 5947 Subu(result, result, Operand(dividend)); |
| 5761 } | 5948 } |
| 5762 if (ms.shift() > 0) sra(result, result, ms.shift()); | 5949 if (ms.shift() > 0) sra(result, result, ms.shift()); |
| 5763 srl(at, dividend, 31); | 5950 srl(at, dividend, 31); |
| 5764 Addu(result, result, Operand(at)); | 5951 Addu(result, result, Operand(at)); |
| 5765 } | 5952 } |
| 5766 | 5953 |
| 5767 | 5954 |
| 5768 } } // namespace v8::internal | 5955 } } // namespace v8::internal |
| 5769 | 5956 |
| 5770 #endif // V8_TARGET_ARCH_MIPS | 5957 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |