OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 17 matching lines...) Expand all Loading... |
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 // The original source code covered by the above license above has been | 31 // The original source code covered by the above license above has been |
32 // modified significantly by Google Inc. | 32 // modified significantly by Google Inc. |
33 // Copyright 2012 the V8 project authors. All rights reserved. | 33 // Copyright 2012 the V8 project authors. All rights reserved. |
34 | 34 |
35 | 35 |
36 #include "src/v8.h" | 36 #include "src/v8.h" |
37 | 37 |
38 #if V8_TARGET_ARCH_MIPS | 38 #if V8_TARGET_ARCH_MIPS64 |
39 | 39 |
40 #include "src/base/cpu.h" | 40 #include "src/base/cpu.h" |
41 #include "src/mips/assembler-mips-inl.h" | 41 #include "src/mips64/assembler-mips64-inl.h" |
42 #include "src/serialize.h" | 42 #include "src/serialize.h" |
43 | 43 |
44 namespace v8 { | 44 namespace v8 { |
45 namespace internal { | 45 namespace internal { |
46 | 46 |
| 47 |
47 // Get the CPU features enabled by the build. For cross compilation the | 48 // Get the CPU features enabled by the build. For cross compilation the |
48 // preprocessor symbols CAN_USE_FPU_INSTRUCTIONS | 49 // preprocessor symbols CAN_USE_FPU_INSTRUCTIONS |
49 // can be defined to enable FPU instructions when building the | 50 // can be defined to enable FPU instructions when building the |
50 // snapshot. | 51 // snapshot. |
51 static unsigned CpuFeaturesImpliedByCompiler() { | 52 static unsigned CpuFeaturesImpliedByCompiler() { |
52 unsigned answer = 0; | 53 unsigned answer = 0; |
53 #ifdef CAN_USE_FPU_INSTRUCTIONS | 54 #ifdef CAN_USE_FPU_INSTRUCTIONS |
54 answer |= 1u << FPU; | 55 answer |= 1u << FPU; |
55 #endif // def CAN_USE_FPU_INSTRUCTIONS | 56 #endif // def CAN_USE_FPU_INSTRUCTIONS |
56 | 57 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 ASSERT(reg.is_valid()); | 115 ASSERT(reg.is_valid()); |
115 const int kNumbers[] = { | 116 const int kNumbers[] = { |
116 0, // zero_reg | 117 0, // zero_reg |
117 1, // at | 118 1, // at |
118 2, // v0 | 119 2, // v0 |
119 3, // v1 | 120 3, // v1 |
120 4, // a0 | 121 4, // a0 |
121 5, // a1 | 122 5, // a1 |
122 6, // a2 | 123 6, // a2 |
123 7, // a3 | 124 7, // a3 |
124 8, // t0 | 125 8, // a4 |
125 9, // t1 | 126 9, // a5 |
126 10, // t2 | 127 10, // a6 |
127 11, // t3 | 128 11, // a7 |
128 12, // t4 | 129 12, // t0 |
129 13, // t5 | 130 13, // t1 |
130 14, // t6 | 131 14, // t2 |
131 15, // t7 | 132 15, // t3 |
132 16, // s0 | 133 16, // s0 |
133 17, // s1 | 134 17, // s1 |
134 18, // s2 | 135 18, // s2 |
135 19, // s3 | 136 19, // s3 |
136 20, // s4 | 137 20, // s4 |
137 21, // s5 | 138 21, // s5 |
138 22, // s6 | 139 22, // s6 |
139 23, // s7 | 140 23, // s7 |
140 24, // t8 | 141 24, // t8 |
141 25, // t9 | 142 25, // t9 |
142 26, // k0 | 143 26, // k0 |
143 27, // k1 | 144 27, // k1 |
144 28, // gp | 145 28, // gp |
145 29, // sp | 146 29, // sp |
146 30, // fp | 147 30, // fp |
147 31, // ra | 148 31, // ra |
148 }; | 149 }; |
149 return kNumbers[reg.code()]; | 150 return kNumbers[reg.code()]; |
150 } | 151 } |
151 | 152 |
152 | 153 |
153 Register ToRegister(int num) { | 154 Register ToRegister(int num) { |
154 ASSERT(num >= 0 && num < kNumRegisters); | 155 ASSERT(num >= 0 && num < kNumRegisters); |
155 const Register kRegisters[] = { | 156 const Register kRegisters[] = { |
156 zero_reg, | 157 zero_reg, |
157 at, | 158 at, |
158 v0, v1, | 159 v0, v1, |
159 a0, a1, a2, a3, | 160 a0, a1, a2, a3, a4, a5, a6, a7, |
160 t0, t1, t2, t3, t4, t5, t6, t7, | 161 t0, t1, t2, t3, |
161 s0, s1, s2, s3, s4, s5, s6, s7, | 162 s0, s1, s2, s3, s4, s5, s6, s7, |
162 t8, t9, | 163 t8, t9, |
163 k0, k1, | 164 k0, k1, |
164 gp, | 165 gp, |
165 sp, | 166 sp, |
166 fp, | 167 fp, |
167 ra | 168 ra |
168 }; | 169 }; |
169 return kRegisters[num]; | 170 return kRegisters[num]; |
170 } | 171 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 // Implementation of Operand and MemOperand. | 216 // Implementation of Operand and MemOperand. |
216 // See assembler-mips-inl.h for inlined constructors. | 217 // See assembler-mips-inl.h for inlined constructors. |
217 | 218 |
218 Operand::Operand(Handle<Object> handle) { | 219 Operand::Operand(Handle<Object> handle) { |
219 AllowDeferredHandleDereference using_raw_address; | 220 AllowDeferredHandleDereference using_raw_address; |
220 rm_ = no_reg; | 221 rm_ = no_reg; |
221 // Verify all Objects referred by code are NOT in new space. | 222 // Verify all Objects referred by code are NOT in new space. |
222 Object* obj = *handle; | 223 Object* obj = *handle; |
223 if (obj->IsHeapObject()) { | 224 if (obj->IsHeapObject()) { |
224 ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj)); | 225 ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj)); |
225 imm32_ = reinterpret_cast<intptr_t>(handle.location()); | 226 imm64_ = reinterpret_cast<intptr_t>(handle.location()); |
226 rmode_ = RelocInfo::EMBEDDED_OBJECT; | 227 rmode_ = RelocInfo::EMBEDDED_OBJECT; |
227 } else { | 228 } else { |
228 // No relocation needed. | 229 // No relocation needed. |
229 imm32_ = reinterpret_cast<intptr_t>(obj); | 230 imm64_ = reinterpret_cast<intptr_t>(obj); |
230 rmode_ = RelocInfo::NONE32; | 231 rmode_ = RelocInfo::NONE64; |
231 } | 232 } |
232 } | 233 } |
233 | 234 |
234 | 235 |
235 MemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) { | 236 MemOperand::MemOperand(Register rm, int64_t offset) : Operand(rm) { |
236 offset_ = offset; | 237 offset_ = offset; |
237 } | 238 } |
238 | 239 |
239 | 240 |
240 MemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier, | 241 MemOperand::MemOperand(Register rm, int64_t unit, int64_t multiplier, |
241 OffsetAddend offset_addend) : Operand(rm) { | 242 OffsetAddend offset_addend) : Operand(rm) { |
242 offset_ = unit * multiplier + offset_addend; | 243 offset_ = unit * multiplier + offset_addend; |
243 } | 244 } |
244 | 245 |
245 | 246 |
246 // ----------------------------------------------------------------------------- | 247 // ----------------------------------------------------------------------------- |
247 // Specific instructions, constants, and masks. | 248 // Specific instructions, constants, and masks. |
248 | 249 |
249 static const int kNegOffset = 0x00008000; | 250 static const int kNegOffset = 0x00008000; |
250 // addiu(sp, sp, 4) aka Pop() operation or part of Pop(r) | 251 // daddiu(sp, sp, 8) aka Pop() operation or part of Pop(r) |
251 // operations as post-increment of sp. | 252 // operations as post-increment of sp. |
252 const Instr kPopInstruction = ADDIU | (kRegister_sp_Code << kRsShift) | 253 const Instr kPopInstruction = DADDIU | (kRegister_sp_Code << kRsShift) |
253 | (kRegister_sp_Code << kRtShift) | 254 | (kRegister_sp_Code << kRtShift) |
254 | (kPointerSize & kImm16Mask); // NOLINT | 255 | (kPointerSize & kImm16Mask); // NOLINT |
255 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp. | 256 // daddiu(sp, sp, -8) part of Push(r) operation as pre-decrement of sp. |
256 const Instr kPushInstruction = ADDIU | (kRegister_sp_Code << kRsShift) | 257 const Instr kPushInstruction = DADDIU | (kRegister_sp_Code << kRsShift) |
257 | (kRegister_sp_Code << kRtShift) | 258 | (kRegister_sp_Code << kRtShift) |
258 | (-kPointerSize & kImm16Mask); // NOLINT | 259 | (-kPointerSize & kImm16Mask); // NOLINT |
259 // sw(r, MemOperand(sp, 0)) | 260 // sd(r, MemOperand(sp, 0)) |
260 const Instr kPushRegPattern = SW | (kRegister_sp_Code << kRsShift) | 261 const Instr kPushRegPattern = SD | (kRegister_sp_Code << kRsShift) |
261 | (0 & kImm16Mask); // NOLINT | 262 | (0 & kImm16Mask); // NOLINT |
262 // lw(r, MemOperand(sp, 0)) | 263 // ld(r, MemOperand(sp, 0)) |
263 const Instr kPopRegPattern = LW | (kRegister_sp_Code << kRsShift) | 264 const Instr kPopRegPattern = LD | (kRegister_sp_Code << kRsShift) |
264 | (0 & kImm16Mask); // NOLINT | 265 | (0 & kImm16Mask); // NOLINT |
265 | 266 |
266 const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift) | 267 const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift) |
267 | (0 & kImm16Mask); // NOLINT | 268 | (0 & kImm16Mask); // NOLINT |
268 | 269 |
269 const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift) | 270 const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift) |
270 | (0 & kImm16Mask); // NOLINT | 271 | (0 & kImm16Mask); // NOLINT |
271 | 272 |
272 const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift) | 273 const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift) |
273 | (kNegOffset & kImm16Mask); // NOLINT | 274 | (kNegOffset & kImm16Mask); // NOLINT |
274 | 275 |
275 const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift) | 276 const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift) |
276 | (kNegOffset & kImm16Mask); // NOLINT | 277 | (kNegOffset & kImm16Mask); // NOLINT |
277 // A mask for the Rt register for push, pop, lw, sw instructions. | 278 // A mask for the Rt register for push, pop, lw, sw instructions. |
278 const Instr kRtMask = kRtFieldMask; | 279 const Instr kRtMask = kRtFieldMask; |
279 const Instr kLwSwInstrTypeMask = 0xffe00000; | 280 const Instr kLwSwInstrTypeMask = 0xffe00000; |
280 const Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask; | 281 const Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask; |
281 const Instr kLwSwOffsetMask = kImm16Mask; | 282 const Instr kLwSwOffsetMask = kImm16Mask; |
282 | 283 |
283 | 284 |
284 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) | 285 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) |
285 : AssemblerBase(isolate, buffer, buffer_size), | 286 : AssemblerBase(isolate, buffer, buffer_size), |
286 recorded_ast_id_(TypeFeedbackId::None()), | 287 recorded_ast_id_(TypeFeedbackId::None()), |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 } | 610 } |
610 | 611 |
611 | 612 |
612 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { | 613 Instr Assembler::SetSwOffset(Instr instr, int16_t offset) { |
613 ASSERT(IsSw(instr)); | 614 ASSERT(IsSw(instr)); |
614 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); | 615 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); |
615 } | 616 } |
616 | 617 |
617 | 618 |
618 bool Assembler::IsAddImmediate(Instr instr) { | 619 bool Assembler::IsAddImmediate(Instr instr) { |
619 return ((instr & kOpcodeMask) == ADDIU); | 620 return ((instr & kOpcodeMask) == ADDIU || (instr & kOpcodeMask) == DADDIU); |
620 } | 621 } |
621 | 622 |
622 | 623 |
623 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { | 624 Instr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { |
624 ASSERT(IsAddImmediate(instr)); | 625 ASSERT(IsAddImmediate(instr)); |
625 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); | 626 return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); |
626 } | 627 } |
627 | 628 |
628 | 629 |
629 bool Assembler::IsAndImmediate(Instr instr) { | 630 bool Assembler::IsAndImmediate(Instr instr) { |
630 return GetOpcodeField(instr) == ANDI; | 631 return GetOpcodeField(instr) == ANDI; |
631 } | 632 } |
632 | 633 |
633 | 634 |
634 int Assembler::target_at(int32_t pos) { | 635 int64_t Assembler::target_at(int64_t pos) { |
635 Instr instr = instr_at(pos); | 636 Instr instr = instr_at(pos); |
636 if ((instr & ~kImm16Mask) == 0) { | 637 if ((instr & ~kImm16Mask) == 0) { |
637 // Emitted label constant, not part of a branch. | 638 // Emitted label constant, not part of a branch. |
638 if (instr == 0) { | 639 if (instr == 0) { |
639 return kEndOfChain; | 640 return kEndOfChain; |
640 } else { | 641 } else { |
641 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 642 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
642 return (imm18 + pos); | 643 return (imm18 + pos); |
643 } | 644 } |
644 } | 645 } |
645 // Check we have a branch or jump instruction. | 646 // Check we have a branch or jump instruction. |
646 ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr)); | 647 ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr)); |
647 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | 648 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming |
648 // the compiler uses arithmectic shifts for signed integers. | 649 // the compiler uses arithmetic shifts for signed integers. |
649 if (IsBranch(instr)) { | 650 if (IsBranch(instr)) { |
650 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 651 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
651 | |
652 if (imm18 == kEndOfChain) { | 652 if (imm18 == kEndOfChain) { |
653 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 653 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
654 return kEndOfChain; | 654 return kEndOfChain; |
655 } else { | 655 } else { |
656 return pos + kBranchPCOffset + imm18; | 656 return pos + kBranchPCOffset + imm18; |
657 } | 657 } |
658 } else if (IsLui(instr)) { | 658 } else if (IsLui(instr)) { |
659 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 659 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
660 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 660 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
| 661 Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize); |
661 ASSERT(IsOri(instr_ori)); | 662 ASSERT(IsOri(instr_ori)); |
662 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 663 ASSERT(IsOri(instr_ori2)); |
663 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 664 |
| 665 // TODO(plind) create named constants for shift values. |
| 666 int64_t imm = static_cast<int64_t>(instr_lui & kImm16Mask) << 48; |
| 667 imm |= static_cast<int64_t>(instr_ori & kImm16Mask) << 32; |
| 668 imm |= static_cast<int64_t>(instr_ori2 & kImm16Mask) << 16; |
| 669 // Sign extend address; |
| 670 imm >>= 16; |
664 | 671 |
665 if (imm == kEndOfJumpChain) { | 672 if (imm == kEndOfJumpChain) { |
666 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 673 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
667 return kEndOfChain; | 674 return kEndOfChain; |
668 } else { | 675 } else { |
669 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 676 uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos); |
670 int32_t delta = instr_address - imm; | 677 int64_t delta = instr_address - imm; |
671 ASSERT(pos > delta); | 678 ASSERT(pos > delta); |
672 return pos - delta; | 679 return pos - delta; |
673 } | 680 } |
674 } else { | 681 } else { |
675 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 682 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
676 if (imm28 == kEndOfJumpChain) { | 683 if (imm28 == kEndOfJumpChain) { |
677 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 684 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
678 return kEndOfChain; | 685 return kEndOfChain; |
679 } else { | 686 } else { |
680 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 687 uint64_t instr_address = reinterpret_cast<int64_t>(buffer_ + pos); |
681 instr_address &= kImm28Mask; | 688 instr_address &= kImm28Mask; |
682 int32_t delta = instr_address - imm28; | 689 int64_t delta = instr_address - imm28; |
683 ASSERT(pos > delta); | 690 ASSERT(pos > delta); |
684 return pos - delta; | 691 return pos - delta; |
685 } | 692 } |
686 } | 693 } |
687 } | 694 } |
688 | 695 |
689 | 696 |
690 void Assembler::target_at_put(int32_t pos, int32_t target_pos) { | 697 void Assembler::target_at_put(int64_t pos, int64_t target_pos) { |
691 Instr instr = instr_at(pos); | 698 Instr instr = instr_at(pos); |
692 if ((instr & ~kImm16Mask) == 0) { | 699 if ((instr & ~kImm16Mask) == 0) { |
693 ASSERT(target_pos == kEndOfChain || target_pos >= 0); | 700 ASSERT(target_pos == kEndOfChain || target_pos >= 0); |
694 // Emitted label constant, not part of a branch. | 701 // Emitted label constant, not part of a branch. |
695 // Make label relative to Code* of generated Code object. | 702 // Make label relative to Code* of generated Code object. |
696 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 703 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
697 return; | 704 return; |
698 } | 705 } |
699 | 706 |
700 ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr)); | 707 ASSERT(IsBranch(instr) || IsJ(instr) || IsLui(instr)); |
701 if (IsBranch(instr)) { | 708 if (IsBranch(instr)) { |
702 int32_t imm18 = target_pos - (pos + kBranchPCOffset); | 709 int32_t imm18 = target_pos - (pos + kBranchPCOffset); |
703 ASSERT((imm18 & 3) == 0); | 710 ASSERT((imm18 & 3) == 0); |
704 | 711 |
705 instr &= ~kImm16Mask; | 712 instr &= ~kImm16Mask; |
706 int32_t imm16 = imm18 >> 2; | 713 int32_t imm16 = imm18 >> 2; |
707 ASSERT(is_int16(imm16)); | 714 ASSERT(is_int16(imm16)); |
708 | 715 |
709 instr_at_put(pos, instr | (imm16 & kImm16Mask)); | 716 instr_at_put(pos, instr | (imm16 & kImm16Mask)); |
710 } else if (IsLui(instr)) { | 717 } else if (IsLui(instr)) { |
711 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 718 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
712 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 719 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
| 720 Instr instr_ori2 = instr_at(pos + 3 * Assembler::kInstrSize); |
713 ASSERT(IsOri(instr_ori)); | 721 ASSERT(IsOri(instr_ori)); |
714 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 722 ASSERT(IsOri(instr_ori2)); |
| 723 |
| 724 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
715 ASSERT((imm & 3) == 0); | 725 ASSERT((imm & 3) == 0); |
716 | 726 |
717 instr_lui &= ~kImm16Mask; | 727 instr_lui &= ~kImm16Mask; |
718 instr_ori &= ~kImm16Mask; | 728 instr_ori &= ~kImm16Mask; |
| 729 instr_ori2 &= ~kImm16Mask; |
719 | 730 |
720 instr_at_put(pos + 0 * Assembler::kInstrSize, | 731 instr_at_put(pos + 0 * Assembler::kInstrSize, |
721 instr_lui | ((imm & kHiMask) >> kLuiShift)); | 732 instr_lui | ((imm >> 32) & kImm16Mask)); |
722 instr_at_put(pos + 1 * Assembler::kInstrSize, | 733 instr_at_put(pos + 1 * Assembler::kInstrSize, |
723 instr_ori | (imm & kImm16Mask)); | 734 instr_ori | ((imm >> 16) & kImm16Mask)); |
| 735 instr_at_put(pos + 3 * Assembler::kInstrSize, |
| 736 instr_ori2 | (imm & kImm16Mask)); |
724 } else { | 737 } else { |
725 uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 738 uint64_t imm28 = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
726 imm28 &= kImm28Mask; | 739 imm28 &= kImm28Mask; |
727 ASSERT((imm28 & 3) == 0); | 740 ASSERT((imm28 & 3) == 0); |
728 | 741 |
729 instr &= ~kImm26Mask; | 742 instr &= ~kImm26Mask; |
730 uint32_t imm26 = imm28 >> 2; | 743 uint32_t imm26 = imm28 >> 2; |
731 ASSERT(is_uint26(imm26)); | 744 ASSERT(is_uint26(imm26)); |
732 | 745 |
733 instr_at_put(pos, instr | (imm26 & kImm26Mask)); | 746 instr_at_put(pos, instr | (imm26 & kImm26Mask)); |
734 } | 747 } |
735 } | 748 } |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 } | 976 } |
964 | 977 |
965 if (kInvalidSlotPos == trampoline_entry) { | 978 if (kInvalidSlotPos == trampoline_entry) { |
966 internal_trampoline_exception_ = true; | 979 internal_trampoline_exception_ = true; |
967 } | 980 } |
968 } | 981 } |
969 return trampoline_entry; | 982 return trampoline_entry; |
970 } | 983 } |
971 | 984 |
972 | 985 |
973 uint32_t Assembler::jump_address(Label* L) { | 986 uint64_t Assembler::jump_address(Label* L) { |
974 int32_t target_pos; | 987 int64_t target_pos; |
975 | 988 |
976 if (L->is_bound()) { | 989 if (L->is_bound()) { |
977 target_pos = L->pos(); | 990 target_pos = L->pos(); |
978 } else { | 991 } else { |
979 if (L->is_linked()) { | 992 if (L->is_linked()) { |
980 target_pos = L->pos(); // L's link. | 993 target_pos = L->pos(); // L's link. |
981 L->link_to(pc_offset()); | 994 L->link_to(pc_offset()); |
982 } else { | 995 } else { |
983 L->link_to(pc_offset()); | 996 L->link_to(pc_offset()); |
984 return kEndOfJumpChain; | 997 return kEndOfJumpChain; |
985 } | 998 } |
986 } | 999 } |
987 | 1000 |
988 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 1001 uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
989 ASSERT((imm & 3) == 0); | 1002 ASSERT((imm & 3) == 0); |
990 | 1003 |
991 return imm; | 1004 return imm; |
992 } | 1005 } |
993 | 1006 |
994 | 1007 |
995 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { | 1008 int32_t Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { |
996 int32_t target_pos; | 1009 int32_t target_pos; |
997 | 1010 |
998 if (L->is_bound()) { | 1011 if (L->is_bound()) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 } | 1122 } |
1110 | 1123 |
1111 | 1124 |
1112 void Assembler::bne(Register rs, Register rt, int16_t offset) { | 1125 void Assembler::bne(Register rs, Register rt, int16_t offset) { |
1113 BlockTrampolinePoolScope block_trampoline_pool(this); | 1126 BlockTrampolinePoolScope block_trampoline_pool(this); |
1114 GenInstrImmediate(BNE, rs, rt, offset); | 1127 GenInstrImmediate(BNE, rs, rt, offset); |
1115 BlockTrampolinePoolFor(1); // For associated delay slot. | 1128 BlockTrampolinePoolFor(1); // For associated delay slot. |
1116 } | 1129 } |
1117 | 1130 |
1118 | 1131 |
1119 void Assembler::j(int32_t target) { | 1132 void Assembler::j(int64_t target) { |
1120 #if DEBUG | 1133 #if DEBUG |
1121 // Get pc of delay slot. | 1134 // Get pc of delay slot. |
1122 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); | 1135 uint64_t ipc = reinterpret_cast<uint64_t>(pc_ + 1 * kInstrSize); |
1123 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> | 1136 bool in_range = (ipc ^ static_cast<uint64_t>(target) >> |
1124 (kImm26Bits + kImmFieldShift)) == 0; | 1137 (kImm26Bits + kImmFieldShift)) == 0; |
1125 ASSERT(in_range && ((target & 3) == 0)); | 1138 ASSERT(in_range && ((target & 3) == 0)); |
1126 #endif | 1139 #endif |
1127 GenInstrJump(J, target >> 2); | 1140 GenInstrJump(J, target >> 2); |
1128 } | 1141 } |
1129 | 1142 |
1130 | 1143 |
1131 void Assembler::jr(Register rs) { | 1144 void Assembler::jr(Register rs) { |
1132 BlockTrampolinePoolScope block_trampoline_pool(this); | 1145 BlockTrampolinePoolScope block_trampoline_pool(this); |
1133 if (rs.is(ra)) { | 1146 if (rs.is(ra)) { |
1134 positions_recorder()->WriteRecordedPositions(); | 1147 positions_recorder()->WriteRecordedPositions(); |
1135 } | 1148 } |
1136 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); | 1149 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); |
1137 BlockTrampolinePoolFor(1); // For associated delay slot. | 1150 BlockTrampolinePoolFor(1); // For associated delay slot. |
1138 } | 1151 } |
1139 | 1152 |
1140 | 1153 |
1141 void Assembler::jal(int32_t target) { | 1154 void Assembler::jal(int64_t target) { |
1142 #ifdef DEBUG | 1155 #ifdef DEBUG |
1143 // Get pc of delay slot. | 1156 // Get pc of delay slot. |
1144 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); | 1157 uint64_t ipc = reinterpret_cast<uint64_t>(pc_ + 1 * kInstrSize); |
1145 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> | 1158 bool in_range = (ipc ^ static_cast<uint64_t>(target) >> |
1146 (kImm26Bits + kImmFieldShift)) == 0; | 1159 (kImm26Bits + kImmFieldShift)) == 0; |
1147 ASSERT(in_range && ((target & 3) == 0)); | 1160 ASSERT(in_range && ((target & 3) == 0)); |
1148 #endif | 1161 #endif |
1149 positions_recorder()->WriteRecordedPositions(); | 1162 positions_recorder()->WriteRecordedPositions(); |
1150 GenInstrJump(JAL, target >> 2); | 1163 GenInstrJump(JAL, target >> 2); |
1151 } | 1164 } |
1152 | 1165 |
1153 | 1166 |
1154 void Assembler::jalr(Register rs, Register rd) { | 1167 void Assembler::jalr(Register rs, Register rd) { |
1155 BlockTrampolinePoolScope block_trampoline_pool(this); | 1168 BlockTrampolinePoolScope block_trampoline_pool(this); |
1156 positions_recorder()->WriteRecordedPositions(); | 1169 positions_recorder()->WriteRecordedPositions(); |
1157 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); | 1170 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); |
1158 BlockTrampolinePoolFor(1); // For associated delay slot. | 1171 BlockTrampolinePoolFor(1); // For associated delay slot. |
1159 } | 1172 } |
1160 | 1173 |
1161 | 1174 |
1162 void Assembler::j_or_jr(int32_t target, Register rs) { | 1175 void Assembler::j_or_jr(int64_t target, Register rs) { |
1163 // Get pc of delay slot. | 1176 // Get pc of delay slot. |
1164 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); | 1177 uint64_t ipc = reinterpret_cast<uint64_t>(pc_ + 1 * kInstrSize); |
1165 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> | 1178 bool in_range = (ipc ^ static_cast<uint64_t>(target) >> |
1166 (kImm26Bits + kImmFieldShift)) == 0; | 1179 (kImm26Bits + kImmFieldShift)) == 0; |
1167 if (in_range) { | 1180 if (in_range) { |
1168 j(target); | 1181 j(target); |
1169 } else { | 1182 } else { |
1170 jr(t9); | 1183 jr(t9); |
1171 } | 1184 } |
1172 } | 1185 } |
1173 | 1186 |
1174 | 1187 |
1175 void Assembler::jal_or_jalr(int32_t target, Register rs) { | 1188 void Assembler::jal_or_jalr(int64_t target, Register rs) { |
1176 // Get pc of delay slot. | 1189 // Get pc of delay slot. |
1177 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); | 1190 uint64_t ipc = reinterpret_cast<uint64_t>(pc_ + 1 * kInstrSize); |
1178 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> | 1191 bool in_range = (ipc ^ static_cast<uint64_t>(target) >> |
1179 (kImm26Bits+kImmFieldShift)) == 0; | 1192 (kImm26Bits+kImmFieldShift)) == 0; |
1180 if (in_range) { | 1193 if (in_range) { |
1181 jal(target); | 1194 jal(target); |
1182 } else { | 1195 } else { |
1183 jalr(t9); | 1196 jalr(t9); |
1184 } | 1197 } |
1185 } | 1198 } |
1186 | 1199 |
1187 | 1200 |
1188 // -------Data-processing-instructions--------- | 1201 // -------Data-processing-instructions--------- |
(...skipping 23 matching lines...) Expand all Loading... |
1212 void Assembler::mult(Register rs, Register rt) { | 1225 void Assembler::mult(Register rs, Register rt) { |
1213 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT); | 1226 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT); |
1214 } | 1227 } |
1215 | 1228 |
1216 | 1229 |
1217 void Assembler::multu(Register rs, Register rt) { | 1230 void Assembler::multu(Register rs, Register rt) { |
1218 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU); | 1231 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU); |
1219 } | 1232 } |
1220 | 1233 |
1221 | 1234 |
| 1235 void Assembler::daddiu(Register rd, Register rs, int32_t j) { |
| 1236 GenInstrImmediate(DADDIU, rs, rd, j); |
| 1237 } |
| 1238 |
| 1239 |
1222 void Assembler::div(Register rs, Register rt) { | 1240 void Assembler::div(Register rs, Register rt) { |
1223 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV); | 1241 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV); |
1224 } | 1242 } |
1225 | 1243 |
1226 | 1244 |
1227 void Assembler::divu(Register rs, Register rt) { | 1245 void Assembler::divu(Register rs, Register rt) { |
1228 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU); | 1246 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU); |
1229 } | 1247 } |
1230 | 1248 |
1231 | 1249 |
| 1250 void Assembler::daddu(Register rd, Register rs, Register rt) { |
| 1251 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DADDU); |
| 1252 } |
| 1253 |
| 1254 |
| 1255 void Assembler::dsubu(Register rd, Register rs, Register rt) { |
| 1256 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSUBU); |
| 1257 } |
| 1258 |
| 1259 |
| 1260 void Assembler::dmult(Register rs, Register rt) { |
| 1261 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULT); |
| 1262 } |
| 1263 |
| 1264 |
| 1265 void Assembler::dmultu(Register rs, Register rt) { |
| 1266 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULTU); |
| 1267 } |
| 1268 |
| 1269 |
| 1270 void Assembler::ddiv(Register rs, Register rt) { |
| 1271 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIV); |
| 1272 } |
| 1273 |
| 1274 |
| 1275 void Assembler::ddivu(Register rs, Register rt) { |
| 1276 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIVU); |
| 1277 } |
| 1278 |
| 1279 |
1232 // Logical. | 1280 // Logical. |
1233 | 1281 |
1234 void Assembler::and_(Register rd, Register rs, Register rt) { | 1282 void Assembler::and_(Register rd, Register rs, Register rt) { |
1235 GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND); | 1283 GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND); |
1236 } | 1284 } |
1237 | 1285 |
1238 | 1286 |
1239 void Assembler::andi(Register rt, Register rs, int32_t j) { | 1287 void Assembler::andi(Register rt, Register rs, int32_t j) { |
1240 ASSERT(is_uint16(j)); | 1288 ASSERT(is_uint16(j)); |
1241 GenInstrImmediate(ANDI, rs, rt, j); | 1289 GenInstrImmediate(ANDI, rs, rt, j); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 | 1352 |
1305 | 1353 |
1306 void Assembler::srav(Register rd, Register rt, Register rs) { | 1354 void Assembler::srav(Register rd, Register rt, Register rs) { |
1307 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); | 1355 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); |
1308 } | 1356 } |
1309 | 1357 |
1310 | 1358 |
1311 void Assembler::rotr(Register rd, Register rt, uint16_t sa) { | 1359 void Assembler::rotr(Register rd, Register rt, uint16_t sa) { |
1312 // Should be called via MacroAssembler::Ror. | 1360 // Should be called via MacroAssembler::Ror. |
1313 ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa)); | 1361 ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa)); |
1314 ASSERT(kArchVariant == kMips32r2); | 1362 ASSERT(kArchVariant == kMips64r2); |
1315 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) | 1363 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) |
1316 | (rd.code() << kRdShift) | (sa << kSaShift) | SRL; | 1364 | (rd.code() << kRdShift) | (sa << kSaShift) | SRL; |
1317 emit(instr); | 1365 emit(instr); |
1318 } | 1366 } |
1319 | 1367 |
1320 | 1368 |
1321 void Assembler::rotrv(Register rd, Register rt, Register rs) { | 1369 void Assembler::rotrv(Register rd, Register rt, Register rs) { |
1322 // Should be called via MacroAssembler::Ror. | 1370 // Should be called via MacroAssembler::Ror. |
1323 ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() ); | 1371 ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() ); |
1324 ASSERT(kArchVariant == kMips32r2); | 1372 ASSERT(kArchVariant == kMips64r2); |
1325 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 1373 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
1326 | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV; | 1374 | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV; |
1327 emit(instr); | 1375 emit(instr); |
1328 } | 1376 } |
1329 | 1377 |
1330 | 1378 |
| 1379 void Assembler::dsll(Register rd, Register rt, uint16_t sa) { |
| 1380 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, DSLL); |
| 1381 } |
| 1382 |
| 1383 |
| 1384 void Assembler::dsllv(Register rd, Register rt, Register rs) { |
| 1385 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSLLV); |
| 1386 } |
| 1387 |
| 1388 |
| 1389 void Assembler::dsrl(Register rd, Register rt, uint16_t sa) { |
| 1390 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, DSRL); |
| 1391 } |
| 1392 |
| 1393 |
| 1394 void Assembler::dsrlv(Register rd, Register rt, Register rs) { |
| 1395 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRLV); |
| 1396 } |
| 1397 |
| 1398 |
| 1399 void Assembler::drotr(Register rd, Register rt, uint16_t sa) { |
| 1400 ASSERT(rd.is_valid() && rt.is_valid() && is_uint5(sa)); |
| 1401 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) |
| 1402 | (rd.code() << kRdShift) | (sa << kSaShift) | DSRL; |
| 1403 emit(instr); |
| 1404 } |
| 1405 |
| 1406 |
| 1407 void Assembler::drotrv(Register rd, Register rt, Register rs) { |
| 1408 ASSERT(rd.is_valid() && rt.is_valid() && rs.is_valid() ); |
| 1409 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
| 1410 | (rd.code() << kRdShift) | (1 << kSaShift) | DSRLV; |
| 1411 emit(instr); |
| 1412 } |
| 1413 |
| 1414 |
| 1415 void Assembler::dsra(Register rd, Register rt, uint16_t sa) { |
| 1416 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, DSRA); |
| 1417 } |
| 1418 |
| 1419 |
| 1420 void Assembler::dsrav(Register rd, Register rt, Register rs) { |
| 1421 GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRAV); |
| 1422 } |
| 1423 |
| 1424 |
| 1425 void Assembler::dsll32(Register rd, Register rt, uint16_t sa) { |
| 1426 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, DSLL32); |
| 1427 } |
| 1428 |
| 1429 |
| 1430 void Assembler::dsrl32(Register rd, Register rt, uint16_t sa) { |
| 1431 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, DSRL32); |
| 1432 } |
| 1433 |
| 1434 |
| 1435 void Assembler::dsra32(Register rd, Register rt, uint16_t sa) { |
| 1436 GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa, DSRA32); |
| 1437 } |
| 1438 |
| 1439 |
1331 // ------------Memory-instructions------------- | 1440 // ------------Memory-instructions------------- |
1332 | 1441 |
1333 // Helper for base-reg + offset, when offset is larger than int16. | 1442 // Helper for base-reg + offset, when offset is larger than int16. |
1334 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) { | 1443 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) { |
1335 ASSERT(!src.rm().is(at)); | 1444 ASSERT(!src.rm().is(at)); |
1336 lui(at, (src.offset_ >> kLuiShift) & kImm16Mask); | 1445 ASSERT(is_int32(src.offset_)); |
| 1446 daddiu(at, zero_reg, (src.offset_ >> kLuiShift) & kImm16Mask); |
| 1447 dsll(at, at, kLuiShift); |
1337 ori(at, at, src.offset_ & kImm16Mask); // Load 32-bit offset. | 1448 ori(at, at, src.offset_ & kImm16Mask); // Load 32-bit offset. |
1338 addu(at, at, src.rm()); // Add base register. | 1449 daddu(at, at, src.rm()); // Add base register. |
1339 } | 1450 } |
1340 | 1451 |
1341 | 1452 |
1342 void Assembler::lb(Register rd, const MemOperand& rs) { | 1453 void Assembler::lb(Register rd, const MemOperand& rs) { |
1343 if (is_int16(rs.offset_)) { | 1454 if (is_int16(rs.offset_)) { |
1344 GenInstrImmediate(LB, rs.rm(), rd, rs.offset_); | 1455 GenInstrImmediate(LB, rs.rm(), rd, rs.offset_); |
1345 } else { // Offset > 16 bits, use multiple instructions to load. | 1456 } else { // Offset > 16 bits, use multiple instructions to load. |
1346 LoadRegPlusOffsetToAt(rs); | 1457 LoadRegPlusOffsetToAt(rs); |
1347 GenInstrImmediate(LB, at, rd, 0); // Equiv to lb(rd, MemOperand(at, 0)); | 1458 GenInstrImmediate(LB, at, rd, 0); // Equiv to lb(rd, MemOperand(at, 0)); |
1348 } | 1459 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 void Assembler::lw(Register rd, const MemOperand& rs) { | 1493 void Assembler::lw(Register rd, const MemOperand& rs) { |
1383 if (is_int16(rs.offset_)) { | 1494 if (is_int16(rs.offset_)) { |
1384 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); | 1495 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); |
1385 } else { // Offset > 16 bits, use multiple instructions to load. | 1496 } else { // Offset > 16 bits, use multiple instructions to load. |
1386 LoadRegPlusOffsetToAt(rs); | 1497 LoadRegPlusOffsetToAt(rs); |
1387 GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0)); | 1498 GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0)); |
1388 } | 1499 } |
1389 } | 1500 } |
1390 | 1501 |
1391 | 1502 |
| 1503 void Assembler::lwu(Register rd, const MemOperand& rs) { |
| 1504 if (is_int16(rs.offset_)) { |
| 1505 GenInstrImmediate(LWU, rs.rm(), rd, rs.offset_); |
| 1506 } else { // Offset > 16 bits, use multiple instructions to load. |
| 1507 LoadRegPlusOffsetToAt(rs); |
| 1508 GenInstrImmediate(LWU, at, rd, 0); // Equiv to lwu(rd, MemOperand(at, 0)); |
| 1509 } |
| 1510 } |
| 1511 |
| 1512 |
1392 void Assembler::lwl(Register rd, const MemOperand& rs) { | 1513 void Assembler::lwl(Register rd, const MemOperand& rs) { |
1393 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); | 1514 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); |
1394 } | 1515 } |
1395 | 1516 |
1396 | 1517 |
1397 void Assembler::lwr(Register rd, const MemOperand& rs) { | 1518 void Assembler::lwr(Register rd, const MemOperand& rs) { |
1398 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); | 1519 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); |
1399 } | 1520 } |
1400 | 1521 |
1401 | 1522 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); | 1559 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); |
1439 } | 1560 } |
1440 | 1561 |
1441 | 1562 |
1442 void Assembler::lui(Register rd, int32_t j) { | 1563 void Assembler::lui(Register rd, int32_t j) { |
1443 ASSERT(is_uint16(j)); | 1564 ASSERT(is_uint16(j)); |
1444 GenInstrImmediate(LUI, zero_reg, rd, j); | 1565 GenInstrImmediate(LUI, zero_reg, rd, j); |
1445 } | 1566 } |
1446 | 1567 |
1447 | 1568 |
| 1569 void Assembler::ldl(Register rd, const MemOperand& rs) { |
| 1570 GenInstrImmediate(LDL, rs.rm(), rd, rs.offset_); |
| 1571 } |
| 1572 |
| 1573 |
| 1574 void Assembler::ldr(Register rd, const MemOperand& rs) { |
| 1575 GenInstrImmediate(LDR, rs.rm(), rd, rs.offset_); |
| 1576 } |
| 1577 |
| 1578 |
| 1579 void Assembler::sdl(Register rd, const MemOperand& rs) { |
| 1580 GenInstrImmediate(SDL, rs.rm(), rd, rs.offset_); |
| 1581 } |
| 1582 |
| 1583 |
| 1584 void Assembler::sdr(Register rd, const MemOperand& rs) { |
| 1585 GenInstrImmediate(SDR, rs.rm(), rd, rs.offset_); |
| 1586 } |
| 1587 |
| 1588 |
| 1589 void Assembler::ld(Register rd, const MemOperand& rs) { |
| 1590 if (is_int16(rs.offset_)) { |
| 1591 GenInstrImmediate(LD, rs.rm(), rd, rs.offset_); |
| 1592 } else { // Offset > 16 bits, use multiple instructions to load. |
| 1593 LoadRegPlusOffsetToAt(rs); |
| 1594 GenInstrImmediate(LD, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0)); |
| 1595 } |
| 1596 } |
| 1597 |
| 1598 |
| 1599 void Assembler::sd(Register rd, const MemOperand& rs) { |
| 1600 if (is_int16(rs.offset_)) { |
| 1601 GenInstrImmediate(SD, rs.rm(), rd, rs.offset_); |
| 1602 } else { // Offset > 16 bits, use multiple instructions to store. |
| 1603 LoadRegPlusOffsetToAt(rs); |
| 1604 GenInstrImmediate(SD, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0)); |
| 1605 } |
| 1606 } |
| 1607 |
| 1608 |
1448 // -------------Misc-instructions-------------- | 1609 // -------------Misc-instructions-------------- |
1449 | 1610 |
1450 // Break / Trap instructions. | 1611 // Break / Trap instructions. |
1451 void Assembler::break_(uint32_t code, bool break_as_stop) { | 1612 void Assembler::break_(uint32_t code, bool break_as_stop) { |
1452 ASSERT((code & ~0xfffff) == 0); | 1613 ASSERT((code & ~0xfffff) == 0); |
1453 // We need to invalidate breaks that could be stops as well because the | 1614 // We need to invalidate breaks that could be stops as well because the |
1454 // simulator expects a char pointer after the stop instruction. | 1615 // simulator expects a char pointer after the stop instruction. |
1455 // See constants-mips.h for explanation. | 1616 // See constants-mips.h for explanation. |
1456 ASSERT((break_as_stop && | 1617 ASSERT((break_as_stop && |
1457 code <= kMaxStopCode && | 1618 code <= kMaxStopCode && |
1458 code > kMaxWatchpointCode) || | 1619 code > kMaxWatchpointCode) || |
1459 (!break_as_stop && | 1620 (!break_as_stop && |
1460 (code > kMaxStopCode || | 1621 (code > kMaxStopCode || |
1461 code <= kMaxWatchpointCode))); | 1622 code <= kMaxWatchpointCode))); |
1462 Instr break_instr = SPECIAL | BREAK | (code << 6); | 1623 Instr break_instr = SPECIAL | BREAK | (code << 6); |
1463 emit(break_instr); | 1624 emit(break_instr); |
1464 } | 1625 } |
1465 | 1626 |
1466 | 1627 |
1467 void Assembler::stop(const char* msg, uint32_t code) { | 1628 void Assembler::stop(const char* msg, uint32_t code) { |
1468 ASSERT(code > kMaxWatchpointCode); | 1629 ASSERT(code > kMaxWatchpointCode); |
1469 ASSERT(code <= kMaxStopCode); | 1630 ASSERT(code <= kMaxStopCode); |
1470 #if V8_HOST_ARCH_MIPS | 1631 #if defined(V8_HOST_ARCH_MIPS) || defined(V8_HOST_ARCH_MIPS64) |
1471 break_(0x54321); | 1632 break_(0x54321); |
1472 #else // V8_HOST_ARCH_MIPS | 1633 #else // V8_HOST_ARCH_MIPS |
1473 BlockTrampolinePoolFor(2); | 1634 BlockTrampolinePoolFor(3); |
1474 // The Simulator will handle the stop instruction and get the message address. | 1635 // The Simulator will handle the stop instruction and get the message address. |
1475 // On MIPS stop() is just a special kind of break_(). | 1636 // On MIPS stop() is just a special kind of break_(). |
1476 break_(code, true); | 1637 break_(code, true); |
1477 emit(reinterpret_cast<Instr>(msg)); | 1638 emit(reinterpret_cast<uint64_t>(msg)); |
1478 #endif | 1639 #endif |
1479 } | 1640 } |
1480 | 1641 |
1481 | 1642 |
1482 void Assembler::tge(Register rs, Register rt, uint16_t code) { | 1643 void Assembler::tge(Register rs, Register rt, uint16_t code) { |
1483 ASSERT(is_uint10(code)); | 1644 ASSERT(is_uint10(code)); |
1484 Instr instr = SPECIAL | TGE | rs.code() << kRsShift | 1645 Instr instr = SPECIAL | TGE | rs.code() << kRsShift |
1485 | rt.code() << kRtShift | code << 6; | 1646 | rt.code() << kRtShift | code << 6; |
1486 emit(instr); | 1647 emit(instr); |
1487 } | 1648 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 // Bit twiddling. | 1750 // Bit twiddling. |
1590 void Assembler::clz(Register rd, Register rs) { | 1751 void Assembler::clz(Register rd, Register rs) { |
1591 // Clz instr requires same GPR number in 'rd' and 'rt' fields. | 1752 // Clz instr requires same GPR number in 'rd' and 'rt' fields. |
1592 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); | 1753 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); |
1593 } | 1754 } |
1594 | 1755 |
1595 | 1756 |
1596 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) { | 1757 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) { |
1597 // Should be called via MacroAssembler::Ins. | 1758 // Should be called via MacroAssembler::Ins. |
1598 // Ins instr has 'rt' field as dest, and two uint5: msb, lsb. | 1759 // Ins instr has 'rt' field as dest, and two uint5: msb, lsb. |
1599 ASSERT(kArchVariant == kMips32r2); | 1760 ASSERT(kArchVariant == kMips64r2); |
1600 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS); | 1761 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS); |
1601 } | 1762 } |
1602 | 1763 |
1603 | 1764 |
1604 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { | 1765 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { |
1605 // Should be called via MacroAssembler::Ext. | 1766 // Should be called via MacroAssembler::Ext. |
1606 // Ext instr has 'rt' field as dest, and two uint5: msb, lsb. | 1767 // Ext instr has 'rt' field as dest, and two uint5: msb, lsb. |
1607 ASSERT(kArchVariant == kMips32r2); | 1768 ASSERT(kArchVariant == kMips64r2); |
1608 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT); | 1769 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT); |
1609 } | 1770 } |
1610 | 1771 |
1611 | 1772 |
1612 void Assembler::pref(int32_t hint, const MemOperand& rs) { | 1773 void Assembler::pref(int32_t hint, const MemOperand& rs) { |
1613 ASSERT(kArchVariant != kLoongson); | 1774 ASSERT(kArchVariant != kLoongson); |
1614 ASSERT(is_uint5(hint) && is_uint16(rs.offset_)); | 1775 ASSERT(is_uint5(hint) && is_uint16(rs.offset_)); |
1615 Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift) | 1776 Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift) |
1616 | (rs.offset_); | 1777 | (rs.offset_); |
1617 emit(instr); | 1778 emit(instr); |
1618 } | 1779 } |
1619 | 1780 |
1620 | 1781 |
1621 // --------Coprocessor-instructions---------------- | 1782 // --------Coprocessor-instructions---------------- |
1622 | 1783 |
1623 // Load, store, move. | 1784 // Load, store, move. |
1624 void Assembler::lwc1(FPURegister fd, const MemOperand& src) { | 1785 void Assembler::lwc1(FPURegister fd, const MemOperand& src) { |
1625 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); | 1786 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); |
1626 } | 1787 } |
1627 | 1788 |
1628 | 1789 |
1629 void Assembler::ldc1(FPURegister fd, const MemOperand& src) { | 1790 void Assembler::ldc1(FPURegister fd, const MemOperand& src) { |
1630 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit | 1791 GenInstrImmediate(LDC1, src.rm(), fd, src.offset_); |
1631 // load to two 32-bit loads. | |
1632 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ + | |
1633 Register::kMantissaOffset); | |
1634 FPURegister nextfpreg; | |
1635 nextfpreg.setcode(fd.code() + 1); | |
1636 GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + | |
1637 Register::kExponentOffset); | |
1638 } | 1792 } |
1639 | 1793 |
1640 | 1794 |
1641 void Assembler::swc1(FPURegister fd, const MemOperand& src) { | 1795 void Assembler::swc1(FPURegister fd, const MemOperand& src) { |
1642 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_); | 1796 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_); |
1643 } | 1797 } |
1644 | 1798 |
1645 | 1799 |
1646 void Assembler::sdc1(FPURegister fd, const MemOperand& src) { | 1800 void Assembler::sdc1(FPURegister fd, const MemOperand& src) { |
1647 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit | 1801 GenInstrImmediate(SDC1, src.rm(), fd, src.offset_); |
1648 // store to two 32-bit stores. | |
1649 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ + | |
1650 Register::kMantissaOffset); | |
1651 FPURegister nextfpreg; | |
1652 nextfpreg.setcode(fd.code() + 1); | |
1653 GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + | |
1654 Register::kExponentOffset); | |
1655 } | 1802 } |
1656 | 1803 |
1657 | 1804 |
1658 void Assembler::mtc1(Register rt, FPURegister fs) { | 1805 void Assembler::mtc1(Register rt, FPURegister fs) { |
1659 GenInstrRegister(COP1, MTC1, rt, fs, f0); | 1806 GenInstrRegister(COP1, MTC1, rt, fs, f0); |
1660 } | 1807 } |
1661 | 1808 |
1662 | 1809 |
| 1810 void Assembler::mthc1(Register rt, FPURegister fs) { |
| 1811 GenInstrRegister(COP1, MTHC1, rt, fs, f0); |
| 1812 } |
| 1813 |
| 1814 |
| 1815 void Assembler::dmtc1(Register rt, FPURegister fs) { |
| 1816 GenInstrRegister(COP1, DMTC1, rt, fs, f0); |
| 1817 } |
| 1818 |
| 1819 |
1663 void Assembler::mfc1(Register rt, FPURegister fs) { | 1820 void Assembler::mfc1(Register rt, FPURegister fs) { |
1664 GenInstrRegister(COP1, MFC1, rt, fs, f0); | 1821 GenInstrRegister(COP1, MFC1, rt, fs, f0); |
1665 } | 1822 } |
1666 | 1823 |
1667 | 1824 |
| 1825 void Assembler::mfhc1(Register rt, FPURegister fs) { |
| 1826 GenInstrRegister(COP1, MFHC1, rt, fs, f0); |
| 1827 } |
| 1828 |
| 1829 |
| 1830 void Assembler::dmfc1(Register rt, FPURegister fs) { |
| 1831 GenInstrRegister(COP1, DMFC1, rt, fs, f0); |
| 1832 } |
| 1833 |
| 1834 |
1668 void Assembler::ctc1(Register rt, FPUControlRegister fs) { | 1835 void Assembler::ctc1(Register rt, FPUControlRegister fs) { |
1669 GenInstrRegister(COP1, CTC1, rt, fs); | 1836 GenInstrRegister(COP1, CTC1, rt, fs); |
1670 } | 1837 } |
1671 | 1838 |
1672 | 1839 |
1673 void Assembler::cfc1(Register rt, FPUControlRegister fs) { | 1840 void Assembler::cfc1(Register rt, FPUControlRegister fs) { |
1674 GenInstrRegister(COP1, CFC1, rt, fs); | 1841 GenInstrRegister(COP1, CFC1, rt, fs); |
1675 } | 1842 } |
1676 | 1843 |
1677 | 1844 |
(...skipping 18 matching lines...) Expand all Loading... |
1696 } | 1863 } |
1697 | 1864 |
1698 | 1865 |
1699 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) { | 1866 void Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) { |
1700 GenInstrRegister(COP1, D, ft, fs, fd, MUL_D); | 1867 GenInstrRegister(COP1, D, ft, fs, fd, MUL_D); |
1701 } | 1868 } |
1702 | 1869 |
1703 | 1870 |
1704 void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs, | 1871 void Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs, |
1705 FPURegister ft) { | 1872 FPURegister ft) { |
| 1873 ASSERT(kArchVariant != kLoongson); |
1706 GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D); | 1874 GenInstrRegister(COP1X, fr, ft, fs, fd, MADD_D); |
1707 } | 1875 } |
1708 | 1876 |
1709 | 1877 |
1710 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) { | 1878 void Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) { |
1711 GenInstrRegister(COP1, D, ft, fs, fd, DIV_D); | 1879 GenInstrRegister(COP1, D, ft, fs, fd, DIV_D); |
1712 } | 1880 } |
1713 | 1881 |
1714 | 1882 |
1715 void Assembler::abs_d(FPURegister fd, FPURegister fs) { | 1883 void Assembler::abs_d(FPURegister fd, FPURegister fs) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S); | 1946 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S); |
1779 } | 1947 } |
1780 | 1948 |
1781 | 1949 |
1782 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) { | 1950 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) { |
1783 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D); | 1951 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D); |
1784 } | 1952 } |
1785 | 1953 |
1786 | 1954 |
1787 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { | 1955 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { |
1788 ASSERT(kArchVariant == kMips32r2); | 1956 ASSERT(kArchVariant == kMips64r2); |
1789 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); | 1957 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); |
1790 } | 1958 } |
1791 | 1959 |
1792 | 1960 |
1793 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { | 1961 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { |
1794 ASSERT(kArchVariant == kMips32r2); | 1962 ASSERT(kArchVariant == kMips64r2); |
1795 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); | 1963 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); |
1796 } | 1964 } |
1797 | 1965 |
1798 | 1966 |
1799 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) { | 1967 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) { |
1800 ASSERT(kArchVariant == kMips32r2); | 1968 ASSERT(kArchVariant == kMips64r2); |
1801 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S); | 1969 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S); |
1802 } | 1970 } |
1803 | 1971 |
1804 | 1972 |
1805 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) { | 1973 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) { |
1806 ASSERT(kArchVariant == kMips32r2); | 1974 ASSERT(kArchVariant == kMips64r2); |
1807 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D); | 1975 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D); |
1808 } | 1976 } |
1809 | 1977 |
1810 | 1978 |
1811 void Assembler::round_l_s(FPURegister fd, FPURegister fs) { | 1979 void Assembler::round_l_s(FPURegister fd, FPURegister fs) { |
1812 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S); | 1980 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S); |
1813 } | 1981 } |
1814 | 1982 |
1815 | 1983 |
1816 void Assembler::round_l_d(FPURegister fd, FPURegister fs) { | 1984 void Assembler::round_l_d(FPURegister fd, FPURegister fs) { |
(...skipping 20 matching lines...) Expand all Loading... |
1837 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D); | 2005 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D); |
1838 } | 2006 } |
1839 | 2007 |
1840 | 2008 |
1841 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { | 2009 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { |
1842 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); | 2010 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); |
1843 } | 2011 } |
1844 | 2012 |
1845 | 2013 |
1846 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { | 2014 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { |
1847 ASSERT(kArchVariant == kMips32r2); | 2015 ASSERT(kArchVariant == kMips64r2); |
1848 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); | 2016 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); |
1849 } | 2017 } |
1850 | 2018 |
1851 | 2019 |
1852 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { | 2020 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { |
1853 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); | 2021 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); |
1854 } | 2022 } |
1855 | 2023 |
1856 | 2024 |
1857 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { | 2025 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { |
1858 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); | 2026 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); |
1859 } | 2027 } |
1860 | 2028 |
1861 | 2029 |
1862 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { | 2030 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { |
1863 ASSERT(kArchVariant == kMips32r2); | 2031 ASSERT(kArchVariant == kMips64r2); |
1864 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); | 2032 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); |
1865 } | 2033 } |
1866 | 2034 |
1867 | 2035 |
1868 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { | 2036 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { |
1869 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); | 2037 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); |
1870 } | 2038 } |
1871 | 2039 |
1872 | 2040 |
1873 // Conditions. | 2041 // Conditions. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1926 } | 2094 } |
1927 } | 2095 } |
1928 | 2096 |
1929 | 2097 |
1930 int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { | 2098 int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { |
1931 Instr instr = instr_at(pc); | 2099 Instr instr = instr_at(pc); |
1932 ASSERT(IsJ(instr) || IsLui(instr)); | 2100 ASSERT(IsJ(instr) || IsLui(instr)); |
1933 if (IsLui(instr)) { | 2101 if (IsLui(instr)) { |
1934 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); | 2102 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); |
1935 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); | 2103 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); |
| 2104 Instr instr_ori2 = instr_at(pc + 3 * Assembler::kInstrSize); |
1936 ASSERT(IsOri(instr_ori)); | 2105 ASSERT(IsOri(instr_ori)); |
1937 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 2106 ASSERT(IsOri(instr_ori2)); |
1938 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 2107 // TODO(plind): symbolic names for the shifts. |
| 2108 int64_t imm = (instr_lui & static_cast<int64_t>(kImm16Mask)) << 48; |
| 2109 imm |= (instr_ori & static_cast<int64_t>(kImm16Mask)) << 32; |
| 2110 imm |= (instr_ori2 & static_cast<int64_t>(kImm16Mask)) << 16; |
| 2111 // Sign extend address. |
| 2112 imm >>= 16; |
| 2113 |
1939 if (imm == kEndOfJumpChain) { | 2114 if (imm == kEndOfJumpChain) { |
1940 return 0; // Number of instructions patched. | 2115 return 0; // Number of instructions patched. |
1941 } | 2116 } |
1942 imm += pc_delta; | 2117 imm += pc_delta; |
1943 ASSERT((imm & 3) == 0); | 2118 ASSERT((imm & 3) == 0); |
1944 | 2119 |
1945 instr_lui &= ~kImm16Mask; | 2120 instr_lui &= ~kImm16Mask; |
1946 instr_ori &= ~kImm16Mask; | 2121 instr_ori &= ~kImm16Mask; |
| 2122 instr_ori2 &= ~kImm16Mask; |
1947 | 2123 |
1948 instr_at_put(pc + 0 * Assembler::kInstrSize, | 2124 instr_at_put(pc + 0 * Assembler::kInstrSize, |
1949 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); | 2125 instr_lui | ((imm >> 32) & kImm16Mask)); |
1950 instr_at_put(pc + 1 * Assembler::kInstrSize, | 2126 instr_at_put(pc + 1 * Assembler::kInstrSize, |
1951 instr_ori | (imm & kImm16Mask)); | 2127 instr_ori | (imm >> 16 & kImm16Mask)); |
1952 return 2; // Number of instructions patched. | 2128 instr_at_put(pc + 3 * Assembler::kInstrSize, |
| 2129 instr_ori2 | (imm & kImm16Mask)); |
| 2130 return 4; // Number of instructions patched. |
1953 } else { | 2131 } else { |
1954 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 2132 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
1955 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { | 2133 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { |
1956 return 0; // Number of instructions patched. | 2134 return 0; // Number of instructions patched. |
1957 } | 2135 } |
| 2136 |
1958 imm28 += pc_delta; | 2137 imm28 += pc_delta; |
1959 imm28 &= kImm28Mask; | 2138 imm28 &= kImm28Mask; |
1960 ASSERT((imm28 & 3) == 0); | 2139 ASSERT((imm28 & 3) == 0); |
1961 | 2140 |
1962 instr &= ~kImm26Mask; | 2141 instr &= ~kImm26Mask; |
1963 uint32_t imm26 = imm28 >> 2; | 2142 uint32_t imm26 = imm28 >> 2; |
1964 ASSERT(is_uint26(imm26)); | 2143 ASSERT(is_uint26(imm26)); |
1965 | 2144 |
1966 instr_at_put(pc, instr | (imm26 & kImm26Mask)); | 2145 instr_at_put(pc, instr | (imm26 & kImm26Mask)); |
1967 return 1; // Number of instructions patched. | 2146 return 1; // Number of instructions patched. |
(...skipping 15 matching lines...) Expand all Loading... |
1983 } | 2162 } |
1984 CHECK_GT(desc.buffer_size, 0); // No overflow. | 2163 CHECK_GT(desc.buffer_size, 0); // No overflow. |
1985 | 2164 |
1986 // Set up new buffer. | 2165 // Set up new buffer. |
1987 desc.buffer = NewArray<byte>(desc.buffer_size); | 2166 desc.buffer = NewArray<byte>(desc.buffer_size); |
1988 | 2167 |
1989 desc.instr_size = pc_offset(); | 2168 desc.instr_size = pc_offset(); |
1990 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 2169 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
1991 | 2170 |
1992 // Copy the data. | 2171 // Copy the data. |
1993 int pc_delta = desc.buffer - buffer_; | 2172 intptr_t pc_delta = desc.buffer - buffer_; |
1994 int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); | 2173 intptr_t rc_delta = (desc.buffer + desc.buffer_size) - |
| 2174 (buffer_ + buffer_size_); |
1995 MemMove(desc.buffer, buffer_, desc.instr_size); | 2175 MemMove(desc.buffer, buffer_, desc.instr_size); |
1996 MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(), | 2176 MemMove(reloc_info_writer.pos() + rc_delta, |
1997 desc.reloc_size); | 2177 reloc_info_writer.pos(), desc.reloc_size); |
1998 | 2178 |
1999 // Switch buffers. | 2179 // Switch buffers. |
2000 DeleteArray(buffer_); | 2180 DeleteArray(buffer_); |
2001 buffer_ = desc.buffer; | 2181 buffer_ = desc.buffer; |
2002 buffer_size_ = desc.buffer_size; | 2182 buffer_size_ = desc.buffer_size; |
2003 pc_ += pc_delta; | 2183 pc_ += pc_delta; |
2004 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 2184 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
2005 reloc_info_writer.last_pc() + pc_delta); | 2185 reloc_info_writer.last_pc() + pc_delta); |
2006 | 2186 |
2007 // Relocate runtime entries. | 2187 // Relocate runtime entries. |
(...skipping 18 matching lines...) Expand all Loading... |
2026 | 2206 |
2027 void Assembler::dd(uint32_t data) { | 2207 void Assembler::dd(uint32_t data) { |
2028 CheckBuffer(); | 2208 CheckBuffer(); |
2029 *reinterpret_cast<uint32_t*>(pc_) = data; | 2209 *reinterpret_cast<uint32_t*>(pc_) = data; |
2030 pc_ += sizeof(uint32_t); | 2210 pc_ += sizeof(uint32_t); |
2031 } | 2211 } |
2032 | 2212 |
2033 | 2213 |
2034 void Assembler::emit_code_stub_address(Code* stub) { | 2214 void Assembler::emit_code_stub_address(Code* stub) { |
2035 CheckBuffer(); | 2215 CheckBuffer(); |
2036 *reinterpret_cast<uint32_t*>(pc_) = | 2216 *reinterpret_cast<uint64_t*>(pc_) = |
2037 reinterpret_cast<uint32_t>(stub->instruction_start()); | 2217 reinterpret_cast<uint64_t>(stub->instruction_start()); |
2038 pc_ += sizeof(uint32_t); | 2218 pc_ += sizeof(uint64_t); |
2039 } | 2219 } |
2040 | 2220 |
2041 | 2221 |
2042 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { | 2222 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
2043 // We do not try to reuse pool constants. | 2223 // We do not try to reuse pool constants. |
2044 RelocInfo rinfo(pc_, rmode, data, NULL); | 2224 RelocInfo rinfo(pc_, rmode, data, NULL); |
2045 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) { | 2225 if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::DEBUG_BREAK_SLOT) { |
2046 // Adjust code for new modes. | 2226 // Adjust code for new modes. |
2047 ASSERT(RelocInfo::IsDebugBreakSlot(rmode) | 2227 ASSERT(RelocInfo::IsDebugBreakSlot(rmode) |
2048 || RelocInfo::IsJSReturn(rmode) | 2228 || RelocInfo::IsJSReturn(rmode) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2098 ASSERT(unbound_labels_count_ >= 0); | 2278 ASSERT(unbound_labels_count_ >= 0); |
2099 if (unbound_labels_count_ > 0) { | 2279 if (unbound_labels_count_ > 0) { |
2100 // First we emit jump (2 instructions), then we emit trampoline pool. | 2280 // First we emit jump (2 instructions), then we emit trampoline pool. |
2101 { BlockTrampolinePoolScope block_trampoline_pool(this); | 2281 { BlockTrampolinePoolScope block_trampoline_pool(this); |
2102 Label after_pool; | 2282 Label after_pool; |
2103 b(&after_pool); | 2283 b(&after_pool); |
2104 nop(); | 2284 nop(); |
2105 | 2285 |
2106 int pool_start = pc_offset(); | 2286 int pool_start = pc_offset(); |
2107 for (int i = 0; i < unbound_labels_count_; i++) { | 2287 for (int i = 0; i < unbound_labels_count_; i++) { |
2108 uint32_t imm32; | 2288 uint64_t imm64; |
2109 imm32 = jump_address(&after_pool); | 2289 imm64 = jump_address(&after_pool); |
2110 { BlockGrowBufferScope block_buf_growth(this); | 2290 { BlockGrowBufferScope block_buf_growth(this); |
2111 // Buffer growth (and relocation) must be blocked for internal | 2291 // Buffer growth (and relocation) must be blocked for internal |
2112 // references until associated instructions are emitted and available | 2292 // references until associated instructions are emitted and available |
2113 // to be patched. | 2293 // to be patched. |
2114 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); | 2294 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
2115 lui(at, (imm32 & kHiMask) >> kLuiShift); | 2295 // TODO(plind): Verify this, presume I cannot use macro-assembler |
2116 ori(at, at, (imm32 & kImm16Mask)); | 2296 // here. |
| 2297 lui(at, (imm64 >> 32) & kImm16Mask); |
| 2298 ori(at, at, (imm64 >> 16) & kImm16Mask); |
| 2299 dsll(at, at, 16); |
| 2300 ori(at, at, imm64 & kImm16Mask); |
2117 } | 2301 } |
2118 jr(at); | 2302 jr(at); |
2119 nop(); | 2303 nop(); |
2120 } | 2304 } |
2121 bind(&after_pool); | 2305 bind(&after_pool); |
2122 trampoline_ = Trampoline(pool_start, unbound_labels_count_); | 2306 trampoline_ = Trampoline(pool_start, unbound_labels_count_); |
2123 | 2307 |
2124 trampoline_emitted_ = true; | 2308 trampoline_emitted_ = true; |
2125 // As we are only going to emit trampoline once, we need to prevent any | 2309 // As we are only going to emit trampoline once, we need to prevent any |
2126 // further emission. | 2310 // further emission. |
2127 next_buffer_check_ = kMaxInt; | 2311 next_buffer_check_ = kMaxInt; |
2128 } | 2312 } |
2129 } else { | 2313 } else { |
2130 // Number of branches to unbound label at this point is zero, so we can | 2314 // Number of branches to unbound label at this point is zero, so we can |
2131 // move next buffer check to maximum. | 2315 // move next buffer check to maximum. |
2132 next_buffer_check_ = pc_offset() + | 2316 next_buffer_check_ = pc_offset() + |
2133 kMaxBranchOffset - kTrampolineSlotsSize * 16; | 2317 kMaxBranchOffset - kTrampolineSlotsSize * 16; |
2134 } | 2318 } |
2135 return; | 2319 return; |
2136 } | 2320 } |
2137 | 2321 |
2138 | 2322 |
2139 Address Assembler::target_address_at(Address pc) { | 2323 Address Assembler::target_address_at(Address pc) { |
2140 Instr instr1 = instr_at(pc); | 2324 Instr instr0 = instr_at(pc); |
2141 Instr instr2 = instr_at(pc + kInstrSize); | 2325 Instr instr1 = instr_at(pc + 1 * kInstrSize); |
2142 // Interpret 2 instructions generated by li: lui/ori | 2326 Instr instr3 = instr_at(pc + 3 * kInstrSize); |
2143 if ((GetOpcodeField(instr1) == LUI) && (GetOpcodeField(instr2) == ORI)) { | 2327 |
2144 // Assemble the 32 bit value. | 2328 // Interpret 4 instructions for address generated by li: See listing in |
2145 return reinterpret_cast<Address>( | 2329 // Assembler::set_target_address_at() just below. |
2146 (GetImmediate16(instr1) << 16) | GetImmediate16(instr2)); | 2330 if ((GetOpcodeField(instr0) == LUI) && (GetOpcodeField(instr1) == ORI) && |
| 2331 (GetOpcodeField(instr3) == ORI)) { |
| 2332 // Assemble the 48 bit value. |
| 2333 int64_t addr = static_cast<int64_t>( |
| 2334 ((uint64_t)(GetImmediate16(instr0)) << 32) | |
| 2335 ((uint64_t)(GetImmediate16(instr1)) << 16) | |
| 2336 ((uint64_t)(GetImmediate16(instr3)))); |
| 2337 |
| 2338 // Sign extend to get canonical address. |
| 2339 addr = (addr << 16) >> 16; |
| 2340 return reinterpret_cast<Address>(addr); |
2147 } | 2341 } |
2148 | |
2149 // We should never get here, force a bad address if we do. | 2342 // We should never get here, force a bad address if we do. |
2150 UNREACHABLE(); | 2343 UNREACHABLE(); |
2151 return (Address)0x0; | 2344 return (Address)0x0; |
2152 } | 2345 } |
2153 | 2346 |
2154 | 2347 |
2155 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 | 2348 // MIPS and ia32 use opposite encoding for qNaN and sNaN, such that ia32 |
2156 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap | 2349 // qNaN is a MIPS sNaN, and ia32 sNaN is MIPS qNaN. If running from a heap |
2157 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted. | 2350 // snapshot generated on ia32, the resulting MIPS sNaN must be quieted. |
2158 // OS::nan_value() returns a qNaN. | 2351 // OS::nan_value() returns a qNaN. |
2159 void Assembler::QuietNaN(HeapObject* object) { | 2352 void Assembler::QuietNaN(HeapObject* object) { |
2160 HeapNumber::cast(object)->set_value(base::OS::nan_value()); | 2353 HeapNumber::cast(object)->set_value(base::OS::nan_value()); |
2161 } | 2354 } |
2162 | 2355 |
2163 | 2356 |
2164 // On Mips, a target address is stored in a lui/ori instruction pair, each | 2357 // On Mips64, a target address is stored in a 4-instruction sequence: |
2165 // of which load 16 bits of the 32-bit address to a register. | 2358 // 0: lui(rd, (j.imm64_ >> 32) & kImm16Mask); |
2166 // Patching the address must replace both instr, and flush the i-cache. | 2359 // 1: ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask); |
| 2360 // 2: dsll(rd, rd, 16); |
| 2361 // 3: ori(rd, rd, j.imm32_ & kImm16Mask); |
| 2362 // |
| 2363 // Patching the address must replace all the lui & ori instructions, |
| 2364 // and flush the i-cache. |
2167 // | 2365 // |
2168 // There is an optimization below, which emits a nop when the address | 2366 // There is an optimization below, which emits a nop when the address |
2169 // fits in just 16 bits. This is unlikely to help, and should be benchmarked, | 2367 // fits in just 16 bits. This is unlikely to help, and should be benchmarked, |
2170 // and possibly removed. | 2368 // and possibly removed. |
2171 void Assembler::set_target_address_at(Address pc, | 2369 void Assembler::set_target_address_at(Address pc, |
2172 Address target, | 2370 Address target, |
2173 ICacheFlushMode icache_flush_mode) { | 2371 ICacheFlushMode icache_flush_mode) { |
2174 Instr instr2 = instr_at(pc + kInstrSize); | 2372 // There is an optimization where only 4 instructions are used to load address |
2175 uint32_t rt_code = GetRtField(instr2); | 2373 // in code on MIP64 because only 48-bits of address is effectively used. |
| 2374 // It relies on fact the upper [63:48] bits are not used for virtual address |
| 2375 // translation and they have to be set according to value of bit 47 in order |
| 2376 // get canonical address. |
| 2377 Instr instr1 = instr_at(pc + kInstrSize); |
| 2378 uint32_t rt_code = GetRt(instr1); |
2176 uint32_t* p = reinterpret_cast<uint32_t*>(pc); | 2379 uint32_t* p = reinterpret_cast<uint32_t*>(pc); |
2177 uint32_t itarget = reinterpret_cast<uint32_t>(target); | 2380 uint64_t itarget = reinterpret_cast<uint64_t>(target); |
2178 | 2381 |
2179 #ifdef DEBUG | 2382 #ifdef DEBUG |
2180 // Check we have the result from a li macro-instruction, using instr pair. | 2383 // Check we have the result from a li macro-instruction. |
2181 Instr instr1 = instr_at(pc); | 2384 Instr instr0 = instr_at(pc); |
2182 CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI)); | 2385 Instr instr3 = instr_at(pc + kInstrSize * 3); |
| 2386 CHECK((GetOpcodeField(instr0) == LUI && GetOpcodeField(instr1) == ORI && |
| 2387 GetOpcodeField(instr3) == ORI)); |
2183 #endif | 2388 #endif |
2184 | 2389 |
2185 // Must use 2 instructions to insure patchable code => just use lui and ori. | 2390 // Must use 4 instructions to insure patchable code. |
2186 // lui rt, upper-16. | 2391 // lui rt, upper-16. |
| 2392 // ori rt, rt, lower-16. |
| 2393 // dsll rt, rt, 16. |
2187 // ori rt rt, lower-16. | 2394 // ori rt rt, lower-16. |
2188 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); | 2395 *p = LUI | (rt_code << kRtShift) | ((itarget >> 32) & kImm16Mask); |
2189 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); | 2396 *(p + 1) = ORI | (rt_code << kRtShift) | (rt_code << kRsShift) |
2190 | 2397 | ((itarget >> 16) & kImm16Mask); |
2191 // The following code is an optimization for the common case of Call() | 2398 *(p + 3) = ORI | (rt_code << kRsShift) | (rt_code << kRtShift) |
2192 // or Jump() which is load to register, and jump through register: | 2399 | (itarget & kImm16Mask); |
2193 // li(t9, address); jalr(t9) (or jr(t9)). | |
2194 // If the destination address is in the same 256 MB page as the call, it | |
2195 // is faster to do a direct jal, or j, rather than jump thru register, since | |
2196 // that lets the cpu pipeline prefetch the target address. However each | |
2197 // time the address above is patched, we have to patch the direct jal/j | |
2198 // instruction, as well as possibly revert to jalr/jr if we now cross a | |
2199 // 256 MB page. Note that with the jal/j instructions, we do not need to | |
2200 // load the register, but that code is left, since it makes it easy to | |
2201 // revert this process. A further optimization could try replacing the | |
2202 // li sequence with nops. | |
2203 // This optimization can only be applied if the rt-code from instr2 is the | |
2204 // register used for the jalr/jr. Finally, we have to skip 'jr ra', which is | |
2205 // mips return. Occasionally this lands after an li(). | |
2206 | |
2207 Instr instr3 = instr_at(pc + 2 * kInstrSize); | |
2208 uint32_t ipc = reinterpret_cast<uint32_t>(pc + 3 * kInstrSize); | |
2209 bool in_range = ((ipc ^ itarget) >> (kImm26Bits + kImmFieldShift)) == 0; | |
2210 uint32_t target_field = | |
2211 static_cast<uint32_t>(itarget & kJumpAddrMask) >> kImmFieldShift; | |
2212 bool patched_jump = false; | |
2213 | |
2214 #ifndef ALLOW_JAL_IN_BOUNDARY_REGION | |
2215 // This is a workaround to the 24k core E156 bug (affect some 34k cores also). | |
2216 // Since the excluded space is only 64KB out of 256MB (0.02 %), we will just | |
2217 // apply this workaround for all cores so we don't have to identify the core. | |
2218 if (in_range) { | |
2219 // The 24k core E156 bug has some very specific requirements, we only check | |
2220 // the most simple one: if the address of the delay slot instruction is in | |
2221 // the first or last 32 KB of the 256 MB segment. | |
2222 uint32_t segment_mask = ((256 * MB) - 1) ^ ((32 * KB) - 1); | |
2223 uint32_t ipc_segment_addr = ipc & segment_mask; | |
2224 if (ipc_segment_addr == 0 || ipc_segment_addr == segment_mask) | |
2225 in_range = false; | |
2226 } | |
2227 #endif | |
2228 | |
2229 if (IsJalr(instr3)) { | |
2230 // Try to convert JALR to JAL. | |
2231 if (in_range && GetRt(instr2) == GetRs(instr3)) { | |
2232 *(p+2) = JAL | target_field; | |
2233 patched_jump = true; | |
2234 } | |
2235 } else if (IsJr(instr3)) { | |
2236 // Try to convert JR to J, skip returns (jr ra). | |
2237 bool is_ret = static_cast<int>(GetRs(instr3)) == ra.code(); | |
2238 if (in_range && !is_ret && GetRt(instr2) == GetRs(instr3)) { | |
2239 *(p+2) = J | target_field; | |
2240 patched_jump = true; | |
2241 } | |
2242 } else if (IsJal(instr3)) { | |
2243 if (in_range) { | |
2244 // We are patching an already converted JAL. | |
2245 *(p+2) = JAL | target_field; | |
2246 } else { | |
2247 // Patch JAL, but out of range, revert to JALR. | |
2248 // JALR rs reg is the rt reg specified in the ORI instruction. | |
2249 uint32_t rs_field = GetRt(instr2) << kRsShift; | |
2250 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. | |
2251 *(p+2) = SPECIAL | rs_field | rd_field | JALR; | |
2252 } | |
2253 patched_jump = true; | |
2254 } else if (IsJ(instr3)) { | |
2255 if (in_range) { | |
2256 // We are patching an already converted J (jump). | |
2257 *(p+2) = J | target_field; | |
2258 } else { | |
2259 // Trying patch J, but out of range, just go back to JR. | |
2260 // JR 'rs' reg is the 'rt' reg specified in the ORI instruction (instr2). | |
2261 uint32_t rs_field = GetRt(instr2) << kRsShift; | |
2262 *(p+2) = SPECIAL | rs_field | JR; | |
2263 } | |
2264 patched_jump = true; | |
2265 } | |
2266 | 2400 |
2267 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 2401 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
2268 CpuFeatures::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t)); | 2402 CpuFeatures::FlushICache(pc, 4 * Assembler::kInstrSize); |
2269 } | 2403 } |
2270 } | 2404 } |
2271 | 2405 |
2272 | 2406 |
2273 void Assembler::JumpLabelToJumpRegister(Address pc) { | 2407 void Assembler::JumpLabelToJumpRegister(Address pc) { |
2274 // Address pc points to lui/ori instructions. | 2408 // Address pc points to lui/ori instructions. |
2275 // Jump to label may follow at pc + 2 * kInstrSize. | 2409 // Jump to label may follow at pc + 2 * kInstrSize. |
2276 uint32_t* p = reinterpret_cast<uint32_t*>(pc); | 2410 uint32_t* p = reinterpret_cast<uint32_t*>(pc); |
2277 #ifdef DEBUG | 2411 #ifdef DEBUG |
2278 Instr instr1 = instr_at(pc); | 2412 Instr instr1 = instr_at(pc); |
2279 #endif | 2413 #endif |
2280 Instr instr2 = instr_at(pc + 1 * kInstrSize); | 2414 Instr instr2 = instr_at(pc + 1 * kInstrSize); |
2281 Instr instr3 = instr_at(pc + 2 * kInstrSize); | 2415 Instr instr3 = instr_at(pc + 6 * kInstrSize); |
2282 bool patched = false; | 2416 bool patched = false; |
2283 | 2417 |
2284 if (IsJal(instr3)) { | 2418 if (IsJal(instr3)) { |
2285 ASSERT(GetOpcodeField(instr1) == LUI); | 2419 ASSERT(GetOpcodeField(instr1) == LUI); |
2286 ASSERT(GetOpcodeField(instr2) == ORI); | 2420 ASSERT(GetOpcodeField(instr2) == ORI); |
2287 | 2421 |
2288 uint32_t rs_field = GetRt(instr2) << kRsShift; | 2422 uint32_t rs_field = GetRt(instr2) << kRsShift; |
2289 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. | 2423 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. |
2290 *(p+2) = SPECIAL | rs_field | rd_field | JALR; | 2424 *(p+6) = SPECIAL | rs_field | rd_field | JALR; |
2291 patched = true; | 2425 patched = true; |
2292 } else if (IsJ(instr3)) { | 2426 } else if (IsJ(instr3)) { |
2293 ASSERT(GetOpcodeField(instr1) == LUI); | 2427 ASSERT(GetOpcodeField(instr1) == LUI); |
2294 ASSERT(GetOpcodeField(instr2) == ORI); | 2428 ASSERT(GetOpcodeField(instr2) == ORI); |
2295 | 2429 |
2296 uint32_t rs_field = GetRt(instr2) << kRsShift; | 2430 uint32_t rs_field = GetRt(instr2) << kRsShift; |
2297 *(p+2) = SPECIAL | rs_field | JR; | 2431 *(p+6) = SPECIAL | rs_field | JR; |
2298 patched = true; | 2432 patched = true; |
2299 } | 2433 } |
2300 | 2434 |
2301 if (patched) { | 2435 if (patched) { |
2302 CpuFeatures::FlushICache(pc+2, sizeof(Address)); | 2436 CpuFeatures::FlushICache(pc+6, sizeof(int32_t)); |
2303 } | 2437 } |
2304 } | 2438 } |
2305 | 2439 |
2306 | 2440 |
2307 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { | 2441 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { |
2308 // No out-of-line constant pool support. | 2442 // No out-of-line constant pool support. |
2309 ASSERT(!FLAG_enable_ool_constant_pool); | 2443 ASSERT(!FLAG_enable_ool_constant_pool); |
2310 return isolate->factory()->empty_constant_pool_array(); | 2444 return isolate->factory()->empty_constant_pool_array(); |
2311 } | 2445 } |
2312 | 2446 |
2313 | 2447 |
2314 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 2448 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
2315 // No out-of-line constant pool support. | 2449 // No out-of-line constant pool support. |
2316 ASSERT(!FLAG_enable_ool_constant_pool); | 2450 ASSERT(!FLAG_enable_ool_constant_pool); |
2317 return; | 2451 return; |
2318 } | 2452 } |
2319 | 2453 |
2320 | 2454 |
2321 } } // namespace v8::internal | 2455 } } // namespace v8::internal |
2322 | 2456 |
2323 #endif // V8_TARGET_ARCH_MIPS | 2457 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |