| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 : Assembler(arg_isolate, buffer, size), | 43 : Assembler(arg_isolate, buffer, size), |
| 44 generating_stub_(false), | 44 generating_stub_(false), |
| 45 allow_stub_calls_(true) { | 45 allow_stub_calls_(true) { |
| 46 if (isolate() != NULL) { | 46 if (isolate() != NULL) { |
| 47 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), | 47 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), |
| 48 isolate()); | 48 isolate()); |
| 49 } | 49 } |
| 50 } | 50 } |
| 51 | 51 |
| 52 | 52 |
| 53 // Arguments macros. | |
| 54 #define COND_TYPED_ARGS Condition cond, Register r1, const Operand& r2 | |
| 55 #define COND_ARGS cond, r1, r2 | |
| 56 | |
| 57 #define REGISTER_TARGET_BODY(Name) \ | |
| 58 void MacroAssembler::Name(Register target, \ | |
| 59 BranchDelaySlot bd) { \ | |
| 60 Name(Operand(target), bd); \ | |
| 61 } \ | |
| 62 void MacroAssembler::Name(Register target, COND_TYPED_ARGS, \ | |
| 63 BranchDelaySlot bd) { \ | |
| 64 Name(Operand(target), COND_ARGS, bd); \ | |
| 65 } | |
| 66 | |
| 67 | |
| 68 #define INT_PTR_TARGET_BODY(Name) \ | |
| 69 void MacroAssembler::Name(intptr_t target, RelocInfo::Mode rmode, \ | |
| 70 BranchDelaySlot bd) { \ | |
| 71 Name(Operand(target, rmode), bd); \ | |
| 72 } \ | |
| 73 void MacroAssembler::Name(intptr_t target, \ | |
| 74 RelocInfo::Mode rmode, \ | |
| 75 COND_TYPED_ARGS, \ | |
| 76 BranchDelaySlot bd) { \ | |
| 77 Name(Operand(target, rmode), COND_ARGS, bd); \ | |
| 78 } | |
| 79 | |
| 80 | |
| 81 #define BYTE_PTR_TARGET_BODY(Name) \ | |
| 82 void MacroAssembler::Name(byte* target, RelocInfo::Mode rmode, \ | |
| 83 BranchDelaySlot bd) { \ | |
| 84 Name(reinterpret_cast<intptr_t>(target), rmode, bd); \ | |
| 85 } \ | |
| 86 void MacroAssembler::Name(byte* target, \ | |
| 87 RelocInfo::Mode rmode, \ | |
| 88 COND_TYPED_ARGS, \ | |
| 89 BranchDelaySlot bd) { \ | |
| 90 Name(reinterpret_cast<intptr_t>(target), rmode, COND_ARGS, bd); \ | |
| 91 } | |
| 92 | |
| 93 | |
| 94 #define CODE_TARGET_BODY(Name) \ | |
| 95 void MacroAssembler::Name(Handle<Code> target, RelocInfo::Mode rmode, \ | |
| 96 BranchDelaySlot bd) { \ | |
| 97 Name(reinterpret_cast<intptr_t>(target.location()), rmode, bd); \ | |
| 98 } \ | |
| 99 void MacroAssembler::Name(Handle<Code> target, \ | |
| 100 RelocInfo::Mode rmode, \ | |
| 101 COND_TYPED_ARGS, \ | |
| 102 BranchDelaySlot bd) { \ | |
| 103 Name(reinterpret_cast<intptr_t>(target.location()), rmode, COND_ARGS, bd); \ | |
| 104 } | |
| 105 | |
| 106 | |
| 107 REGISTER_TARGET_BODY(Jump) | |
| 108 REGISTER_TARGET_BODY(Call) | |
| 109 INT_PTR_TARGET_BODY(Jump) | |
| 110 INT_PTR_TARGET_BODY(Call) | |
| 111 BYTE_PTR_TARGET_BODY(Jump) | |
| 112 BYTE_PTR_TARGET_BODY(Call) | |
| 113 CODE_TARGET_BODY(Jump) | |
| 114 CODE_TARGET_BODY(Call) | |
| 115 | |
| 116 #undef COND_TYPED_ARGS | |
| 117 #undef COND_ARGS | |
| 118 #undef REGISTER_TARGET_BODY | |
| 119 #undef BYTE_PTR_TARGET_BODY | |
| 120 #undef CODE_TARGET_BODY | |
| 121 | |
| 122 | |
| 123 void MacroAssembler::Ret(BranchDelaySlot bd) { | |
| 124 Jump(Operand(ra), bd); | |
| 125 } | |
| 126 | |
| 127 | |
| 128 void MacroAssembler::Ret(Condition cond, Register r1, const Operand& r2, | |
| 129 BranchDelaySlot bd) { | |
| 130 Jump(Operand(ra), cond, r1, r2, bd); | |
| 131 } | |
| 132 | |
| 133 | |
| 134 void MacroAssembler::LoadRoot(Register destination, | 53 void MacroAssembler::LoadRoot(Register destination, |
| 135 Heap::RootListIndex index) { | 54 Heap::RootListIndex index) { |
| 136 lw(destination, MemOperand(s6, index << kPointerSizeLog2)); | 55 lw(destination, MemOperand(s6, index << kPointerSizeLog2)); |
| 137 } | 56 } |
| 138 | 57 |
| 139 | 58 |
| 140 void MacroAssembler::LoadRoot(Register destination, | 59 void MacroAssembler::LoadRoot(Register destination, |
| 141 Heap::RootListIndex index, | 60 Heap::RootListIndex index, |
| 142 Condition cond, | 61 Condition cond, |
| 143 Register src1, const Operand& src2) { | 62 Register src1, const Operand& src2) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 kPageSizeBits - Page::kRegionSizeLog2); | 105 kPageSizeBits - Page::kRegionSizeLog2); |
| 187 | 106 |
| 188 // Mark region dirty. | 107 // Mark region dirty. |
| 189 lw(scratch, MemOperand(object, Page::kDirtyFlagOffset)); | 108 lw(scratch, MemOperand(object, Page::kDirtyFlagOffset)); |
| 190 li(at, Operand(1)); | 109 li(at, Operand(1)); |
| 191 sllv(at, at, address); | 110 sllv(at, at, address); |
| 192 or_(scratch, scratch, at); | 111 or_(scratch, scratch, at); |
| 193 sw(scratch, MemOperand(object, Page::kDirtyFlagOffset)); | 112 sw(scratch, MemOperand(object, Page::kDirtyFlagOffset)); |
| 194 } | 113 } |
| 195 | 114 |
| 115 |
| 196 // Push and pop all registers that can hold pointers. | 116 // Push and pop all registers that can hold pointers. |
| 197 void MacroAssembler::PushSafepointRegisters() { | 117 void MacroAssembler::PushSafepointRegisters() { |
| 198 // Safepoints expect a block of kNumSafepointRegisters values on the | 118 // Safepoints expect a block of kNumSafepointRegisters values on the |
| 199 // stack, so adjust the stack for unsaved registers. | 119 // stack, so adjust the stack for unsaved registers. |
| 200 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 120 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 201 ASSERT(num_unsaved >= 0); | 121 ASSERT(num_unsaved >= 0); |
| 202 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); | 122 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 203 MultiPush(kSafepointSavedRegisters); | 123 MultiPush(kSafepointSavedRegisters); |
| 204 } | 124 } |
| 205 | 125 |
| 126 |
| 206 void MacroAssembler::PopSafepointRegisters() { | 127 void MacroAssembler::PopSafepointRegisters() { |
| 207 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 128 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 208 MultiPop(kSafepointSavedRegisters); | 129 MultiPop(kSafepointSavedRegisters); |
| 209 Addu(sp, sp, Operand(num_unsaved * kPointerSize)); | 130 Addu(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 210 } | 131 } |
| 211 | 132 |
| 133 |
| 212 void MacroAssembler::PushSafepointRegistersAndDoubles() { | 134 void MacroAssembler::PushSafepointRegistersAndDoubles() { |
| 213 PushSafepointRegisters(); | 135 PushSafepointRegisters(); |
| 214 Subu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize)); | 136 Subu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize)); |
| 215 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) { | 137 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) { |
| 216 FPURegister reg = FPURegister::FromAllocationIndex(i); | 138 FPURegister reg = FPURegister::FromAllocationIndex(i); |
| 217 sdc1(reg, MemOperand(sp, i * kDoubleSize)); | 139 sdc1(reg, MemOperand(sp, i * kDoubleSize)); |
| 218 } | 140 } |
| 219 } | 141 } |
| 220 | 142 |
| 143 |
| 221 void MacroAssembler::PopSafepointRegistersAndDoubles() { | 144 void MacroAssembler::PopSafepointRegistersAndDoubles() { |
| 222 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) { | 145 for (int i = 0; i < FPURegister::kNumAllocatableRegisters; i+=2) { |
| 223 FPURegister reg = FPURegister::FromAllocationIndex(i); | 146 FPURegister reg = FPURegister::FromAllocationIndex(i); |
| 224 ldc1(reg, MemOperand(sp, i * kDoubleSize)); | 147 ldc1(reg, MemOperand(sp, i * kDoubleSize)); |
| 225 } | 148 } |
| 226 Addu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize)); | 149 Addu(sp, sp, Operand(FPURegister::kNumAllocatableRegisters * kDoubleSize)); |
| 227 PopSafepointRegisters(); | 150 PopSafepointRegisters(); |
| 228 } | 151 } |
| 229 | 152 |
| 153 |
| 230 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src, | 154 void MacroAssembler::StoreToSafepointRegistersAndDoublesSlot(Register src, |
| 231 Register dst) { | 155 Register dst) { |
| 232 sw(src, SafepointRegistersAndDoublesSlot(dst)); | 156 sw(src, SafepointRegistersAndDoublesSlot(dst)); |
| 233 } | 157 } |
| 234 | 158 |
| 235 | 159 |
| 236 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { | 160 void MacroAssembler::StoreToSafepointRegisterSlot(Register src, Register dst) { |
| 237 sw(src, SafepointRegisterSlot(dst)); | 161 sw(src, SafepointRegisterSlot(dst)); |
| 238 } | 162 } |
| 239 | 163 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 Context::SECURITY_TOKEN_INDEX * kPointerSize; | 336 Context::SECURITY_TOKEN_INDEX * kPointerSize; |
| 413 | 337 |
| 414 lw(scratch, FieldMemOperand(scratch, token_offset)); | 338 lw(scratch, FieldMemOperand(scratch, token_offset)); |
| 415 lw(at, FieldMemOperand(at, token_offset)); | 339 lw(at, FieldMemOperand(at, token_offset)); |
| 416 Branch(miss, ne, scratch, Operand(at)); | 340 Branch(miss, ne, scratch, Operand(at)); |
| 417 | 341 |
| 418 bind(&same_contexts); | 342 bind(&same_contexts); |
| 419 } | 343 } |
| 420 | 344 |
| 421 | 345 |
| 346 void MacroAssembler::LoadFromNumberDictionary(Label* miss, |
| 347 Register elements, |
| 348 Register key, |
| 349 Register result, |
| 350 Register reg0, |
| 351 Register reg1, |
| 352 Register reg2) { |
| 353 // Register use: |
| 354 // |
| 355 // elements - holds the slow-case elements of the receiver on entry. |
| 356 // Unchanged unless 'result' is the same register. |
| 357 // |
| 358 // key - holds the smi key on entry. |
| 359 // Unchanged unless 'result' is the same register. |
| 360 // |
| 361 // |
| 362 // result - holds the result on exit if the load succeeded. |
| 363 // Allowed to be the same as 'key' or 'result'. |
| 364 // Unchanged on bailout so 'key' or 'result' can be used |
| 365 // in further computation. |
| 366 // |
| 367 // Scratch registers: |
| 368 // |
| 369 // reg0 - holds the untagged key on entry and holds the hash once computed. |
| 370 // |
| 371 // reg1 - Used to hold the capacity mask of the dictionary. |
| 372 // |
| 373 // reg2 - Used for the index into the dictionary. |
| 374 // at - Temporary (avoid MacroAssembler instructions also using 'at'). |
| 375 Label done; |
| 376 |
| 377 // Compute the hash code from the untagged key. This must be kept in sync |
| 378 // with ComputeIntegerHash in utils.h. |
| 379 // |
| 380 // hash = ~hash + (hash << 15); |
| 381 nor(reg1, reg0, zero_reg); |
| 382 sll(at, reg0, 15); |
| 383 addu(reg0, reg1, at); |
| 384 |
| 385 // hash = hash ^ (hash >> 12); |
| 386 srl(at, reg0, 12); |
| 387 xor_(reg0, reg0, at); |
| 388 |
| 389 // hash = hash + (hash << 2); |
| 390 sll(at, reg0, 2); |
| 391 addu(reg0, reg0, at); |
| 392 |
| 393 // hash = hash ^ (hash >> 4); |
| 394 srl(at, reg0, 4); |
| 395 xor_(reg0, reg0, at); |
| 396 |
| 397 // hash = hash * 2057; |
| 398 li(reg1, Operand(2057)); |
| 399 mul(reg0, reg0, reg1); |
| 400 |
| 401 // hash = hash ^ (hash >> 16); |
| 402 srl(at, reg0, 16); |
| 403 xor_(reg0, reg0, at); |
| 404 |
| 405 // Compute the capacity mask. |
| 406 lw(reg1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); |
| 407 sra(reg1, reg1, kSmiTagSize); |
| 408 Subu(reg1, reg1, Operand(1)); |
| 409 |
| 410 // Generate an unrolled loop that performs a few probes before giving up. |
| 411 static const int kProbes = 4; |
| 412 for (int i = 0; i < kProbes; i++) { |
| 413 // Use reg2 for index calculations and keep the hash intact in reg0. |
| 414 mov(reg2, reg0); |
| 415 // Compute the masked index: (hash + i + i * i) & mask. |
| 416 if (i > 0) { |
| 417 Addu(reg2, reg2, Operand(NumberDictionary::GetProbeOffset(i))); |
| 418 } |
| 419 and_(reg2, reg2, reg1); |
| 420 |
| 421 // Scale the index by multiplying by the element size. |
| 422 ASSERT(NumberDictionary::kEntrySize == 3); |
| 423 sll(at, reg2, 1); // 2x. |
| 424 addu(reg2, reg2, at); // reg2 = reg2 * 3. |
| 425 |
| 426 // Check if the key is identical to the name. |
| 427 sll(at, reg2, kPointerSizeLog2); |
| 428 addu(reg2, elements, at); |
| 429 |
| 430 lw(at, FieldMemOperand(reg2, NumberDictionary::kElementsStartOffset)); |
| 431 if (i != kProbes - 1) { |
| 432 Branch(&done, eq, key, Operand(at)); |
| 433 } else { |
| 434 Branch(miss, ne, key, Operand(at)); |
| 435 } |
| 436 } |
| 437 |
| 438 bind(&done); |
| 439 // Check that the value is a normal property. |
| 440 // reg2: elements + (index * kPointerSize). |
| 441 const int kDetailsOffset = |
| 442 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
| 443 lw(reg1, FieldMemOperand(reg2, kDetailsOffset)); |
| 444 And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::mask()))); |
| 445 Branch(miss, ne, at, Operand(zero_reg)); |
| 446 |
| 447 // Get the value at the masked, scaled index and return. |
| 448 const int kValueOffset = |
| 449 NumberDictionary::kElementsStartOffset + kPointerSize; |
| 450 lw(result, FieldMemOperand(reg2, kValueOffset)); |
| 451 } |
| 452 |
| 453 |
| 422 // --------------------------------------------------------------------------- | 454 // --------------------------------------------------------------------------- |
| 423 // Instruction macros. | 455 // Instruction macros. |
| 424 | 456 |
| 425 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { | 457 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { |
| 426 if (rt.is_reg()) { | 458 if (rt.is_reg()) { |
| 427 addu(rd, rs, rt.rm()); | 459 addu(rd, rs, rt.rm()); |
| 428 } else { | 460 } else { |
| 429 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 461 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
| 430 addiu(rd, rs, rt.imm32_); | 462 addiu(rd, rs, rt.imm32_); |
| 431 } else { | 463 } else { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 RecordRelocInfo(j.rmode_, j.imm32_); | 695 RecordRelocInfo(j.rmode_, j.imm32_); |
| 664 } | 696 } |
| 665 // We need always the same number of instructions as we may need to patch | 697 // We need always the same number of instructions as we may need to patch |
| 666 // this code to load another value which may need 2 instructions to load. | 698 // this code to load another value which may need 2 instructions to load. |
| 667 lui(rd, (j.imm32_ & kHiMask) >> kLuiShift); | 699 lui(rd, (j.imm32_ & kHiMask) >> kLuiShift); |
| 668 ori(rd, rd, (j.imm32_ & kImm16Mask)); | 700 ori(rd, rd, (j.imm32_ & kImm16Mask)); |
| 669 } | 701 } |
| 670 } | 702 } |
| 671 | 703 |
| 672 | 704 |
| 673 // Exception-generating instructions and debugging support. | |
| 674 void MacroAssembler::stop(const char* msg) { | |
| 675 // TO_UPGRADE: Just a break for now. Maybe we could upgrade it. | |
| 676 // We use the 0x54321 value to be able to find it easily when reading memory. | |
| 677 break_(0x54321); | |
| 678 } | |
| 679 | |
| 680 | |
| 681 void MacroAssembler::MultiPush(RegList regs) { | 705 void MacroAssembler::MultiPush(RegList regs) { |
| 682 int16_t NumSaved = 0; | 706 int16_t NumSaved = 0; |
| 683 int16_t NumToPush = NumberOfBitsSet(regs); | 707 int16_t NumToPush = NumberOfBitsSet(regs); |
| 684 | 708 |
| 685 addiu(sp, sp, -4 * NumToPush); | 709 addiu(sp, sp, -4 * NumToPush); |
| 686 for (int16_t i = kNumRegisters; i > 0; i--) { | 710 for (int16_t i = kNumRegisters; i > 0; i--) { |
| 687 if ((regs & (1 << i)) != 0) { | 711 if ((regs & (1 << i)) != 0) { |
| 688 sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved))); | 712 sw(ToRegister(i), MemOperand(sp, 4 * (NumToPush - ++NumSaved))); |
| 689 } | 713 } |
| 690 } | 714 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 | 857 |
| 834 | 858 |
| 835 void MacroAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs) { | 859 void MacroAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs) { |
| 836 Trunc_uw_d(fs, t4); | 860 Trunc_uw_d(fs, t4); |
| 837 mtc1(t4, fd); | 861 mtc1(t4, fd); |
| 838 } | 862 } |
| 839 | 863 |
| 840 | 864 |
| 841 void MacroAssembler::Trunc_uw_d(FPURegister fd, Register rs) { | 865 void MacroAssembler::Trunc_uw_d(FPURegister fd, Register rs) { |
| 842 ASSERT(!fd.is(f22)); | 866 ASSERT(!fd.is(f22)); |
| 843 ASSERT(!rs.is(t6)); | 867 ASSERT(!rs.is(t8)); |
| 844 | 868 |
| 845 // Load 2^31 into f22. | 869 // Load 2^31 into f22. |
| 846 Or(t6, zero_reg, 0x80000000); | 870 Or(t8, zero_reg, 0x80000000); |
| 847 Cvt_d_uw(f22, t6); | 871 Cvt_d_uw(f22, t8); |
| 848 | 872 |
| 849 // Test if f22 > fd. | 873 // Test if f22 > fd. |
| 850 c(OLT, D, fd, f22); | 874 c(OLT, D, fd, f22); |
| 851 | 875 |
| 852 Label simple_convert; | 876 Label simple_convert; |
| 853 // If fd < 2^31 we can convert it normally. | 877 // If fd < 2^31 we can convert it normally. |
| 854 bc1t(&simple_convert); | 878 bc1t(&simple_convert); |
| 855 | 879 |
| 856 // First we subtract 2^31 from fd, then trunc it to rs | 880 // First we subtract 2^31 from fd, then trunc it to rs |
| 857 // and add 2^31 to rs. | 881 // and add 2^31 to rs. |
| 858 | 882 |
| 859 sub_d(f22, fd, f22); | 883 sub_d(f22, fd, f22); |
| 860 trunc_w_d(f22, f22); | 884 trunc_w_d(f22, f22); |
| 861 mfc1(rs, f22); | 885 mfc1(rs, f22); |
| 862 or_(rs, rs, t6); | 886 or_(rs, rs, t8); |
| 863 | 887 |
| 864 Label done; | 888 Label done; |
| 865 Branch(&done); | 889 Branch(&done); |
| 866 // Simple conversion. | 890 // Simple conversion. |
| 867 bind(&simple_convert); | 891 bind(&simple_convert); |
| 868 trunc_w_d(f22, fd); | 892 trunc_w_d(f22, fd); |
| 869 mfc1(rs, f22); | 893 mfc1(rs, f22); |
| 870 | 894 |
| 871 bind(&done); | 895 bind(&done); |
| 872 } | 896 } |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1045 // Restore sign if necessary. | 1069 // Restore sign if necessary. |
| 1046 mov(scratch, sign); | 1070 mov(scratch, sign); |
| 1047 result = sign; | 1071 result = sign; |
| 1048 sign = no_reg; | 1072 sign = no_reg; |
| 1049 Subu(result, zero_reg, input_high); | 1073 Subu(result, zero_reg, input_high); |
| 1050 movz(result, input_high, scratch); | 1074 movz(result, input_high, scratch); |
| 1051 bind(&done); | 1075 bind(&done); |
| 1052 } | 1076 } |
| 1053 | 1077 |
| 1054 | 1078 |
| 1079 void MacroAssembler::EmitECMATruncate(Register result, |
| 1080 FPURegister double_input, |
| 1081 FPURegister single_scratch, |
| 1082 Register scratch, |
| 1083 Register input_high, |
| 1084 Register input_low) { |
| 1085 CpuFeatures::Scope scope(FPU); |
| 1086 ASSERT(!input_high.is(result)); |
| 1087 ASSERT(!input_low.is(result)); |
| 1088 ASSERT(!input_low.is(input_high)); |
| 1089 ASSERT(!scratch.is(result) && |
| 1090 !scratch.is(input_high) && |
| 1091 !scratch.is(input_low)); |
| 1092 ASSERT(!single_scratch.is(double_input)); |
| 1093 |
| 1094 Label done; |
| 1095 Label manual; |
| 1096 |
| 1097 // Clear cumulative exception flags and save the FCSR. |
| 1098 Register scratch2 = input_high; |
| 1099 cfc1(scratch2, FCSR); |
| 1100 ctc1(zero_reg, FCSR); |
| 1101 // Try a conversion to a signed integer. |
| 1102 trunc_w_d(single_scratch, double_input); |
| 1103 mfc1(result, single_scratch); |
| 1104 // Retrieve and restore the FCSR. |
| 1105 cfc1(scratch, FCSR); |
| 1106 ctc1(scratch2, FCSR); |
| 1107 // Check for overflow and NaNs. |
| 1108 And(scratch, |
| 1109 scratch, |
| 1110 kFCSROverflowFlagMask | kFCSRUnderflowFlagMask | kFCSRInvalidOpFlagMask); |
| 1111 // If we had no exceptions we are done. |
| 1112 Branch(&done, eq, scratch, Operand(zero_reg)); |
| 1113 |
| 1114 // Load the double value and perform a manual truncation. |
| 1115 Move(input_low, input_high, double_input); |
| 1116 EmitOutOfInt32RangeTruncate(result, |
| 1117 input_high, |
| 1118 input_low, |
| 1119 scratch); |
| 1120 bind(&done); |
| 1121 } |
| 1122 |
| 1123 |
| 1055 void MacroAssembler::GetLeastBitsFromSmi(Register dst, | 1124 void MacroAssembler::GetLeastBitsFromSmi(Register dst, |
| 1056 Register src, | 1125 Register src, |
| 1057 int num_least_bits) { | 1126 int num_least_bits) { |
| 1058 Ext(dst, src, kSmiTagSize, num_least_bits); | 1127 Ext(dst, src, kSmiTagSize, num_least_bits); |
| 1059 } | 1128 } |
| 1060 | 1129 |
| 1061 | 1130 |
| 1062 void MacroAssembler::GetLeastBitsFromInt32(Register dst, | 1131 void MacroAssembler::GetLeastBitsFromInt32(Register dst, |
| 1063 Register src, | 1132 Register src, |
| 1064 int num_least_bits) { | 1133 int num_least_bits) { |
| 1065 And(dst, src, Operand((1 << num_least_bits) - 1)); | 1134 And(dst, src, Operand((1 << num_least_bits) - 1)); |
| 1066 } | 1135 } |
| 1067 | 1136 |
| 1068 | 1137 |
| 1069 // Emulated condtional branches do not emit a nop in the branch delay slot. | 1138 // Emulated condtional branches do not emit a nop in the branch delay slot. |
| 1070 // | 1139 // |
| 1071 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. | 1140 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. |
| 1072 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \ | 1141 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \ |
| 1073 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ | 1142 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ |
| 1074 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) | 1143 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) |
| 1075 | 1144 |
| 1076 | 1145 |
| 1146 bool MacroAssembler::UseAbsoluteCodePointers() { |
| 1147 if (is_trampoline_emitted()) { |
| 1148 return true; |
| 1149 } else { |
| 1150 return false; |
| 1151 } |
| 1152 } |
| 1153 |
| 1154 |
| 1077 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { | 1155 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { |
| 1156 BranchShort(offset, bdslot); |
| 1157 } |
| 1158 |
| 1159 |
| 1160 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
| 1161 const Operand& rt, |
| 1162 BranchDelaySlot bdslot) { |
| 1163 BranchShort(offset, cond, rs, rt, bdslot); |
| 1164 } |
| 1165 |
| 1166 |
| 1167 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { |
| 1168 bool is_label_near = is_near(L); |
| 1169 if (UseAbsoluteCodePointers() && !is_label_near) { |
| 1170 Jr(L, bdslot); |
| 1171 } else { |
| 1172 BranchShort(L, bdslot); |
| 1173 } |
| 1174 } |
| 1175 |
| 1176 |
| 1177 void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
| 1178 const Operand& rt, |
| 1179 BranchDelaySlot bdslot) { |
| 1180 bool is_label_near = is_near(L); |
| 1181 if (UseAbsoluteCodePointers() && !is_label_near) { |
| 1182 Label skip; |
| 1183 Condition neg_cond = NegateCondition(cond); |
| 1184 BranchShort(&skip, neg_cond, rs, rt); |
| 1185 Jr(L, bdslot); |
| 1186 bind(&skip); |
| 1187 } else { |
| 1188 BranchShort(L, cond, rs, rt, bdslot); |
| 1189 } |
| 1190 } |
| 1191 |
| 1192 |
| 1193 void MacroAssembler::BranchShort(int16_t offset, BranchDelaySlot bdslot) { |
| 1078 b(offset); | 1194 b(offset); |
| 1079 | 1195 |
| 1080 // Emit a nop in the branch delay slot if required. | 1196 // Emit a nop in the branch delay slot if required. |
| 1081 if (bdslot == PROTECT) | 1197 if (bdslot == PROTECT) |
| 1082 nop(); | 1198 nop(); |
| 1083 } | 1199 } |
| 1084 | 1200 |
| 1085 | 1201 |
| 1086 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, | 1202 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, |
| 1087 const Operand& rt, | 1203 const Operand& rt, |
| 1088 BranchDelaySlot bdslot) { | 1204 BranchDelaySlot bdslot) { |
| 1089 BRANCH_ARGS_CHECK(cond, rs, rt); | 1205 BRANCH_ARGS_CHECK(cond, rs, rt); |
| 1090 ASSERT(!rs.is(zero_reg)); | 1206 ASSERT(!rs.is(zero_reg)); |
| 1091 Register r2 = no_reg; | 1207 Register r2 = no_reg; |
| 1092 Register scratch = at; | 1208 Register scratch = at; |
| 1093 | 1209 |
| 1094 if (rt.is_reg()) { | 1210 if (rt.is_reg()) { |
| 1095 // We don't want any other register but scratch clobbered. | 1211 // We don't want any other register but scratch clobbered. |
| 1096 ASSERT(!scratch.is(rs) && !scratch.is(rt.rm_)); | 1212 ASSERT(!scratch.is(rs) && !scratch.is(rt.rm_)); |
| 1097 r2 = rt.rm_; | 1213 r2 = rt.rm_; |
| 1098 switch (cond) { | 1214 switch (cond) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 case Ugreater_equal: | 1266 case Ugreater_equal: |
| 1151 if (r2.is(zero_reg)) { | 1267 if (r2.is(zero_reg)) { |
| 1152 bgez(rs, offset); | 1268 bgez(rs, offset); |
| 1153 } else { | 1269 } else { |
| 1154 sltu(scratch, rs, r2); | 1270 sltu(scratch, rs, r2); |
| 1155 beq(scratch, zero_reg, offset); | 1271 beq(scratch, zero_reg, offset); |
| 1156 } | 1272 } |
| 1157 break; | 1273 break; |
| 1158 case Uless: | 1274 case Uless: |
| 1159 if (r2.is(zero_reg)) { | 1275 if (r2.is(zero_reg)) { |
| 1160 b(offset); | 1276 // No code needs to be emitted. |
| 1277 return; |
| 1161 } else { | 1278 } else { |
| 1162 sltu(scratch, rs, r2); | 1279 sltu(scratch, rs, r2); |
| 1163 bne(scratch, zero_reg, offset); | 1280 bne(scratch, zero_reg, offset); |
| 1164 } | 1281 } |
| 1165 break; | 1282 break; |
| 1166 case Uless_equal: | 1283 case Uless_equal: |
| 1167 if (r2.is(zero_reg)) { | 1284 if (r2.is(zero_reg)) { |
| 1168 b(offset); | 1285 b(offset); |
| 1169 } else { | 1286 } else { |
| 1170 sltu(scratch, r2, rs); | 1287 sltu(scratch, r2, rs); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 break; | 1326 break; |
| 1210 case greater_equal: | 1327 case greater_equal: |
| 1211 if (rt.imm32_ == 0) { | 1328 if (rt.imm32_ == 0) { |
| 1212 bgez(rs, offset); | 1329 bgez(rs, offset); |
| 1213 } else if (is_int16(rt.imm32_)) { | 1330 } else if (is_int16(rt.imm32_)) { |
| 1214 slti(scratch, rs, rt.imm32_); | 1331 slti(scratch, rs, rt.imm32_); |
| 1215 beq(scratch, zero_reg, offset); | 1332 beq(scratch, zero_reg, offset); |
| 1216 } else { | 1333 } else { |
| 1217 r2 = scratch; | 1334 r2 = scratch; |
| 1218 li(r2, rt); | 1335 li(r2, rt); |
| 1219 sltu(scratch, rs, r2); | 1336 slt(scratch, rs, r2); |
| 1220 beq(scratch, zero_reg, offset); | 1337 beq(scratch, zero_reg, offset); |
| 1221 } | 1338 } |
| 1222 break; | 1339 break; |
| 1223 case less: | 1340 case less: |
| 1224 if (rt.imm32_ == 0) { | 1341 if (rt.imm32_ == 0) { |
| 1225 bltz(rs, offset); | 1342 bltz(rs, offset); |
| 1226 } else if (is_int16(rt.imm32_)) { | 1343 } else if (is_int16(rt.imm32_)) { |
| 1227 slti(scratch, rs, rt.imm32_); | 1344 slti(scratch, rs, rt.imm32_); |
| 1228 bne(scratch, zero_reg, offset); | 1345 bne(scratch, zero_reg, offset); |
| 1229 } else { | 1346 } else { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 beq(scratch, zero_reg, offset); | 1379 beq(scratch, zero_reg, offset); |
| 1263 } else { | 1380 } else { |
| 1264 r2 = scratch; | 1381 r2 = scratch; |
| 1265 li(r2, rt); | 1382 li(r2, rt); |
| 1266 sltu(scratch, rs, r2); | 1383 sltu(scratch, rs, r2); |
| 1267 beq(scratch, zero_reg, offset); | 1384 beq(scratch, zero_reg, offset); |
| 1268 } | 1385 } |
| 1269 break; | 1386 break; |
| 1270 case Uless: | 1387 case Uless: |
| 1271 if (rt.imm32_ == 0) { | 1388 if (rt.imm32_ == 0) { |
| 1272 b(offset); | 1389 // No code needs to be emitted. |
| 1390 return; |
| 1273 } else if (is_int16(rt.imm32_)) { | 1391 } else if (is_int16(rt.imm32_)) { |
| 1274 sltiu(scratch, rs, rt.imm32_); | 1392 sltiu(scratch, rs, rt.imm32_); |
| 1275 bne(scratch, zero_reg, offset); | 1393 bne(scratch, zero_reg, offset); |
| 1276 } else { | 1394 } else { |
| 1277 r2 = scratch; | 1395 r2 = scratch; |
| 1278 li(r2, rt); | 1396 li(r2, rt); |
| 1279 sltu(scratch, rs, r2); | 1397 sltu(scratch, rs, r2); |
| 1280 bne(scratch, zero_reg, offset); | 1398 bne(scratch, zero_reg, offset); |
| 1281 } | 1399 } |
| 1282 break; | 1400 break; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1293 default: | 1411 default: |
| 1294 UNREACHABLE(); | 1412 UNREACHABLE(); |
| 1295 } | 1413 } |
| 1296 } | 1414 } |
| 1297 // Emit a nop in the branch delay slot if required. | 1415 // Emit a nop in the branch delay slot if required. |
| 1298 if (bdslot == PROTECT) | 1416 if (bdslot == PROTECT) |
| 1299 nop(); | 1417 nop(); |
| 1300 } | 1418 } |
| 1301 | 1419 |
| 1302 | 1420 |
| 1303 void MacroAssembler::Branch(Label* L, BranchDelaySlot bdslot) { | 1421 void MacroAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) { |
| 1304 // We use branch_offset as an argument for the branch instructions to be sure | 1422 // We use branch_offset as an argument for the branch instructions to be sure |
| 1305 // it is called just before generating the branch instruction, as needed. | 1423 // it is called just before generating the branch instruction, as needed. |
| 1306 | 1424 |
| 1307 b(shifted_branch_offset(L, false)); | 1425 b(shifted_branch_offset(L, false)); |
| 1308 | 1426 |
| 1309 // Emit a nop in the branch delay slot if required. | 1427 // Emit a nop in the branch delay slot if required. |
| 1310 if (bdslot == PROTECT) | 1428 if (bdslot == PROTECT) |
| 1311 nop(); | 1429 nop(); |
| 1312 } | 1430 } |
| 1313 | 1431 |
| 1314 | 1432 |
| 1315 void MacroAssembler::Branch(Label* L, Condition cond, Register rs, | 1433 void MacroAssembler::BranchShort(Label* L, Condition cond, Register rs, |
| 1316 const Operand& rt, | 1434 const Operand& rt, |
| 1317 BranchDelaySlot bdslot) { | 1435 BranchDelaySlot bdslot) { |
| 1318 BRANCH_ARGS_CHECK(cond, rs, rt); | 1436 BRANCH_ARGS_CHECK(cond, rs, rt); |
| 1319 | 1437 |
| 1320 int32_t offset; | 1438 int32_t offset; |
| 1321 Register r2 = no_reg; | 1439 Register r2 = no_reg; |
| 1322 Register scratch = at; | 1440 Register scratch = at; |
| 1323 if (rt.is_reg()) { | 1441 if (rt.is_reg()) { |
| 1324 r2 = rt.rm_; | 1442 r2 = rt.rm_; |
| 1325 // Be careful to always use shifted_branch_offset only just before the | 1443 // Be careful to always use shifted_branch_offset only just before the |
| 1326 // branch instruction, as the location will be remember for patching the | 1444 // branch instruction, as the location will be remember for patching the |
| 1327 // target. | 1445 // target. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1395 offset = shifted_branch_offset(L, false); | 1513 offset = shifted_branch_offset(L, false); |
| 1396 bgez(rs, offset); | 1514 bgez(rs, offset); |
| 1397 } else { | 1515 } else { |
| 1398 sltu(scratch, rs, r2); | 1516 sltu(scratch, rs, r2); |
| 1399 offset = shifted_branch_offset(L, false); | 1517 offset = shifted_branch_offset(L, false); |
| 1400 beq(scratch, zero_reg, offset); | 1518 beq(scratch, zero_reg, offset); |
| 1401 } | 1519 } |
| 1402 break; | 1520 break; |
| 1403 case Uless: | 1521 case Uless: |
| 1404 if (r2.is(zero_reg)) { | 1522 if (r2.is(zero_reg)) { |
| 1405 offset = shifted_branch_offset(L, false); | 1523 // No code needs to be emitted. |
| 1406 b(offset); | 1524 return; |
| 1407 } else { | 1525 } else { |
| 1408 sltu(scratch, rs, r2); | 1526 sltu(scratch, rs, r2); |
| 1409 offset = shifted_branch_offset(L, false); | 1527 offset = shifted_branch_offset(L, false); |
| 1410 bne(scratch, zero_reg, offset); | 1528 bne(scratch, zero_reg, offset); |
| 1411 } | 1529 } |
| 1412 break; | 1530 break; |
| 1413 case Uless_equal: | 1531 case Uless_equal: |
| 1414 if (r2.is(zero_reg)) { | 1532 if (r2.is(zero_reg)) { |
| 1415 offset = shifted_branch_offset(L, false); | 1533 offset = shifted_branch_offset(L, false); |
| 1416 b(offset); | 1534 b(offset); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1461 if (rt.imm32_ == 0) { | 1579 if (rt.imm32_ == 0) { |
| 1462 offset = shifted_branch_offset(L, false); | 1580 offset = shifted_branch_offset(L, false); |
| 1463 bgez(rs, offset); | 1581 bgez(rs, offset); |
| 1464 } else if (is_int16(rt.imm32_)) { | 1582 } else if (is_int16(rt.imm32_)) { |
| 1465 slti(scratch, rs, rt.imm32_); | 1583 slti(scratch, rs, rt.imm32_); |
| 1466 offset = shifted_branch_offset(L, false); | 1584 offset = shifted_branch_offset(L, false); |
| 1467 beq(scratch, zero_reg, offset); | 1585 beq(scratch, zero_reg, offset); |
| 1468 } else { | 1586 } else { |
| 1469 r2 = scratch; | 1587 r2 = scratch; |
| 1470 li(r2, rt); | 1588 li(r2, rt); |
| 1471 sltu(scratch, rs, r2); | 1589 slt(scratch, rs, r2); |
| 1472 offset = shifted_branch_offset(L, false); | 1590 offset = shifted_branch_offset(L, false); |
| 1473 beq(scratch, zero_reg, offset); | 1591 beq(scratch, zero_reg, offset); |
| 1474 } | 1592 } |
| 1475 break; | 1593 break; |
| 1476 case less: | 1594 case less: |
| 1477 if (rt.imm32_ == 0) { | 1595 if (rt.imm32_ == 0) { |
| 1478 offset = shifted_branch_offset(L, false); | 1596 offset = shifted_branch_offset(L, false); |
| 1479 bltz(rs, offset); | 1597 bltz(rs, offset); |
| 1480 } else if (is_int16(rt.imm32_)) { | 1598 } else if (is_int16(rt.imm32_)) { |
| 1481 slti(scratch, rs, rt.imm32_); | 1599 slti(scratch, rs, rt.imm32_); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1525 } else { | 1643 } else { |
| 1526 r2 = scratch; | 1644 r2 = scratch; |
| 1527 li(r2, rt); | 1645 li(r2, rt); |
| 1528 sltu(scratch, rs, r2); | 1646 sltu(scratch, rs, r2); |
| 1529 offset = shifted_branch_offset(L, false); | 1647 offset = shifted_branch_offset(L, false); |
| 1530 beq(scratch, zero_reg, offset); | 1648 beq(scratch, zero_reg, offset); |
| 1531 } | 1649 } |
| 1532 break; | 1650 break; |
| 1533 case Uless: | 1651 case Uless: |
| 1534 if (rt.imm32_ == 0) { | 1652 if (rt.imm32_ == 0) { |
| 1535 offset = shifted_branch_offset(L, false); | 1653 // No code needs to be emitted. |
| 1536 b(offset); | 1654 return; |
| 1537 } else if (is_int16(rt.imm32_)) { | 1655 } else if (is_int16(rt.imm32_)) { |
| 1538 sltiu(scratch, rs, rt.imm32_); | 1656 sltiu(scratch, rs, rt.imm32_); |
| 1539 offset = shifted_branch_offset(L, false); | 1657 offset = shifted_branch_offset(L, false); |
| 1540 bne(scratch, zero_reg, offset); | 1658 bne(scratch, zero_reg, offset); |
| 1541 } else { | 1659 } else { |
| 1542 r2 = scratch; | 1660 r2 = scratch; |
| 1543 li(r2, rt); | 1661 li(r2, rt); |
| 1544 sltu(scratch, rs, r2); | 1662 sltu(scratch, rs, r2); |
| 1545 offset = shifted_branch_offset(L, false); | 1663 offset = shifted_branch_offset(L, false); |
| 1546 bne(scratch, zero_reg, offset); | 1664 bne(scratch, zero_reg, offset); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1563 } | 1681 } |
| 1564 } | 1682 } |
| 1565 // Check that offset could actually hold on an int16_t. | 1683 // Check that offset could actually hold on an int16_t. |
| 1566 ASSERT(is_int16(offset)); | 1684 ASSERT(is_int16(offset)); |
| 1567 // Emit a nop in the branch delay slot if required. | 1685 // Emit a nop in the branch delay slot if required. |
| 1568 if (bdslot == PROTECT) | 1686 if (bdslot == PROTECT) |
| 1569 nop(); | 1687 nop(); |
| 1570 } | 1688 } |
| 1571 | 1689 |
| 1572 | 1690 |
| 1691 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) { |
| 1692 BranchAndLinkShort(offset, bdslot); |
| 1693 } |
| 1694 |
| 1695 |
| 1696 void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs, |
| 1697 const Operand& rt, |
| 1698 BranchDelaySlot bdslot) { |
| 1699 BranchAndLinkShort(offset, cond, rs, rt, bdslot); |
| 1700 } |
| 1701 |
| 1702 |
| 1703 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { |
| 1704 bool is_label_near = is_near(L); |
| 1705 if (UseAbsoluteCodePointers() && !is_label_near) { |
| 1706 Jalr(L, bdslot); |
| 1707 } else { |
| 1708 BranchAndLinkShort(L, bdslot); |
| 1709 } |
| 1710 } |
| 1711 |
| 1712 |
| 1713 void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs, |
| 1714 const Operand& rt, |
| 1715 BranchDelaySlot bdslot) { |
| 1716 bool is_label_near = is_near(L); |
| 1717 if (UseAbsoluteCodePointers() && !is_label_near) { |
| 1718 Label skip; |
| 1719 Condition neg_cond = NegateCondition(cond); |
| 1720 BranchShort(&skip, neg_cond, rs, rt); |
| 1721 Jalr(L, bdslot); |
| 1722 bind(&skip); |
| 1723 } else { |
| 1724 BranchAndLinkShort(L, cond, rs, rt, bdslot); |
| 1725 } |
| 1726 } |
| 1727 |
| 1728 |
| 1573 // We need to use a bgezal or bltzal, but they can't be used directly with the | 1729 // We need to use a bgezal or bltzal, but they can't be used directly with the |
| 1574 // slt instructions. We could use sub or add instead but we would miss overflow | 1730 // slt instructions. We could use sub or add instead but we would miss overflow |
| 1575 // cases, so we keep slt and add an intermediate third instruction. | 1731 // cases, so we keep slt and add an intermediate third instruction. |
| 1576 void MacroAssembler::BranchAndLink(int16_t offset, | 1732 void MacroAssembler::BranchAndLinkShort(int16_t offset, |
| 1577 BranchDelaySlot bdslot) { | 1733 BranchDelaySlot bdslot) { |
| 1578 bal(offset); | 1734 bal(offset); |
| 1579 | 1735 |
| 1580 // Emit a nop in the branch delay slot if required. | 1736 // Emit a nop in the branch delay slot if required. |
| 1581 if (bdslot == PROTECT) | 1737 if (bdslot == PROTECT) |
| 1582 nop(); | 1738 nop(); |
| 1583 } | 1739 } |
| 1584 | 1740 |
| 1585 | 1741 |
| 1586 void MacroAssembler::BranchAndLink(int16_t offset, Condition cond, Register rs, | 1742 void MacroAssembler::BranchAndLinkShort(int16_t offset, Condition cond, |
| 1587 const Operand& rt, | 1743 Register rs, const Operand& rt, |
| 1588 BranchDelaySlot bdslot) { | 1744 BranchDelaySlot bdslot) { |
| 1589 BRANCH_ARGS_CHECK(cond, rs, rt); | 1745 BRANCH_ARGS_CHECK(cond, rs, rt); |
| 1590 Register r2 = no_reg; | 1746 Register r2 = no_reg; |
| 1591 Register scratch = at; | 1747 Register scratch = at; |
| 1592 | 1748 |
| 1593 if (rt.is_reg()) { | 1749 if (rt.is_reg()) { |
| 1594 r2 = rt.rm_; | 1750 r2 = rt.rm_; |
| 1595 } else if (cond != cc_always) { | 1751 } else if (cond != cc_always) { |
| 1596 r2 = scratch; | 1752 r2 = scratch; |
| 1597 li(r2, rt); | 1753 li(r2, rt); |
| 1598 } | 1754 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1658 | 1814 |
| 1659 default: | 1815 default: |
| 1660 UNREACHABLE(); | 1816 UNREACHABLE(); |
| 1661 } | 1817 } |
| 1662 // Emit a nop in the branch delay slot if required. | 1818 // Emit a nop in the branch delay slot if required. |
| 1663 if (bdslot == PROTECT) | 1819 if (bdslot == PROTECT) |
| 1664 nop(); | 1820 nop(); |
| 1665 } | 1821 } |
| 1666 | 1822 |
| 1667 | 1823 |
| 1668 void MacroAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { | 1824 void MacroAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) { |
| 1669 bal(shifted_branch_offset(L, false)); | 1825 bal(shifted_branch_offset(L, false)); |
| 1670 | 1826 |
| 1671 // Emit a nop in the branch delay slot if required. | 1827 // Emit a nop in the branch delay slot if required. |
| 1672 if (bdslot == PROTECT) | 1828 if (bdslot == PROTECT) |
| 1673 nop(); | 1829 nop(); |
| 1674 } | 1830 } |
| 1675 | 1831 |
| 1676 | 1832 |
| 1677 void MacroAssembler::BranchAndLink(Label* L, Condition cond, Register rs, | 1833 void MacroAssembler::BranchAndLinkShort(Label* L, Condition cond, Register rs, |
| 1678 const Operand& rt, | 1834 const Operand& rt, |
| 1679 BranchDelaySlot bdslot) { | 1835 BranchDelaySlot bdslot) { |
| 1680 BRANCH_ARGS_CHECK(cond, rs, rt); | 1836 BRANCH_ARGS_CHECK(cond, rs, rt); |
| 1681 | 1837 |
| 1682 int32_t offset; | 1838 int32_t offset; |
| 1683 Register r2 = no_reg; | 1839 Register r2 = no_reg; |
| 1684 Register scratch = at; | 1840 Register scratch = at; |
| 1685 if (rt.is_reg()) { | 1841 if (rt.is_reg()) { |
| 1686 r2 = rt.rm_; | 1842 r2 = rt.rm_; |
| 1687 } else if (cond != cc_always) { | 1843 } else if (cond != cc_always) { |
| 1688 r2 = scratch; | 1844 r2 = scratch; |
| 1689 li(r2, rt); | 1845 li(r2, rt); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1765 | 1921 |
| 1766 // Check that offset could actually hold on an int16_t. | 1922 // Check that offset could actually hold on an int16_t. |
| 1767 ASSERT(is_int16(offset)); | 1923 ASSERT(is_int16(offset)); |
| 1768 | 1924 |
| 1769 // Emit a nop in the branch delay slot if required. | 1925 // Emit a nop in the branch delay slot if required. |
| 1770 if (bdslot == PROTECT) | 1926 if (bdslot == PROTECT) |
| 1771 nop(); | 1927 nop(); |
| 1772 } | 1928 } |
| 1773 | 1929 |
| 1774 | 1930 |
| 1775 void MacroAssembler::Jump(const Operand& target, BranchDelaySlot bdslot) { | 1931 void MacroAssembler::Jump(Register target, |
| 1932 Condition cond, |
| 1933 Register rs, |
| 1934 const Operand& rt, |
| 1935 BranchDelaySlot bd) { |
| 1776 BlockTrampolinePoolScope block_trampoline_pool(this); | 1936 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1777 if (target.is_reg()) { | 1937 if (cond == cc_always) { |
| 1778 jr(target.rm()); | 1938 jr(target); |
| 1779 } else { | 1939 } else { |
| 1780 if (!MustUseReg(target.rmode_)) { | 1940 BRANCH_ARGS_CHECK(cond, rs, rt); |
| 1781 j(target.imm32_); | 1941 Branch(2, NegateCondition(cond), rs, rt); |
| 1782 } else { | 1942 jr(target); |
| 1783 li(t9, target); | |
| 1784 jr(t9); | |
| 1785 } | |
| 1786 } | 1943 } |
| 1787 // Emit a nop in the branch delay slot if required. | 1944 // Emit a nop in the branch delay slot if required. |
| 1788 if (bdslot == PROTECT) | 1945 if (bd == PROTECT) |
| 1789 nop(); | 1946 nop(); |
| 1790 } | 1947 } |
| 1791 | 1948 |
| 1792 | 1949 |
| 1793 void MacroAssembler::Jump(const Operand& target, | 1950 void MacroAssembler::Jump(intptr_t target, |
| 1794 Condition cond, Register rs, const Operand& rt, | 1951 RelocInfo::Mode rmode, |
| 1795 BranchDelaySlot bdslot) { | 1952 Condition cond, |
| 1796 BlockTrampolinePoolScope block_trampoline_pool(this); | 1953 Register rs, |
| 1797 BRANCH_ARGS_CHECK(cond, rs, rt); | 1954 const Operand& rt, |
| 1798 if (target.is_reg()) { | 1955 BranchDelaySlot bd) { |
| 1799 if (cond == cc_always) { | 1956 li(t9, Operand(target, rmode)); |
| 1800 jr(target.rm()); | 1957 Jump(t9, cond, rs, rt, bd); |
| 1801 } else { | |
| 1802 Branch(2, NegateCondition(cond), rs, rt); | |
| 1803 jr(target.rm()); | |
| 1804 } | |
| 1805 } else { // Not register target. | |
| 1806 if (!MustUseReg(target.rmode_)) { | |
| 1807 if (cond == cc_always) { | |
| 1808 j(target.imm32_); | |
| 1809 } else { | |
| 1810 Branch(2, NegateCondition(cond), rs, rt); | |
| 1811 j(target.imm32_); // Will generate only one instruction. | |
| 1812 } | |
| 1813 } else { // MustUseReg(target). | |
| 1814 li(t9, target); | |
| 1815 if (cond == cc_always) { | |
| 1816 jr(t9); | |
| 1817 } else { | |
| 1818 Branch(2, NegateCondition(cond), rs, rt); | |
| 1819 jr(t9); // Will generate only one instruction. | |
| 1820 } | |
| 1821 } | |
| 1822 } | |
| 1823 // Emit a nop in the branch delay slot if required. | |
| 1824 if (bdslot == PROTECT) | |
| 1825 nop(); | |
| 1826 } | 1958 } |
| 1827 | 1959 |
| 1828 | 1960 |
| 1829 int MacroAssembler::CallSize(Handle<Code> code, RelocInfo::Mode rmode) { | 1961 void MacroAssembler::Jump(Address target, |
| 1830 return 4 * kInstrSize; | 1962 RelocInfo::Mode rmode, |
| 1963 Condition cond, |
| 1964 Register rs, |
| 1965 const Operand& rt, |
| 1966 BranchDelaySlot bd) { |
| 1967 ASSERT(!RelocInfo::IsCodeTarget(rmode)); |
| 1968 Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd); |
| 1831 } | 1969 } |
| 1832 | 1970 |
| 1833 | 1971 |
| 1834 int MacroAssembler::CallSize(Register reg) { | 1972 void MacroAssembler::Jump(Handle<Code> code, |
| 1835 return 2 * kInstrSize; | 1973 RelocInfo::Mode rmode, |
| 1974 Condition cond, |
| 1975 Register rs, |
| 1976 const Operand& rt, |
| 1977 BranchDelaySlot bd) { |
| 1978 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 1979 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd); |
| 1980 } |
| 1981 |
| 1982 |
| 1983 int MacroAssembler::CallSize(Register target, |
| 1984 Condition cond, |
| 1985 Register rs, |
| 1986 const Operand& rt, |
| 1987 BranchDelaySlot bd) { |
| 1988 int size = 0; |
| 1989 |
| 1990 if (cond == cc_always) { |
| 1991 size += 1; |
| 1992 } else { |
| 1993 size += 3; |
| 1994 } |
| 1995 |
| 1996 if (bd == PROTECT) |
| 1997 size += 1; |
| 1998 |
| 1999 return size * kInstrSize; |
| 1836 } | 2000 } |
| 1837 | 2001 |
| 1838 | 2002 |
| 1839 // Note: To call gcc-compiled C code on mips, you must call thru t9. | 2003 // Note: To call gcc-compiled C code on mips, you must call thru t9. |
| 1840 void MacroAssembler::Call(const Operand& target, BranchDelaySlot bdslot) { | 2004 void MacroAssembler::Call(Register target, |
| 2005 Condition cond, |
| 2006 Register rs, |
| 2007 const Operand& rt, |
| 2008 BranchDelaySlot bd) { |
| 1841 BlockTrampolinePoolScope block_trampoline_pool(this); | 2009 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1842 if (target.is_reg()) { | 2010 Label start; |
| 1843 jalr(target.rm()); | 2011 bind(&start); |
| 1844 } else { // !target.is_reg(). | 2012 if (cond == cc_always) { |
| 1845 if (!MustUseReg(target.rmode_)) { | 2013 jalr(target); |
| 1846 jal(target.imm32_); | 2014 } else { |
| 1847 } else { // MustUseReg(target). | 2015 BRANCH_ARGS_CHECK(cond, rs, rt); |
| 1848 // Must record previous source positions before the | 2016 Branch(2, NegateCondition(cond), rs, rt); |
| 1849 // li() generates a new code target. | 2017 jalr(target); |
| 1850 positions_recorder()->WriteRecordedPositions(); | 2018 } |
| 1851 li(t9, target); | 2019 // Emit a nop in the branch delay slot if required. |
| 1852 jalr(t9); | 2020 if (bd == PROTECT) |
| 1853 } | 2021 nop(); |
| 2022 |
| 2023 ASSERT_EQ(CallSize(target, cond, rs, rt, bd), |
| 2024 SizeOfCodeGeneratedSince(&start)); |
| 2025 } |
| 2026 |
| 2027 |
| 2028 int MacroAssembler::CallSize(Address target, |
| 2029 RelocInfo::Mode rmode, |
| 2030 Condition cond, |
| 2031 Register rs, |
| 2032 const Operand& rt, |
| 2033 BranchDelaySlot bd) { |
| 2034 int size = CallSize(t9, cond, rs, rt, bd); |
| 2035 return size + 2 * kInstrSize; |
| 2036 } |
| 2037 |
| 2038 |
| 2039 void MacroAssembler::Call(Address target, |
| 2040 RelocInfo::Mode rmode, |
| 2041 Condition cond, |
| 2042 Register rs, |
| 2043 const Operand& rt, |
| 2044 BranchDelaySlot bd) { |
| 2045 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2046 Label start; |
| 2047 bind(&start); |
| 2048 int32_t target_int = reinterpret_cast<int32_t>(target); |
| 2049 // Must record previous source positions before the |
| 2050 // li() generates a new code target. |
| 2051 positions_recorder()->WriteRecordedPositions(); |
| 2052 li(t9, Operand(target_int, rmode), true); |
| 2053 Call(t9, cond, rs, rt, bd); |
| 2054 ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd), |
| 2055 SizeOfCodeGeneratedSince(&start)); |
| 2056 } |
| 2057 |
| 2058 |
| 2059 int MacroAssembler::CallSize(Handle<Code> code, |
| 2060 RelocInfo::Mode rmode, |
| 2061 unsigned ast_id, |
| 2062 Condition cond, |
| 2063 Register rs, |
| 2064 const Operand& rt, |
| 2065 BranchDelaySlot bd) { |
| 2066 return CallSize(reinterpret_cast<Address>(code.location()), |
| 2067 rmode, cond, rs, rt, bd); |
| 2068 } |
| 2069 |
| 2070 |
| 2071 void MacroAssembler::Call(Handle<Code> code, |
| 2072 RelocInfo::Mode rmode, |
| 2073 unsigned ast_id, |
| 2074 Condition cond, |
| 2075 Register rs, |
| 2076 const Operand& rt, |
| 2077 BranchDelaySlot bd) { |
| 2078 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2079 Label start; |
| 2080 bind(&start); |
| 2081 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 2082 if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) { |
| 2083 ASSERT(ast_id_for_reloc_info_ == kNoASTId); |
| 2084 ast_id_for_reloc_info_ = ast_id; |
| 2085 rmode = RelocInfo::CODE_TARGET_WITH_ID; |
| 2086 } |
| 2087 Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd); |
| 2088 ASSERT_EQ(CallSize(code, rmode, ast_id, cond, rs, rt), |
| 2089 SizeOfCodeGeneratedSince(&start)); |
| 2090 } |
| 2091 |
| 2092 |
| 2093 void MacroAssembler::Ret(Condition cond, |
| 2094 Register rs, |
| 2095 const Operand& rt, |
| 2096 BranchDelaySlot bd) { |
| 2097 Jump(ra, cond, rs, rt, bd); |
| 2098 } |
| 2099 |
| 2100 |
| 2101 void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) { |
| 2102 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 2103 |
| 2104 uint32_t imm28; |
| 2105 imm28 = jump_address(L); |
| 2106 imm28 &= kImm28Mask; |
| 2107 { BlockGrowBufferScope block_buf_growth(this); |
| 2108 // Buffer growth (and relocation) must be blocked for internal references |
| 2109 // until associated instructions are emitted and available to be patched. |
| 2110 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2111 j(imm28); |
| 1854 } | 2112 } |
| 1855 // Emit a nop in the branch delay slot if required. | 2113 // Emit a nop in the branch delay slot if required. |
| 1856 if (bdslot == PROTECT) | 2114 if (bdslot == PROTECT) |
| 1857 nop(); | |
| 1858 } | |
| 1859 | |
| 1860 | |
| 1861 // Note: To call gcc-compiled C code on mips, you must call thru t9. | |
| 1862 void MacroAssembler::Call(const Operand& target, | |
| 1863 Condition cond, Register rs, const Operand& rt, | |
| 1864 BranchDelaySlot bdslot) { | |
| 1865 BlockTrampolinePoolScope block_trampoline_pool(this); | |
| 1866 BRANCH_ARGS_CHECK(cond, rs, rt); | |
| 1867 if (target.is_reg()) { | |
| 1868 if (cond == cc_always) { | |
| 1869 jalr(target.rm()); | |
| 1870 } else { | |
| 1871 Branch(2, NegateCondition(cond), rs, rt); | |
| 1872 jalr(target.rm()); | |
| 1873 } | |
| 1874 } else { // !target.is_reg(). | |
| 1875 if (!MustUseReg(target.rmode_)) { | |
| 1876 if (cond == cc_always) { | |
| 1877 jal(target.imm32_); | |
| 1878 } else { | |
| 1879 Branch(2, NegateCondition(cond), rs, rt); | |
| 1880 jal(target.imm32_); // Will generate only one instruction. | |
| 1881 } | |
| 1882 } else { // MustUseReg(target) | |
| 1883 li(t9, target); | |
| 1884 if (cond == cc_always) { | |
| 1885 jalr(t9); | |
| 1886 } else { | |
| 1887 Branch(2, NegateCondition(cond), rs, rt); | |
| 1888 jalr(t9); // Will generate only one instruction. | |
| 1889 } | |
| 1890 } | |
| 1891 } | |
| 1892 // Emit a nop in the branch delay slot if required. | |
| 1893 if (bdslot == PROTECT) | |
| 1894 nop(); | 2115 nop(); |
| 1895 } | 2116 } |
| 1896 | 2117 |
| 1897 | 2118 |
| 1898 void MacroAssembler::CallWithAstId(Handle<Code> code, | 2119 void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) { |
| 1899 RelocInfo::Mode rmode, | 2120 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1900 unsigned ast_id, | 2121 |
| 1901 Condition cond, | 2122 uint32_t imm32; |
| 1902 Register r1, | 2123 imm32 = jump_address(L); |
| 1903 const Operand& r2) { | 2124 { BlockGrowBufferScope block_buf_growth(this); |
| 1904 ASSERT(rmode == RelocInfo::CODE_TARGET_WITH_ID); | 2125 // Buffer growth (and relocation) must be blocked for internal references |
| 1905 ASSERT(ast_id != kNoASTId); | 2126 // until associated instructions are emitted and available to be patched. |
| 1906 ASSERT(ast_id_for_reloc_info_ == kNoASTId); | 2127 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 1907 ast_id_for_reloc_info_ = ast_id; | 2128 lui(at, (imm32 & kHiMask) >> kLuiShift); |
| 1908 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond, r1, r2); | 2129 ori(at, at, (imm32 & kImm16Mask)); |
| 2130 } |
| 2131 jr(at); |
| 2132 |
| 2133 // Emit a nop in the branch delay slot if required. |
| 2134 if (bdslot == PROTECT) |
| 2135 nop(); |
| 1909 } | 2136 } |
| 1910 | 2137 |
| 1911 | 2138 |
| 1912 void MacroAssembler::Drop(int count, | 2139 void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) { |
| 1913 Condition cond, | 2140 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1914 Register reg, | 2141 |
| 1915 const Operand& op) { | 2142 uint32_t imm32; |
| 1916 if (count <= 0) { | 2143 imm32 = jump_address(L); |
| 1917 return; | 2144 { BlockGrowBufferScope block_buf_growth(this); |
| 2145 // Buffer growth (and relocation) must be blocked for internal references |
| 2146 // until associated instructions are emitted and available to be patched. |
| 2147 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2148 lui(at, (imm32 & kHiMask) >> kLuiShift); |
| 2149 ori(at, at, (imm32 & kImm16Mask)); |
| 1918 } | 2150 } |
| 2151 jalr(at); |
| 1919 | 2152 |
| 1920 Label skip; | 2153 // Emit a nop in the branch delay slot if required. |
| 1921 | 2154 if (bdslot == PROTECT) |
| 1922 if (cond != al) { | 2155 nop(); |
| 1923 Branch(&skip, NegateCondition(cond), reg, op); | |
| 1924 } | |
| 1925 | |
| 1926 if (count > 0) { | |
| 1927 addiu(sp, sp, count * kPointerSize); | |
| 1928 } | |
| 1929 | |
| 1930 if (cond != al) { | |
| 1931 bind(&skip); | |
| 1932 } | |
| 1933 } | 2156 } |
| 1934 | 2157 |
| 1935 | 2158 |
| 1936 void MacroAssembler::DropAndRet(int drop, | 2159 void MacroAssembler::DropAndRet(int drop, |
| 1937 Condition cond, | 2160 Condition cond, |
| 1938 Register r1, | 2161 Register r1, |
| 1939 const Operand& r2) { | 2162 const Operand& r2) { |
| 1940 // This is a workaround to make sure only one branch instruction is | 2163 // This is a workaround to make sure only one branch instruction is |
| 1941 // generated. It relies on Drop and Ret not creating branches if | 2164 // generated. It relies on Drop and Ret not creating branches if |
| 1942 // cond == cc_always. | 2165 // cond == cc_always. |
| 1943 Label skip; | 2166 Label skip; |
| 1944 if (cond != cc_always) { | 2167 if (cond != cc_always) { |
| 1945 Branch(&skip, NegateCondition(cond), r1, r2); | 2168 Branch(&skip, NegateCondition(cond), r1, r2); |
| 1946 } | 2169 } |
| 1947 | 2170 |
| 1948 Drop(drop); | 2171 Drop(drop); |
| 1949 Ret(); | 2172 Ret(); |
| 1950 | 2173 |
| 1951 if (cond != cc_always) { | 2174 if (cond != cc_always) { |
| 1952 bind(&skip); | 2175 bind(&skip); |
| 1953 } | 2176 } |
| 1954 } | 2177 } |
| 1955 | 2178 |
| 1956 | 2179 |
| 2180 void MacroAssembler::Drop(int count, |
| 2181 Condition cond, |
| 2182 Register reg, |
| 2183 const Operand& op) { |
| 2184 if (count <= 0) { |
| 2185 return; |
| 2186 } |
| 2187 |
| 2188 Label skip; |
| 2189 |
| 2190 if (cond != al) { |
| 2191 Branch(&skip, NegateCondition(cond), reg, op); |
| 2192 } |
| 2193 |
| 2194 addiu(sp, sp, count * kPointerSize); |
| 2195 |
| 2196 if (cond != al) { |
| 2197 bind(&skip); |
| 2198 } |
| 2199 } |
| 2200 |
| 2201 |
| 2202 |
| 1957 void MacroAssembler::Swap(Register reg1, | 2203 void MacroAssembler::Swap(Register reg1, |
| 1958 Register reg2, | 2204 Register reg2, |
| 1959 Register scratch) { | 2205 Register scratch) { |
| 1960 if (scratch.is(no_reg)) { | 2206 if (scratch.is(no_reg)) { |
| 1961 Xor(reg1, reg1, Operand(reg2)); | 2207 Xor(reg1, reg1, Operand(reg2)); |
| 1962 Xor(reg2, reg2, Operand(reg1)); | 2208 Xor(reg2, reg2, Operand(reg1)); |
| 1963 Xor(reg1, reg1, Operand(reg2)); | 2209 Xor(reg1, reg1, Operand(reg2)); |
| 1964 } else { | 2210 } else { |
| 1965 mov(scratch, reg1); | 2211 mov(scratch, reg1); |
| 1966 mov(reg1, reg2); | 2212 mov(reg1, reg2); |
| 1967 mov(reg2, scratch); | 2213 mov(reg2, scratch); |
| 1968 } | 2214 } |
| 1969 } | 2215 } |
| 1970 | 2216 |
| 1971 | 2217 |
| 1972 void MacroAssembler::Call(Label* target) { | 2218 void MacroAssembler::Call(Label* target) { |
| 1973 BranchAndLink(target); | 2219 BranchAndLink(target); |
| 1974 } | 2220 } |
| 1975 | 2221 |
| 1976 | 2222 |
| 2223 void MacroAssembler::Push(Handle<Object> handle) { |
| 2224 li(at, Operand(handle)); |
| 2225 push(at); |
| 2226 } |
| 2227 |
| 2228 |
| 1977 #ifdef ENABLE_DEBUGGER_SUPPORT | 2229 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1978 | 2230 |
| 1979 void MacroAssembler::DebugBreak() { | 2231 void MacroAssembler::DebugBreak() { |
| 1980 ASSERT(allow_stub_calls()); | 2232 ASSERT(allow_stub_calls()); |
| 1981 mov(a0, zero_reg); | 2233 mov(a0, zero_reg); |
| 1982 li(a1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); | 2234 li(a1, Operand(ExternalReference(Runtime::kDebugBreak, isolate()))); |
| 1983 CEntryStub ces(1); | 2235 CEntryStub ces(1); |
| 1984 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 2236 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| 1985 } | 2237 } |
| 1986 | 2238 |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2508 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 2760 AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 2509 sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); | 2761 sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset)); |
| 2510 } | 2762 } |
| 2511 | 2763 |
| 2512 | 2764 |
| 2513 void MacroAssembler::AllocateHeapNumberWithValue(Register result, | 2765 void MacroAssembler::AllocateHeapNumberWithValue(Register result, |
| 2514 FPURegister value, | 2766 FPURegister value, |
| 2515 Register scratch1, | 2767 Register scratch1, |
| 2516 Register scratch2, | 2768 Register scratch2, |
| 2517 Label* gc_required) { | 2769 Label* gc_required) { |
| 2518 LoadRoot(t6, Heap::kHeapNumberMapRootIndex); | 2770 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
| 2519 AllocateHeapNumber(result, scratch1, scratch2, t6, gc_required); | 2771 AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required); |
| 2520 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset)); | 2772 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset)); |
| 2521 } | 2773 } |
| 2522 | 2774 |
| 2523 | 2775 |
| 2524 // Copies a fixed number of fields of heap objects from src to dst. | 2776 // Copies a fixed number of fields of heap objects from src to dst. |
| 2525 void MacroAssembler::CopyFields(Register dst, | 2777 void MacroAssembler::CopyFields(Register dst, |
| 2526 Register src, | 2778 Register src, |
| 2527 RegList temps, | 2779 RegList temps, |
| 2528 int field_count) { | 2780 int field_count) { |
| 2529 ASSERT((temps & dst.bit()) == 0); | 2781 ASSERT((temps & dst.bit()) == 0); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2598 lbu(scratch, MemOperand(src)); | 2850 lbu(scratch, MemOperand(src)); |
| 2599 Addu(src, src, 1); | 2851 Addu(src, src, 1); |
| 2600 sb(scratch, MemOperand(dst)); | 2852 sb(scratch, MemOperand(dst)); |
| 2601 Addu(dst, dst, 1); | 2853 Addu(dst, dst, 1); |
| 2602 Subu(length, length, Operand(1)); | 2854 Subu(length, length, Operand(1)); |
| 2603 Branch(&byte_loop_1, ne, length, Operand(zero_reg)); | 2855 Branch(&byte_loop_1, ne, length, Operand(zero_reg)); |
| 2604 bind(&done); | 2856 bind(&done); |
| 2605 } | 2857 } |
| 2606 | 2858 |
| 2607 | 2859 |
| 2860 void MacroAssembler::CheckFastElements(Register map, |
| 2861 Register scratch, |
| 2862 Label* fail) { |
| 2863 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0); |
| 2864 lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset)); |
| 2865 Branch(fail, hi, scratch, Operand(Map::kMaximumBitField2FastElementValue)); |
| 2866 } |
| 2867 |
| 2868 |
| 2608 void MacroAssembler::CheckMap(Register obj, | 2869 void MacroAssembler::CheckMap(Register obj, |
| 2609 Register scratch, | 2870 Register scratch, |
| 2610 Handle<Map> map, | 2871 Handle<Map> map, |
| 2611 Label* fail, | 2872 Label* fail, |
| 2612 SmiCheckType smi_check_type) { | 2873 SmiCheckType smi_check_type) { |
| 2613 if (smi_check_type == DO_SMI_CHECK) { | 2874 if (smi_check_type == DO_SMI_CHECK) { |
| 2614 JumpIfSmi(obj, fail); | 2875 JumpIfSmi(obj, fail); |
| 2615 } | 2876 } |
| 2616 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 2877 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 2617 li(at, Operand(map)); | 2878 li(at, Operand(map)); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2768 | 3029 |
| 2769 if (!definitely_matches) { | 3030 if (!definitely_matches) { |
| 2770 if (!code_constant.is_null()) { | 3031 if (!code_constant.is_null()) { |
| 2771 li(a3, Operand(code_constant)); | 3032 li(a3, Operand(code_constant)); |
| 2772 addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag); | 3033 addiu(a3, a3, Code::kHeaderSize - kHeapObjectTag); |
| 2773 } | 3034 } |
| 2774 | 3035 |
| 2775 Handle<Code> adaptor = | 3036 Handle<Code> adaptor = |
| 2776 isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3037 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 2777 if (flag == CALL_FUNCTION) { | 3038 if (flag == CALL_FUNCTION) { |
| 2778 call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); | 3039 call_wrapper.BeforeCall(CallSize(adaptor)); |
| 2779 SetCallKind(t1, call_kind); | 3040 SetCallKind(t1, call_kind); |
| 2780 Call(adaptor, RelocInfo::CODE_TARGET); | 3041 Call(adaptor); |
| 2781 call_wrapper.AfterCall(); | 3042 call_wrapper.AfterCall(); |
| 2782 jmp(done); | 3043 jmp(done); |
| 2783 } else { | 3044 } else { |
| 2784 SetCallKind(t1, call_kind); | 3045 SetCallKind(t1, call_kind); |
| 2785 Jump(adaptor, RelocInfo::CODE_TARGET); | 3046 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 2786 } | 3047 } |
| 2787 bind(®ular_invoke); | 3048 bind(®ular_invoke); |
| 2788 } | 3049 } |
| 2789 } | 3050 } |
| 2790 | 3051 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2854 sra(expected_reg, expected_reg, kSmiTagSize); | 3115 sra(expected_reg, expected_reg, kSmiTagSize); |
| 2855 lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 3116 lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 2856 | 3117 |
| 2857 ParameterCount expected(expected_reg); | 3118 ParameterCount expected(expected_reg); |
| 2858 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); | 3119 InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); |
| 2859 } | 3120 } |
| 2860 | 3121 |
| 2861 | 3122 |
| 2862 void MacroAssembler::InvokeFunction(JSFunction* function, | 3123 void MacroAssembler::InvokeFunction(JSFunction* function, |
| 2863 const ParameterCount& actual, | 3124 const ParameterCount& actual, |
| 2864 InvokeFlag flag) { | 3125 InvokeFlag flag, |
| 3126 CallKind call_kind) { |
| 2865 ASSERT(function->is_compiled()); | 3127 ASSERT(function->is_compiled()); |
| 2866 | 3128 |
| 2867 // Get the function and setup the context. | 3129 // Get the function and setup the context. |
| 2868 li(a1, Operand(Handle<JSFunction>(function))); | 3130 li(a1, Operand(Handle<JSFunction>(function))); |
| 2869 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 3131 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 2870 | 3132 |
| 2871 // Invoke the cached code. | 3133 // Invoke the cached code. |
| 2872 Handle<Code> code(function->code()); | 3134 Handle<Code> code(function->code()); |
| 2873 ParameterCount expected(function->shared()->formal_parameter_count()); | 3135 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2874 if (V8::UseCrankshaft()) { | 3136 if (V8::UseCrankshaft()) { |
| 2875 UNIMPLEMENTED_MIPS(); | 3137 UNIMPLEMENTED_MIPS(); |
| 2876 } else { | 3138 } else { |
| 2877 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); | 3139 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag, call_kind); |
| 2878 } | 3140 } |
| 2879 } | 3141 } |
| 2880 | 3142 |
| 2881 | 3143 |
| 2882 void MacroAssembler::IsObjectJSObjectType(Register heap_object, | 3144 void MacroAssembler::IsObjectJSObjectType(Register heap_object, |
| 2883 Register map, | 3145 Register map, |
| 2884 Register scratch, | 3146 Register scratch, |
| 2885 Label* fail) { | 3147 Label* fail) { |
| 2886 lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); | 3148 lw(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); |
| 2887 IsInstanceJSObjectType(map, scratch, fail); | 3149 IsInstanceJSObjectType(map, scratch, fail); |
| 2888 } | 3150 } |
| 2889 | 3151 |
| 2890 | 3152 |
| 2891 void MacroAssembler::IsInstanceJSObjectType(Register map, | 3153 void MacroAssembler::IsInstanceJSObjectType(Register map, |
| 2892 Register scratch, | 3154 Register scratch, |
| 2893 Label* fail) { | 3155 Label* fail) { |
| 2894 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 3156 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 2895 Branch(fail, lt, scratch, Operand(FIRST_JS_OBJECT_TYPE)); | 3157 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2896 Branch(fail, gt, scratch, Operand(LAST_JS_OBJECT_TYPE)); | 3158 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
| 2897 } | 3159 } |
| 2898 | 3160 |
| 2899 | 3161 |
| 2900 void MacroAssembler::IsObjectJSStringType(Register object, | 3162 void MacroAssembler::IsObjectJSStringType(Register object, |
| 2901 Register scratch, | 3163 Register scratch, |
| 2902 Label* fail) { | 3164 Label* fail) { |
| 2903 ASSERT(kNotStringTag != 0); | 3165 ASSERT(kNotStringTag != 0); |
| 2904 | 3166 |
| 2905 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3167 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 2906 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3168 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2966 lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 3228 lbu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 2967 } | 3229 } |
| 2968 | 3230 |
| 2969 | 3231 |
| 2970 // ----------------------------------------------------------------------------- | 3232 // ----------------------------------------------------------------------------- |
| 2971 // Runtime calls. | 3233 // Runtime calls. |
| 2972 | 3234 |
| 2973 void MacroAssembler::CallStub(CodeStub* stub, Condition cond, | 3235 void MacroAssembler::CallStub(CodeStub* stub, Condition cond, |
| 2974 Register r1, const Operand& r2) { | 3236 Register r1, const Operand& r2) { |
| 2975 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. | 3237 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
| 2976 Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2); | 3238 Call(stub->GetCode(), RelocInfo::CODE_TARGET, kNoASTId, cond, r1, r2); |
| 2977 } | 3239 } |
| 2978 | 3240 |
| 2979 | 3241 |
| 2980 MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond, | 3242 MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond, |
| 2981 Register r1, const Operand& r2) { | 3243 Register r1, const Operand& r2) { |
| 2982 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. | 3244 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
| 2983 Object* result; | 3245 Object* result; |
| 2984 { MaybeObject* maybe_result = stub->TryGetCode(); | 3246 { MaybeObject* maybe_result = stub->TryGetCode(); |
| 2985 if (!maybe_result->ToObject(&result)) return maybe_result; | 3247 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2986 } | 3248 } |
| 2987 Call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond, r1, r2); | 3249 Call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, |
| 3250 kNoASTId, cond, r1, r2); |
| 2988 return result; | 3251 return result; |
| 2989 } | 3252 } |
| 2990 | 3253 |
| 2991 | 3254 |
| 2992 | |
| 2993 void MacroAssembler::TailCallStub(CodeStub* stub) { | 3255 void MacroAssembler::TailCallStub(CodeStub* stub) { |
| 2994 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. | 3256 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
| 2995 Jump(stub->GetCode(), RelocInfo::CODE_TARGET); | 3257 Jump(stub->GetCode(), RelocInfo::CODE_TARGET); |
| 2996 } | 3258 } |
| 2997 | 3259 |
| 3260 |
| 2998 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, | 3261 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, |
| 2999 Condition cond, | 3262 Condition cond, |
| 3000 Register r1, | 3263 Register r1, |
| 3001 const Operand& r2) { | 3264 const Operand& r2) { |
| 3002 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. | 3265 ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs. |
| 3003 Object* result; | 3266 Object* result; |
| 3004 { MaybeObject* maybe_result = stub->TryGetCode(); | 3267 { MaybeObject* maybe_result = stub->TryGetCode(); |
| 3005 if (!maybe_result->ToObject(&result)) return maybe_result; | 3268 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3006 } | 3269 } |
| 3007 Jump(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond, r1, r2); | 3270 Jump(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond, r1, r2); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3183 Register right, | 3446 Register right, |
| 3184 Register overflow_dst, | 3447 Register overflow_dst, |
| 3185 Register scratch) { | 3448 Register scratch) { |
| 3186 ASSERT(!dst.is(overflow_dst)); | 3449 ASSERT(!dst.is(overflow_dst)); |
| 3187 ASSERT(!dst.is(scratch)); | 3450 ASSERT(!dst.is(scratch)); |
| 3188 ASSERT(!overflow_dst.is(scratch)); | 3451 ASSERT(!overflow_dst.is(scratch)); |
| 3189 ASSERT(!overflow_dst.is(left)); | 3452 ASSERT(!overflow_dst.is(left)); |
| 3190 ASSERT(!overflow_dst.is(right)); | 3453 ASSERT(!overflow_dst.is(right)); |
| 3191 ASSERT(!left.is(right)); | 3454 ASSERT(!left.is(right)); |
| 3192 | 3455 |
| 3193 // TODO(kalmard) There must be a way to optimize dst == left and dst == right | |
| 3194 // cases. | |
| 3195 | |
| 3196 if (dst.is(left)) { | 3456 if (dst.is(left)) { |
| 3197 addu(overflow_dst, left, right); | 3457 mov(scratch, left); // Preserve left. |
| 3198 xor_(dst, overflow_dst, left); | 3458 addu(dst, left, right); // Left is overwritten. |
| 3199 xor_(scratch, overflow_dst, right); | 3459 xor_(scratch, dst, scratch); // Original left. |
| 3200 and_(scratch, scratch, dst); | 3460 xor_(overflow_dst, dst, right); |
| 3201 mov(dst, overflow_dst); | 3461 and_(overflow_dst, overflow_dst, scratch); |
| 3202 mov(overflow_dst, scratch); | |
| 3203 } else if (dst.is(right)) { | 3462 } else if (dst.is(right)) { |
| 3204 addu(overflow_dst, left, right); | 3463 mov(scratch, right); // Preserve right. |
| 3205 xor_(dst, overflow_dst, right); | 3464 addu(dst, left, right); // Right is overwritten. |
| 3206 xor_(scratch, overflow_dst, left); | 3465 xor_(scratch, dst, scratch); // Original right. |
| 3207 and_(scratch, scratch, dst); | 3466 xor_(overflow_dst, dst, left); |
| 3208 mov(dst, overflow_dst); | 3467 and_(overflow_dst, overflow_dst, scratch); |
| 3209 mov(overflow_dst, scratch); | |
| 3210 } else { | 3468 } else { |
| 3211 addu(dst, left, right); | 3469 addu(dst, left, right); |
| 3212 xor_(overflow_dst, dst, left); | 3470 xor_(overflow_dst, dst, left); |
| 3213 xor_(scratch, dst, right); | 3471 xor_(scratch, dst, right); |
| 3214 and_(overflow_dst, scratch, overflow_dst); | 3472 and_(overflow_dst, scratch, overflow_dst); |
| 3215 } | 3473 } |
| 3216 } | 3474 } |
| 3217 | 3475 |
| 3218 | 3476 |
| 3219 void MacroAssembler::SubuAndCheckForOverflow(Register dst, | 3477 void MacroAssembler::SubuAndCheckForOverflow(Register dst, |
| 3220 Register left, | 3478 Register left, |
| 3221 Register right, | 3479 Register right, |
| 3222 Register overflow_dst, | 3480 Register overflow_dst, |
| 3223 Register scratch) { | 3481 Register scratch) { |
| 3224 ASSERT(!dst.is(overflow_dst)); | 3482 ASSERT(!dst.is(overflow_dst)); |
| 3225 ASSERT(!dst.is(scratch)); | 3483 ASSERT(!dst.is(scratch)); |
| 3226 ASSERT(!overflow_dst.is(scratch)); | 3484 ASSERT(!overflow_dst.is(scratch)); |
| 3227 ASSERT(!overflow_dst.is(left)); | 3485 ASSERT(!overflow_dst.is(left)); |
| 3228 ASSERT(!overflow_dst.is(right)); | 3486 ASSERT(!overflow_dst.is(right)); |
| 3229 ASSERT(!left.is(right)); | 3487 ASSERT(!left.is(right)); |
| 3230 ASSERT(!scratch.is(left)); | 3488 ASSERT(!scratch.is(left)); |
| 3231 ASSERT(!scratch.is(right)); | 3489 ASSERT(!scratch.is(right)); |
| 3232 | 3490 |
| 3233 // TODO(kalmard) There must be a way to optimize dst == left and dst == right | |
| 3234 // cases. | |
| 3235 | |
| 3236 if (dst.is(left)) { | 3491 if (dst.is(left)) { |
| 3237 subu(overflow_dst, left, right); | 3492 mov(scratch, left); // Preserve left. |
| 3238 xor_(scratch, overflow_dst, left); | 3493 subu(dst, left, right); // Left is overwritten. |
| 3239 xor_(dst, left, right); | 3494 xor_(overflow_dst, dst, scratch); // scratch is original left. |
| 3240 and_(scratch, scratch, dst); | 3495 xor_(scratch, scratch, right); // scratch is original left. |
| 3241 mov(dst, overflow_dst); | 3496 and_(overflow_dst, scratch, overflow_dst); |
| 3242 mov(overflow_dst, scratch); | |
| 3243 } else if (dst.is(right)) { | 3497 } else if (dst.is(right)) { |
| 3244 subu(overflow_dst, left, right); | 3498 mov(scratch, right); // Preserve right. |
| 3245 xor_(dst, left, right); | 3499 subu(dst, left, right); // Right is overwritten. |
| 3246 xor_(scratch, overflow_dst, left); | 3500 xor_(overflow_dst, dst, left); |
| 3247 and_(scratch, scratch, dst); | 3501 xor_(scratch, left, scratch); // Original right. |
| 3248 mov(dst, overflow_dst); | 3502 and_(overflow_dst, scratch, overflow_dst); |
| 3249 mov(overflow_dst, scratch); | |
| 3250 } else { | 3503 } else { |
| 3251 subu(dst, left, right); | 3504 subu(dst, left, right); |
| 3252 xor_(overflow_dst, dst, left); | 3505 xor_(overflow_dst, dst, left); |
| 3253 xor_(scratch, left, right); | 3506 xor_(scratch, left, right); |
| 3254 and_(overflow_dst, scratch, overflow_dst); | 3507 and_(overflow_dst, scratch, overflow_dst); |
| 3255 } | 3508 } |
| 3256 } | 3509 } |
| 3257 | 3510 |
| 3258 | 3511 |
| 3259 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 3512 void MacroAssembler::CallRuntime(const Runtime::Function* f, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3308 int num_arguments, | 3561 int num_arguments, |
| 3309 int result_size) { | 3562 int result_size) { |
| 3310 // TODO(1236192): Most runtime routines don't need the number of | 3563 // TODO(1236192): Most runtime routines don't need the number of |
| 3311 // arguments passed in because it is constant. At some point we | 3564 // arguments passed in because it is constant. At some point we |
| 3312 // should remove this need and make the runtime routine entry code | 3565 // should remove this need and make the runtime routine entry code |
| 3313 // smarter. | 3566 // smarter. |
| 3314 li(a0, Operand(num_arguments)); | 3567 li(a0, Operand(num_arguments)); |
| 3315 JumpToExternalReference(ext); | 3568 JumpToExternalReference(ext); |
| 3316 } | 3569 } |
| 3317 | 3570 |
| 3571 |
| 3318 MaybeObject* MacroAssembler::TryTailCallExternalReference( | 3572 MaybeObject* MacroAssembler::TryTailCallExternalReference( |
| 3319 const ExternalReference& ext, int num_arguments, int result_size) { | 3573 const ExternalReference& ext, int num_arguments, int result_size) { |
| 3320 // TODO(1236192): Most runtime routines don't need the number of | 3574 // TODO(1236192): Most runtime routines don't need the number of |
| 3321 // arguments passed in because it is constant. At some point we | 3575 // arguments passed in because it is constant. At some point we |
| 3322 // should remove this need and make the runtime routine entry code | 3576 // should remove this need and make the runtime routine entry code |
| 3323 // smarter. | 3577 // smarter. |
| 3324 li(a0, num_arguments); | 3578 li(a0, num_arguments); |
| 3325 return TryJumpToExternalReference(ext); | 3579 return TryJumpToExternalReference(ext); |
| 3326 } | 3580 } |
| 3327 | 3581 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3349 return TryTailCallStub(&stub); | 3603 return TryTailCallStub(&stub); |
| 3350 } | 3604 } |
| 3351 | 3605 |
| 3352 | 3606 |
| 3353 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 3607 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| 3354 InvokeFlag flag, | 3608 InvokeFlag flag, |
| 3355 const CallWrapper& call_wrapper) { | 3609 const CallWrapper& call_wrapper) { |
| 3356 GetBuiltinEntry(t9, id); | 3610 GetBuiltinEntry(t9, id); |
| 3357 if (flag == CALL_FUNCTION) { | 3611 if (flag == CALL_FUNCTION) { |
| 3358 call_wrapper.BeforeCall(CallSize(t9)); | 3612 call_wrapper.BeforeCall(CallSize(t9)); |
| 3613 SetCallKind(t1, CALL_AS_METHOD); |
| 3359 Call(t9); | 3614 Call(t9); |
| 3360 call_wrapper.AfterCall(); | 3615 call_wrapper.AfterCall(); |
| 3361 } else { | 3616 } else { |
| 3362 ASSERT(flag == JUMP_FUNCTION); | 3617 ASSERT(flag == JUMP_FUNCTION); |
| 3618 SetCallKind(t1, CALL_AS_METHOD); |
| 3363 Jump(t9); | 3619 Jump(t9); |
| 3364 } | 3620 } |
| 3365 } | 3621 } |
| 3366 | 3622 |
| 3367 | 3623 |
| 3368 void MacroAssembler::GetBuiltinFunction(Register target, | 3624 void MacroAssembler::GetBuiltinFunction(Register target, |
| 3369 Builtins::JavaScript id) { | 3625 Builtins::JavaScript id) { |
| 3370 // Load the builtins object into target register. | 3626 // Load the builtins object into target register. |
| 3371 lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | 3627 lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 3372 lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); | 3628 lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3502 while (abort_instructions++ < kExpectedAbortInstructions) { | 3758 while (abort_instructions++ < kExpectedAbortInstructions) { |
| 3503 nop(); | 3759 nop(); |
| 3504 } | 3760 } |
| 3505 } | 3761 } |
| 3506 } | 3762 } |
| 3507 | 3763 |
| 3508 | 3764 |
| 3509 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 3765 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
| 3510 if (context_chain_length > 0) { | 3766 if (context_chain_length > 0) { |
| 3511 // Move up the chain of contexts to the context containing the slot. | 3767 // Move up the chain of contexts to the context containing the slot. |
| 3512 lw(dst, MemOperand(cp, Context::SlotOffset(Context::CLOSURE_INDEX))); | 3768 lw(dst, MemOperand(cp, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 3513 // Load the function context (which is the incoming, outer context). | |
| 3514 lw(dst, FieldMemOperand(dst, JSFunction::kContextOffset)); | |
| 3515 for (int i = 1; i < context_chain_length; i++) { | 3769 for (int i = 1; i < context_chain_length; i++) { |
| 3516 lw(dst, MemOperand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); | 3770 lw(dst, MemOperand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 3517 lw(dst, FieldMemOperand(dst, JSFunction::kContextOffset)); | |
| 3518 } | 3771 } |
| 3519 } else { | 3772 } else { |
| 3520 // Slot is in the current function context. Move it into the | 3773 // Slot is in the current function context. Move it into the |
| 3521 // destination register in case we store into it (the write barrier | 3774 // destination register in case we store into it (the write barrier |
| 3522 // cannot be allowed to destroy the context in esi). | 3775 // cannot be allowed to destroy the context in esi). |
| 3523 Move(dst, cp); | 3776 Move(dst, cp); |
| 3524 } | 3777 } |
| 3525 | |
| 3526 // We should not have found a 'with' context by walking the context chain | |
| 3527 // (i.e., the static scope chain and runtime context chain do not agree). | |
| 3528 // A variable occurring in such a scope should have slot type LOOKUP and | |
| 3529 // not CONTEXT. | |
| 3530 if (emit_debug_code()) { | |
| 3531 lw(t9, MemOperand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); | |
| 3532 Check(eq, "Yo dawg, I heard you liked function contexts " | |
| 3533 "so I put function contexts in all your contexts", | |
| 3534 dst, Operand(t9)); | |
| 3535 } | |
| 3536 } | 3778 } |
| 3537 | 3779 |
| 3538 | 3780 |
| 3539 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 3781 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 3540 // Load the global or builtins object from the current context. | 3782 // Load the global or builtins object from the current context. |
| 3541 lw(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | 3783 lw(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 3542 // Load the global context from the global or builtins object. | 3784 // Load the global context from the global or builtins object. |
| 3543 lw(function, FieldMemOperand(function, | 3785 lw(function, FieldMemOperand(function, |
| 3544 GlobalObject::kGlobalContextOffset)); | 3786 GlobalObject::kGlobalContextOffset)); |
| 3545 // Load the function from the global context. | 3787 // Load the function from the global context. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3711 return OS::ActivationFrameAlignment(); | 3953 return OS::ActivationFrameAlignment(); |
| 3712 #else // defined(V8_HOST_ARCH_MIPS) | 3954 #else // defined(V8_HOST_ARCH_MIPS) |
| 3713 // If we are using the simulator then we should always align to the expected | 3955 // If we are using the simulator then we should always align to the expected |
| 3714 // alignment. As the simulator is used to generate snapshots we do not know | 3956 // alignment. As the simulator is used to generate snapshots we do not know |
| 3715 // if the target platform will need alignment, so this is controlled from a | 3957 // if the target platform will need alignment, so this is controlled from a |
| 3716 // flag. | 3958 // flag. |
| 3717 return FLAG_sim_stack_alignment; | 3959 return FLAG_sim_stack_alignment; |
| 3718 #endif // defined(V8_HOST_ARCH_MIPS) | 3960 #endif // defined(V8_HOST_ARCH_MIPS) |
| 3719 } | 3961 } |
| 3720 | 3962 |
| 3963 |
| 3721 void MacroAssembler::AssertStackIsAligned() { | 3964 void MacroAssembler::AssertStackIsAligned() { |
| 3722 if (emit_debug_code()) { | 3965 if (emit_debug_code()) { |
| 3723 const int frame_alignment = ActivationFrameAlignment(); | 3966 const int frame_alignment = ActivationFrameAlignment(); |
| 3724 const int frame_alignment_mask = frame_alignment - 1; | 3967 const int frame_alignment_mask = frame_alignment - 1; |
| 3725 | 3968 |
| 3726 if (frame_alignment > kPointerSize) { | 3969 if (frame_alignment > kPointerSize) { |
| 3727 Label alignment_as_expected; | 3970 Label alignment_as_expected; |
| 3728 ASSERT(IsPowerOf2(frame_alignment)); | 3971 ASSERT(IsPowerOf2(frame_alignment)); |
| 3729 andi(at, sp, frame_alignment_mask); | 3972 andi(at, sp, frame_alignment_mask); |
| 3730 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); | 3973 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 opcode == BGTZL); | 4290 opcode == BGTZL); |
| 4048 opcode = (cond == eq) ? BEQ : BNE; | 4291 opcode = (cond == eq) ? BEQ : BNE; |
| 4049 instr = (instr & ~kOpcodeMask) | opcode; | 4292 instr = (instr & ~kOpcodeMask) | opcode; |
| 4050 masm_.emit(instr); | 4293 masm_.emit(instr); |
| 4051 } | 4294 } |
| 4052 | 4295 |
| 4053 | 4296 |
| 4054 } } // namespace v8::internal | 4297 } } // namespace v8::internal |
| 4055 | 4298 |
| 4056 #endif // V8_TARGET_ARCH_MIPS | 4299 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |