blob: e769489479442a24ffcc3f6b480d1c313632d703 [file] [log] [blame]
jeffhao7fbee072012-08-24 17:56:54 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "assembler_mips.h"
18
Vladimir Marko80afd022015-05-19 18:08:00 +010019#include "base/bit_utils.h"
Elliott Hughes1aa246d2012-12-13 09:29:36 -080020#include "base/casts.h"
Ian Rogers166db042013-07-26 12:05:57 -070021#include "entrypoints/quick/quick_entrypoints.h"
jeffhao7fbee072012-08-24 17:56:54 -070022#include "memory_region.h"
jeffhao7fbee072012-08-24 17:56:54 -070023#include "thread.h"
24
25namespace art {
26namespace mips {
jeffhao7fbee072012-08-24 17:56:54 -070027
jeffhao7fbee072012-08-24 17:56:54 -070028std::ostream& operator<<(std::ostream& os, const DRegister& rhs) {
29 if (rhs >= D0 && rhs < kNumberOfDRegisters) {
30 os << "d" << static_cast<int>(rhs);
31 } else {
32 os << "DRegister[" << static_cast<int>(rhs) << "]";
33 }
34 return os;
35}
36
37void MipsAssembler::Emit(int32_t value) {
38 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
39 buffer_.Emit<int32_t>(value);
40}
41
42void MipsAssembler::EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct) {
43 CHECK_NE(rs, kNoRegister);
44 CHECK_NE(rt, kNoRegister);
45 CHECK_NE(rd, kNoRegister);
46 int32_t encoding = opcode << kOpcodeShift |
47 static_cast<int32_t>(rs) << kRsShift |
48 static_cast<int32_t>(rt) << kRtShift |
49 static_cast<int32_t>(rd) << kRdShift |
50 shamt << kShamtShift |
51 funct;
52 Emit(encoding);
53}
54
55void MipsAssembler::EmitI(int opcode, Register rs, Register rt, uint16_t imm) {
56 CHECK_NE(rs, kNoRegister);
57 CHECK_NE(rt, kNoRegister);
58 int32_t encoding = opcode << kOpcodeShift |
59 static_cast<int32_t>(rs) << kRsShift |
60 static_cast<int32_t>(rt) << kRtShift |
61 imm;
62 Emit(encoding);
63}
64
65void MipsAssembler::EmitJ(int opcode, int address) {
66 int32_t encoding = opcode << kOpcodeShift |
67 address;
68 Emit(encoding);
69}
70
71void MipsAssembler::EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct) {
72 CHECK_NE(ft, kNoFRegister);
73 CHECK_NE(fs, kNoFRegister);
74 CHECK_NE(fd, kNoFRegister);
75 int32_t encoding = opcode << kOpcodeShift |
76 fmt << kFmtShift |
77 static_cast<int32_t>(ft) << kFtShift |
78 static_cast<int32_t>(fs) << kFsShift |
79 static_cast<int32_t>(fd) << kFdShift |
80 funct;
81 Emit(encoding);
82}
83
84void MipsAssembler::EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm) {
85 CHECK_NE(rt, kNoFRegister);
86 int32_t encoding = opcode << kOpcodeShift |
87 fmt << kFmtShift |
88 static_cast<int32_t>(rt) << kRtShift |
89 imm;
90 Emit(encoding);
91}
92
93void MipsAssembler::EmitBranch(Register rt, Register rs, Label* label, bool equal) {
94 int offset;
95 if (label->IsBound()) {
96 offset = label->Position() - buffer_.Size();
97 } else {
98 // Use the offset field of the branch instruction for linking the sites.
99 offset = label->position_;
100 label->LinkTo(buffer_.Size());
101 }
102 if (equal) {
103 Beq(rt, rs, (offset >> 2) & kBranchOffsetMask);
104 } else {
105 Bne(rt, rs, (offset >> 2) & kBranchOffsetMask);
106 }
107}
108
109void MipsAssembler::EmitJump(Label* label, bool link) {
110 int offset;
111 if (label->IsBound()) {
112 offset = label->Position() - buffer_.Size();
113 } else {
114 // Use the offset field of the jump instruction for linking the sites.
115 offset = label->position_;
116 label->LinkTo(buffer_.Size());
117 }
118 if (link) {
119 Jal((offset >> 2) & kJumpOffsetMask);
120 } else {
121 J((offset >> 2) & kJumpOffsetMask);
122 }
123}
124
125int32_t MipsAssembler::EncodeBranchOffset(int offset, int32_t inst, bool is_jump) {
126 CHECK_ALIGNED(offset, 4);
Vladimir Marko81949632014-05-02 11:53:22 +0100127 CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
jeffhao7fbee072012-08-24 17:56:54 -0700128
129 // Properly preserve only the bits supported in the instruction.
130 offset >>= 2;
131 if (is_jump) {
132 offset &= kJumpOffsetMask;
133 return (inst & ~kJumpOffsetMask) | offset;
134 } else {
135 offset &= kBranchOffsetMask;
136 return (inst & ~kBranchOffsetMask) | offset;
137 }
138}
139
140int MipsAssembler::DecodeBranchOffset(int32_t inst, bool is_jump) {
141 // Sign-extend, then left-shift by 2.
142 if (is_jump) {
143 return (((inst & kJumpOffsetMask) << 6) >> 4);
144 } else {
145 return (((inst & kBranchOffsetMask) << 16) >> 14);
146 }
147}
148
149void MipsAssembler::Bind(Label* label, bool is_jump) {
150 CHECK(!label->IsBound());
151 int bound_pc = buffer_.Size();
152 while (label->IsLinked()) {
153 int32_t position = label->Position();
154 int32_t next = buffer_.Load<int32_t>(position);
155 int32_t offset = is_jump ? bound_pc - position : bound_pc - position - 4;
156 int32_t encoded = MipsAssembler::EncodeBranchOffset(offset, next, is_jump);
157 buffer_.Store<int32_t>(position, encoded);
158 label->position_ = MipsAssembler::DecodeBranchOffset(next, is_jump);
159 }
160 label->BindTo(bound_pc);
161}
162
163void MipsAssembler::Add(Register rd, Register rs, Register rt) {
164 EmitR(0, rs, rt, rd, 0, 0x20);
165}
166
167void MipsAssembler::Addu(Register rd, Register rs, Register rt) {
168 EmitR(0, rs, rt, rd, 0, 0x21);
169}
170
171void MipsAssembler::Addi(Register rt, Register rs, uint16_t imm16) {
172 EmitI(0x8, rs, rt, imm16);
173}
174
175void MipsAssembler::Addiu(Register rt, Register rs, uint16_t imm16) {
176 EmitI(0x9, rs, rt, imm16);
177}
178
179void MipsAssembler::Sub(Register rd, Register rs, Register rt) {
180 EmitR(0, rs, rt, rd, 0, 0x22);
181}
182
183void MipsAssembler::Subu(Register rd, Register rs, Register rt) {
184 EmitR(0, rs, rt, rd, 0, 0x23);
185}
186
187void MipsAssembler::Mult(Register rs, Register rt) {
188 EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x18);
189}
190
191void MipsAssembler::Multu(Register rs, Register rt) {
192 EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x19);
193}
194
195void MipsAssembler::Div(Register rs, Register rt) {
196 EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1a);
197}
198
199void MipsAssembler::Divu(Register rs, Register rt) {
200 EmitR(0, rs, rt, static_cast<Register>(0), 0, 0x1b);
201}
202
203void MipsAssembler::And(Register rd, Register rs, Register rt) {
204 EmitR(0, rs, rt, rd, 0, 0x24);
205}
206
207void MipsAssembler::Andi(Register rt, Register rs, uint16_t imm16) {
208 EmitI(0xc, rs, rt, imm16);
209}
210
211void MipsAssembler::Or(Register rd, Register rs, Register rt) {
212 EmitR(0, rs, rt, rd, 0, 0x25);
213}
214
215void MipsAssembler::Ori(Register rt, Register rs, uint16_t imm16) {
216 EmitI(0xd, rs, rt, imm16);
217}
218
219void MipsAssembler::Xor(Register rd, Register rs, Register rt) {
220 EmitR(0, rs, rt, rd, 0, 0x26);
221}
222
223void MipsAssembler::Xori(Register rt, Register rs, uint16_t imm16) {
224 EmitI(0xe, rs, rt, imm16);
225}
226
227void MipsAssembler::Nor(Register rd, Register rs, Register rt) {
228 EmitR(0, rs, rt, rd, 0, 0x27);
229}
230
231void MipsAssembler::Sll(Register rd, Register rs, int shamt) {
232 EmitR(0, rs, static_cast<Register>(0), rd, shamt, 0x00);
233}
234
235void MipsAssembler::Srl(Register rd, Register rs, int shamt) {
236 EmitR(0, rs, static_cast<Register>(0), rd, shamt, 0x02);
237}
238
239void MipsAssembler::Sra(Register rd, Register rs, int shamt) {
240 EmitR(0, rs, static_cast<Register>(0), rd, shamt, 0x03);
241}
242
243void MipsAssembler::Sllv(Register rd, Register rs, Register rt) {
244 EmitR(0, rs, rt, rd, 0, 0x04);
245}
246
247void MipsAssembler::Srlv(Register rd, Register rs, Register rt) {
248 EmitR(0, rs, rt, rd, 0, 0x06);
249}
250
251void MipsAssembler::Srav(Register rd, Register rs, Register rt) {
252 EmitR(0, rs, rt, rd, 0, 0x07);
253}
254
255void MipsAssembler::Lb(Register rt, Register rs, uint16_t imm16) {
256 EmitI(0x20, rs, rt, imm16);
257}
258
259void MipsAssembler::Lh(Register rt, Register rs, uint16_t imm16) {
260 EmitI(0x21, rs, rt, imm16);
261}
262
263void MipsAssembler::Lw(Register rt, Register rs, uint16_t imm16) {
264 EmitI(0x23, rs, rt, imm16);
265}
266
267void MipsAssembler::Lbu(Register rt, Register rs, uint16_t imm16) {
268 EmitI(0x24, rs, rt, imm16);
269}
270
271void MipsAssembler::Lhu(Register rt, Register rs, uint16_t imm16) {
272 EmitI(0x25, rs, rt, imm16);
273}
274
275void MipsAssembler::Lui(Register rt, uint16_t imm16) {
276 EmitI(0xf, static_cast<Register>(0), rt, imm16);
277}
278
279void MipsAssembler::Mfhi(Register rd) {
280 EmitR(0, static_cast<Register>(0), static_cast<Register>(0), rd, 0, 0x10);
281}
282
283void MipsAssembler::Mflo(Register rd) {
284 EmitR(0, static_cast<Register>(0), static_cast<Register>(0), rd, 0, 0x12);
285}
286
287void MipsAssembler::Sb(Register rt, Register rs, uint16_t imm16) {
288 EmitI(0x28, rs, rt, imm16);
289}
290
291void MipsAssembler::Sh(Register rt, Register rs, uint16_t imm16) {
292 EmitI(0x29, rs, rt, imm16);
293}
294
295void MipsAssembler::Sw(Register rt, Register rs, uint16_t imm16) {
296 EmitI(0x2b, rs, rt, imm16);
297}
298
299void MipsAssembler::Slt(Register rd, Register rs, Register rt) {
300 EmitR(0, rs, rt, rd, 0, 0x2a);
301}
302
303void MipsAssembler::Sltu(Register rd, Register rs, Register rt) {
304 EmitR(0, rs, rt, rd, 0, 0x2b);
305}
306
307void MipsAssembler::Slti(Register rt, Register rs, uint16_t imm16) {
308 EmitI(0xa, rs, rt, imm16);
309}
310
311void MipsAssembler::Sltiu(Register rt, Register rs, uint16_t imm16) {
312 EmitI(0xb, rs, rt, imm16);
313}
314
315void MipsAssembler::Beq(Register rt, Register rs, uint16_t imm16) {
316 EmitI(0x4, rs, rt, imm16);
jeffhao07030602012-09-26 14:33:14 -0700317 Nop();
jeffhao7fbee072012-08-24 17:56:54 -0700318}
319
320void MipsAssembler::Bne(Register rt, Register rs, uint16_t imm16) {
321 EmitI(0x5, rs, rt, imm16);
jeffhao07030602012-09-26 14:33:14 -0700322 Nop();
jeffhao7fbee072012-08-24 17:56:54 -0700323}
324
325void MipsAssembler::J(uint32_t address) {
326 EmitJ(0x2, address);
jeffhao07030602012-09-26 14:33:14 -0700327 Nop();
jeffhao7fbee072012-08-24 17:56:54 -0700328}
329
330void MipsAssembler::Jal(uint32_t address) {
331 EmitJ(0x2, address);
jeffhao07030602012-09-26 14:33:14 -0700332 Nop();
jeffhao7fbee072012-08-24 17:56:54 -0700333}
334
335void MipsAssembler::Jr(Register rs) {
Andreas Gampe8d365912015-01-13 11:32:32 -0800336 EmitR(0, rs, static_cast<Register>(0), static_cast<Register>(0), 0, 0x09); // Jalr zero, rs
jeffhao07030602012-09-26 14:33:14 -0700337 Nop();
jeffhao7fbee072012-08-24 17:56:54 -0700338}
339
340void MipsAssembler::Jalr(Register rs) {
jeffhao07030602012-09-26 14:33:14 -0700341 EmitR(0, rs, static_cast<Register>(0), RA, 0, 0x09);
342 Nop();
jeffhao7fbee072012-08-24 17:56:54 -0700343}
344
345void MipsAssembler::AddS(FRegister fd, FRegister fs, FRegister ft) {
346 EmitFR(0x11, 0x10, ft, fs, fd, 0x0);
347}
348
349void MipsAssembler::SubS(FRegister fd, FRegister fs, FRegister ft) {
350 EmitFR(0x11, 0x10, ft, fs, fd, 0x1);
351}
352
353void MipsAssembler::MulS(FRegister fd, FRegister fs, FRegister ft) {
354 EmitFR(0x11, 0x10, ft, fs, fd, 0x2);
355}
356
357void MipsAssembler::DivS(FRegister fd, FRegister fs, FRegister ft) {
358 EmitFR(0x11, 0x10, ft, fs, fd, 0x3);
359}
360
361void MipsAssembler::AddD(DRegister fd, DRegister fs, DRegister ft) {
362 EmitFR(0x11, 0x11, static_cast<FRegister>(ft), static_cast<FRegister>(fs),
363 static_cast<FRegister>(fd), 0x0);
364}
365
366void MipsAssembler::SubD(DRegister fd, DRegister fs, DRegister ft) {
367 EmitFR(0x11, 0x11, static_cast<FRegister>(ft), static_cast<FRegister>(fs),
368 static_cast<FRegister>(fd), 0x1);
369}
370
371void MipsAssembler::MulD(DRegister fd, DRegister fs, DRegister ft) {
372 EmitFR(0x11, 0x11, static_cast<FRegister>(ft), static_cast<FRegister>(fs),
373 static_cast<FRegister>(fd), 0x2);
374}
375
376void MipsAssembler::DivD(DRegister fd, DRegister fs, DRegister ft) {
377 EmitFR(0x11, 0x11, static_cast<FRegister>(ft), static_cast<FRegister>(fs),
378 static_cast<FRegister>(fd), 0x3);
379}
380
381void MipsAssembler::MovS(FRegister fd, FRegister fs) {
382 EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6);
383}
384
385void MipsAssembler::MovD(DRegister fd, DRegister fs) {
386 EmitFR(0x11, 0x11, static_cast<FRegister>(0), static_cast<FRegister>(fs),
387 static_cast<FRegister>(fd), 0x6);
388}
389
390void MipsAssembler::Mfc1(Register rt, FRegister fs) {
391 EmitFR(0x11, 0x00, static_cast<FRegister>(rt), fs, static_cast<FRegister>(0), 0x0);
392}
393
394void MipsAssembler::Mtc1(FRegister ft, Register rs) {
395 EmitFR(0x11, 0x04, ft, static_cast<FRegister>(rs), static_cast<FRegister>(0), 0x0);
396}
397
398void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) {
399 EmitI(0x31, rs, static_cast<Register>(ft), imm16);
400}
401
402void MipsAssembler::Ldc1(DRegister ft, Register rs, uint16_t imm16) {
403 EmitI(0x35, rs, static_cast<Register>(ft), imm16);
404}
405
406void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) {
407 EmitI(0x39, rs, static_cast<Register>(ft), imm16);
408}
409
410void MipsAssembler::Sdc1(DRegister ft, Register rs, uint16_t imm16) {
411 EmitI(0x3d, rs, static_cast<Register>(ft), imm16);
412}
413
414void MipsAssembler::Break() {
415 EmitR(0, static_cast<Register>(0), static_cast<Register>(0),
416 static_cast<Register>(0), 0, 0xD);
417}
418
jeffhao07030602012-09-26 14:33:14 -0700419void MipsAssembler::Nop() {
420 EmitR(0x0, static_cast<Register>(0), static_cast<Register>(0), static_cast<Register>(0), 0, 0x0);
421}
422
jeffhao7fbee072012-08-24 17:56:54 -0700423void MipsAssembler::Move(Register rt, Register rs) {
Andreas Gampe8d365912015-01-13 11:32:32 -0800424 EmitI(0x9, rs, rt, 0); // Addiu
jeffhao7fbee072012-08-24 17:56:54 -0700425}
426
427void MipsAssembler::Clear(Register rt) {
428 EmitR(0, static_cast<Register>(0), static_cast<Register>(0), rt, 0, 0x20);
429}
430
431void MipsAssembler::Not(Register rt, Register rs) {
432 EmitR(0, static_cast<Register>(0), rs, rt, 0, 0x27);
433}
434
435void MipsAssembler::Mul(Register rd, Register rs, Register rt) {
436 Mult(rs, rt);
437 Mflo(rd);
438}
439
440void MipsAssembler::Div(Register rd, Register rs, Register rt) {
441 Div(rs, rt);
442 Mflo(rd);
443}
444
445void MipsAssembler::Rem(Register rd, Register rs, Register rt) {
446 Div(rs, rt);
447 Mfhi(rd);
448}
449
450void MipsAssembler::AddConstant(Register rt, Register rs, int32_t value) {
Andreas Gampe8d365912015-01-13 11:32:32 -0800451 Addiu(rt, rs, value);
jeffhao7fbee072012-08-24 17:56:54 -0700452}
453
454void MipsAssembler::LoadImmediate(Register rt, int32_t value) {
Andreas Gampe8d365912015-01-13 11:32:32 -0800455 Addiu(rt, ZERO, value);
jeffhao7fbee072012-08-24 17:56:54 -0700456}
457
458void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset,
459 size_t size) {
460 MipsManagedRegister dst = m_dst.AsMips();
461 if (dst.IsNoRegister()) {
462 CHECK_EQ(0u, size) << dst;
463 } else if (dst.IsCoreRegister()) {
464 CHECK_EQ(4u, size) << dst;
465 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset);
466 } else if (dst.IsRegisterPair()) {
467 CHECK_EQ(8u, size) << dst;
468 LoadFromOffset(kLoadWord, dst.AsRegisterPairLow(), src_register, src_offset);
469 LoadFromOffset(kLoadWord, dst.AsRegisterPairHigh(), src_register, src_offset + 4);
470 } else if (dst.IsFRegister()) {
471 LoadSFromOffset(dst.AsFRegister(), src_register, src_offset);
472 } else {
473 CHECK(dst.IsDRegister()) << dst;
474 LoadDFromOffset(dst.AsDRegister(), src_register, src_offset);
475 }
476}
477
478void MipsAssembler::LoadFromOffset(LoadOperandType type, Register reg, Register base,
479 int32_t offset) {
480 switch (type) {
481 case kLoadSignedByte:
482 Lb(reg, base, offset);
483 break;
484 case kLoadUnsignedByte:
485 Lbu(reg, base, offset);
486 break;
487 case kLoadSignedHalfword:
488 Lh(reg, base, offset);
489 break;
490 case kLoadUnsignedHalfword:
491 Lhu(reg, base, offset);
492 break;
493 case kLoadWord:
494 Lw(reg, base, offset);
495 break;
496 case kLoadWordPair:
497 LOG(FATAL) << "UNREACHABLE";
498 break;
499 default:
500 LOG(FATAL) << "UNREACHABLE";
501 }
502}
503
504void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) {
505 Lwc1(reg, base, offset);
506}
507
508void MipsAssembler::LoadDFromOffset(DRegister reg, Register base, int32_t offset) {
509 Ldc1(reg, base, offset);
510}
511
512void MipsAssembler::StoreToOffset(StoreOperandType type, Register reg, Register base,
513 int32_t offset) {
514 switch (type) {
515 case kStoreByte:
516 Sb(reg, base, offset);
517 break;
518 case kStoreHalfword:
519 Sh(reg, base, offset);
520 break;
521 case kStoreWord:
522 Sw(reg, base, offset);
523 break;
524 case kStoreWordPair:
525 LOG(FATAL) << "UNREACHABLE";
526 break;
527 default:
528 LOG(FATAL) << "UNREACHABLE";
529 }
530}
531
532void MipsAssembler::StoreFToOffset(FRegister reg, Register base, int32_t offset) {
533 Swc1(reg, base, offset);
534}
535
536void MipsAssembler::StoreDToOffset(DRegister reg, Register base, int32_t offset) {
537 Sdc1(reg, base, offset);
538}
539
David Srbeckydd973932015-04-07 20:29:48 +0100540static dwarf::Reg DWARFReg(Register reg) {
541 return dwarf::Reg::MipsCore(static_cast<int>(reg));
542}
543
Ian Rogers790a6b72014-04-01 10:36:00 -0700544constexpr size_t kFramePointerSize = 4;
545
jeffhao7fbee072012-08-24 17:56:54 -0700546void MipsAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
547 const std::vector<ManagedRegister>& callee_save_regs,
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700548 const ManagedRegisterEntrySpills& entry_spills) {
jeffhao7fbee072012-08-24 17:56:54 -0700549 CHECK_ALIGNED(frame_size, kStackAlignment);
550
551 // Increase frame to required size.
552 IncreaseFrameSize(frame_size);
553
554 // Push callee saves and return address
Ian Rogers790a6b72014-04-01 10:36:00 -0700555 int stack_offset = frame_size - kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700556 StoreToOffset(kStoreWord, RA, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100557 cfi_.RelOffset(DWARFReg(RA), stack_offset);
jeffhao7fbee072012-08-24 17:56:54 -0700558 for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700559 stack_offset -= kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700560 Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
561 StoreToOffset(kStoreWord, reg, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100562 cfi_.RelOffset(DWARFReg(reg), stack_offset);
jeffhao7fbee072012-08-24 17:56:54 -0700563 }
564
565 // Write out Method*.
566 StoreToOffset(kStoreWord, method_reg.AsMips().AsCoreRegister(), SP, 0);
567
568 // Write out entry spills.
569 for (size_t i = 0; i < entry_spills.size(); ++i) {
570 Register reg = entry_spills.at(i).AsMips().AsCoreRegister();
Ian Rogers790a6b72014-04-01 10:36:00 -0700571 StoreToOffset(kStoreWord, reg, SP, frame_size + kFramePointerSize + (i * kFramePointerSize));
jeffhao7fbee072012-08-24 17:56:54 -0700572 }
573}
574
575void MipsAssembler::RemoveFrame(size_t frame_size,
576 const std::vector<ManagedRegister>& callee_save_regs) {
577 CHECK_ALIGNED(frame_size, kStackAlignment);
David Srbeckydd973932015-04-07 20:29:48 +0100578 cfi_.RememberState();
jeffhao7fbee072012-08-24 17:56:54 -0700579
580 // Pop callee saves and return address
Ian Rogers790a6b72014-04-01 10:36:00 -0700581 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700582 for (size_t i = 0; i < callee_save_regs.size(); ++i) {
583 Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
584 LoadFromOffset(kLoadWord, reg, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100585 cfi_.Restore(DWARFReg(reg));
Ian Rogers790a6b72014-04-01 10:36:00 -0700586 stack_offset += kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700587 }
588 LoadFromOffset(kLoadWord, RA, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100589 cfi_.Restore(DWARFReg(RA));
jeffhao7fbee072012-08-24 17:56:54 -0700590
591 // Decrease frame to required size.
592 DecreaseFrameSize(frame_size);
jeffhao07030602012-09-26 14:33:14 -0700593
594 // Then jump to the return address.
595 Jr(RA);
David Srbeckydd973932015-04-07 20:29:48 +0100596
597 // The CFI should be restored for any code that follows the exit block.
598 cfi_.RestoreState();
599 cfi_.DefCFAOffset(frame_size);
jeffhao7fbee072012-08-24 17:56:54 -0700600}
601
602void MipsAssembler::IncreaseFrameSize(size_t adjust) {
603 CHECK_ALIGNED(adjust, kStackAlignment);
604 AddConstant(SP, SP, -adjust);
David Srbeckydd973932015-04-07 20:29:48 +0100605 cfi_.AdjustCFAOffset(adjust);
jeffhao7fbee072012-08-24 17:56:54 -0700606}
607
608void MipsAssembler::DecreaseFrameSize(size_t adjust) {
609 CHECK_ALIGNED(adjust, kStackAlignment);
610 AddConstant(SP, SP, adjust);
David Srbeckydd973932015-04-07 20:29:48 +0100611 cfi_.AdjustCFAOffset(-adjust);
jeffhao7fbee072012-08-24 17:56:54 -0700612}
613
614void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
615 MipsManagedRegister src = msrc.AsMips();
616 if (src.IsNoRegister()) {
617 CHECK_EQ(0u, size);
618 } else if (src.IsCoreRegister()) {
619 CHECK_EQ(4u, size);
620 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
621 } else if (src.IsRegisterPair()) {
622 CHECK_EQ(8u, size);
623 StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
624 StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
625 SP, dest.Int32Value() + 4);
626 } else if (src.IsFRegister()) {
627 StoreFToOffset(src.AsFRegister(), SP, dest.Int32Value());
628 } else {
629 CHECK(src.IsDRegister());
630 StoreDToOffset(src.AsDRegister(), SP, dest.Int32Value());
631 }
632}
633
634void MipsAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
635 MipsManagedRegister src = msrc.AsMips();
636 CHECK(src.IsCoreRegister());
637 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
638}
639
640void MipsAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
641 MipsManagedRegister src = msrc.AsMips();
642 CHECK(src.IsCoreRegister());
643 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
644}
645
646void MipsAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
647 ManagedRegister mscratch) {
648 MipsManagedRegister scratch = mscratch.AsMips();
649 CHECK(scratch.IsCoreRegister()) << scratch;
650 LoadImmediate(scratch.AsCoreRegister(), imm);
651 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
652}
653
Ian Rogersdd7624d2014-03-14 17:43:00 -0700654void MipsAssembler::StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm,
jeffhao7fbee072012-08-24 17:56:54 -0700655 ManagedRegister mscratch) {
656 MipsManagedRegister scratch = mscratch.AsMips();
657 CHECK(scratch.IsCoreRegister()) << scratch;
658 LoadImmediate(scratch.AsCoreRegister(), imm);
659 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), S1, dest.Int32Value());
660}
661
Ian Rogersdd7624d2014-03-14 17:43:00 -0700662void MipsAssembler::StoreStackOffsetToThread32(ThreadOffset<4> thr_offs,
jeffhao7fbee072012-08-24 17:56:54 -0700663 FrameOffset fr_offs,
664 ManagedRegister mscratch) {
665 MipsManagedRegister scratch = mscratch.AsMips();
666 CHECK(scratch.IsCoreRegister()) << scratch;
667 AddConstant(scratch.AsCoreRegister(), SP, fr_offs.Int32Value());
668 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
669 S1, thr_offs.Int32Value());
670}
671
Ian Rogersdd7624d2014-03-14 17:43:00 -0700672void MipsAssembler::StoreStackPointerToThread32(ThreadOffset<4> thr_offs) {
jeffhao7fbee072012-08-24 17:56:54 -0700673 StoreToOffset(kStoreWord, SP, S1, thr_offs.Int32Value());
674}
675
676void MipsAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
677 FrameOffset in_off, ManagedRegister mscratch) {
678 MipsManagedRegister src = msrc.AsMips();
679 MipsManagedRegister scratch = mscratch.AsMips();
680 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
681 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
682 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
683}
684
685void MipsAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
686 return EmitLoad(mdest, SP, src.Int32Value(), size);
687}
688
Ian Rogersdd7624d2014-03-14 17:43:00 -0700689void MipsAssembler::LoadFromThread32(ManagedRegister mdest, ThreadOffset<4> src, size_t size) {
jeffhao7fbee072012-08-24 17:56:54 -0700690 return EmitLoad(mdest, S1, src.Int32Value(), size);
691}
692
693void MipsAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
694 MipsManagedRegister dest = mdest.AsMips();
695 CHECK(dest.IsCoreRegister());
696 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
697}
698
699void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
700 MemberOffset offs) {
701 MipsManagedRegister dest = mdest.AsMips();
702 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
703 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
704 base.AsMips().AsCoreRegister(), offs.Int32Value());
Hiroshi Yamauchie63a7452014-02-27 14:44:36 -0800705 if (kPoisonHeapReferences) {
706 Subu(dest.AsCoreRegister(), ZERO, dest.AsCoreRegister());
707 }
jeffhao7fbee072012-08-24 17:56:54 -0700708}
709
710void MipsAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
711 Offset offs) {
712 MipsManagedRegister dest = mdest.AsMips();
713 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister()) << dest;
714 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
715 base.AsMips().AsCoreRegister(), offs.Int32Value());
716}
717
Ian Rogersdd7624d2014-03-14 17:43:00 -0700718void MipsAssembler::LoadRawPtrFromThread32(ManagedRegister mdest,
719 ThreadOffset<4> offs) {
jeffhao7fbee072012-08-24 17:56:54 -0700720 MipsManagedRegister dest = mdest.AsMips();
721 CHECK(dest.IsCoreRegister());
722 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), S1, offs.Int32Value());
723}
724
725void MipsAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
726 UNIMPLEMENTED(FATAL) << "no sign extension necessary for mips";
727}
728
729void MipsAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
730 UNIMPLEMENTED(FATAL) << "no zero extension necessary for mips";
731}
732
733void MipsAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t /*size*/) {
734 MipsManagedRegister dest = mdest.AsMips();
735 MipsManagedRegister src = msrc.AsMips();
736 if (!dest.Equals(src)) {
737 if (dest.IsCoreRegister()) {
738 CHECK(src.IsCoreRegister()) << src;
739 Move(dest.AsCoreRegister(), src.AsCoreRegister());
740 } else if (dest.IsFRegister()) {
741 CHECK(src.IsFRegister()) << src;
742 MovS(dest.AsFRegister(), src.AsFRegister());
743 } else if (dest.IsDRegister()) {
744 CHECK(src.IsDRegister()) << src;
745 MovD(dest.AsDRegister(), src.AsDRegister());
746 } else {
747 CHECK(dest.IsRegisterPair()) << dest;
748 CHECK(src.IsRegisterPair()) << src;
749 // Ensure that the first move doesn't clobber the input of the second
750 if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
751 Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
752 Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
753 } else {
754 Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
755 Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
756 }
757 }
758 }
759}
760
761void MipsAssembler::CopyRef(FrameOffset dest, FrameOffset src,
762 ManagedRegister mscratch) {
763 MipsManagedRegister scratch = mscratch.AsMips();
764 CHECK(scratch.IsCoreRegister()) << scratch;
765 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
766 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
767}
768
Ian Rogersdd7624d2014-03-14 17:43:00 -0700769void MipsAssembler::CopyRawPtrFromThread32(FrameOffset fr_offs,
770 ThreadOffset<4> thr_offs,
jeffhao7fbee072012-08-24 17:56:54 -0700771 ManagedRegister mscratch) {
772 MipsManagedRegister scratch = mscratch.AsMips();
773 CHECK(scratch.IsCoreRegister()) << scratch;
774 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
775 S1, thr_offs.Int32Value());
776 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
777 SP, fr_offs.Int32Value());
778}
779
Ian Rogersdd7624d2014-03-14 17:43:00 -0700780void MipsAssembler::CopyRawPtrToThread32(ThreadOffset<4> thr_offs,
jeffhao7fbee072012-08-24 17:56:54 -0700781 FrameOffset fr_offs,
782 ManagedRegister mscratch) {
783 MipsManagedRegister scratch = mscratch.AsMips();
784 CHECK(scratch.IsCoreRegister()) << scratch;
785 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
786 SP, fr_offs.Int32Value());
787 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
788 S1, thr_offs.Int32Value());
789}
790
791void MipsAssembler::Copy(FrameOffset dest, FrameOffset src,
792 ManagedRegister mscratch, size_t size) {
793 MipsManagedRegister scratch = mscratch.AsMips();
794 CHECK(scratch.IsCoreRegister()) << scratch;
795 CHECK(size == 4 || size == 8) << size;
796 if (size == 4) {
797 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
798 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
799 } else if (size == 8) {
800 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
801 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
802 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + 4);
803 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
804 }
805}
806
807void MipsAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
808 ManagedRegister mscratch, size_t size) {
809 Register scratch = mscratch.AsMips().AsCoreRegister();
810 CHECK_EQ(size, 4u);
811 LoadFromOffset(kLoadWord, scratch, src_base.AsMips().AsCoreRegister(), src_offset.Int32Value());
812 StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
813}
814
815void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
816 ManagedRegister mscratch, size_t size) {
817 Register scratch = mscratch.AsMips().AsCoreRegister();
818 CHECK_EQ(size, 4u);
819 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
820 StoreToOffset(kStoreWord, scratch, dest_base.AsMips().AsCoreRegister(), dest_offset.Int32Value());
821}
822
823void MipsAssembler::Copy(FrameOffset /*dest*/, FrameOffset /*src_base*/, Offset /*src_offset*/,
824 ManagedRegister /*mscratch*/, size_t /*size*/) {
Ian Rogers468532e2013-08-05 10:56:33 -0700825 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700826}
827
828void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
829 ManagedRegister src, Offset src_offset,
830 ManagedRegister mscratch, size_t size) {
831 CHECK_EQ(size, 4u);
832 Register scratch = mscratch.AsMips().AsCoreRegister();
833 LoadFromOffset(kLoadWord, scratch, src.AsMips().AsCoreRegister(), src_offset.Int32Value());
834 StoreToOffset(kStoreWord, scratch, dest.AsMips().AsCoreRegister(), dest_offset.Int32Value());
835}
836
837void MipsAssembler::Copy(FrameOffset /*dest*/, Offset /*dest_offset*/, FrameOffset /*src*/, Offset /*src_offset*/,
838 ManagedRegister /*mscratch*/, size_t /*size*/) {
Ian Rogers468532e2013-08-05 10:56:33 -0700839 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700840}
841
842void MipsAssembler::MemoryBarrier(ManagedRegister) {
Ian Rogers468532e2013-08-05 10:56:33 -0700843 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700844}
845
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700846void MipsAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
847 FrameOffset handle_scope_offset,
jeffhao7fbee072012-08-24 17:56:54 -0700848 ManagedRegister min_reg, bool null_allowed) {
849 MipsManagedRegister out_reg = mout_reg.AsMips();
850 MipsManagedRegister in_reg = min_reg.AsMips();
851 CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg;
852 CHECK(out_reg.IsCoreRegister()) << out_reg;
853 if (null_allowed) {
854 Label null_arg;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700855 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
856 // the address in the handle scope holding the reference.
jeffhao7fbee072012-08-24 17:56:54 -0700857 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
858 if (in_reg.IsNoRegister()) {
859 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700860 SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700861 in_reg = out_reg;
862 }
863 if (!out_reg.Equals(in_reg)) {
864 LoadImmediate(out_reg.AsCoreRegister(), 0);
865 }
866 EmitBranch(in_reg.AsCoreRegister(), ZERO, &null_arg, true);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700867 AddConstant(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700868 Bind(&null_arg, false);
869 } else {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700870 AddConstant(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700871 }
872}
873
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700874void MipsAssembler::CreateHandleScopeEntry(FrameOffset out_off,
875 FrameOffset handle_scope_offset,
jeffhao7fbee072012-08-24 17:56:54 -0700876 ManagedRegister mscratch,
877 bool null_allowed) {
878 MipsManagedRegister scratch = mscratch.AsMips();
879 CHECK(scratch.IsCoreRegister()) << scratch;
880 if (null_allowed) {
881 Label null_arg;
882 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP,
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700883 handle_scope_offset.Int32Value());
884 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
885 // the address in the handle scope holding the reference.
886 // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
jeffhao7fbee072012-08-24 17:56:54 -0700887 EmitBranch(scratch.AsCoreRegister(), ZERO, &null_arg, true);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700888 AddConstant(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700889 Bind(&null_arg, false);
890 } else {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700891 AddConstant(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700892 }
893 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
894}
895
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700896// Given a handle scope entry, load the associated reference.
897void MipsAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
jeffhao7fbee072012-08-24 17:56:54 -0700898 ManagedRegister min_reg) {
899 MipsManagedRegister out_reg = mout_reg.AsMips();
900 MipsManagedRegister in_reg = min_reg.AsMips();
901 CHECK(out_reg.IsCoreRegister()) << out_reg;
902 CHECK(in_reg.IsCoreRegister()) << in_reg;
903 Label null_arg;
904 if (!out_reg.Equals(in_reg)) {
905 LoadImmediate(out_reg.AsCoreRegister(), 0);
906 }
907 EmitBranch(in_reg.AsCoreRegister(), ZERO, &null_arg, true);
908 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
909 in_reg.AsCoreRegister(), 0);
910 Bind(&null_arg, false);
911}
912
913void MipsAssembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) {
914 // TODO: not validating references
915}
916
917void MipsAssembler::VerifyObject(FrameOffset /*src*/, bool /*could_be_null*/) {
918 // TODO: not validating references
919}
920
921void MipsAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
922 MipsManagedRegister base = mbase.AsMips();
923 MipsManagedRegister scratch = mscratch.AsMips();
924 CHECK(base.IsCoreRegister()) << base;
925 CHECK(scratch.IsCoreRegister()) << scratch;
926 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
927 base.AsCoreRegister(), offset.Int32Value());
928 Jalr(scratch.AsCoreRegister());
929 // TODO: place reference map on call
930}
931
932void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
933 MipsManagedRegister scratch = mscratch.AsMips();
934 CHECK(scratch.IsCoreRegister()) << scratch;
935 // Call *(*(SP + base) + offset)
936 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
937 SP, base.Int32Value());
938 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
939 scratch.AsCoreRegister(), offset.Int32Value());
940 Jalr(scratch.AsCoreRegister());
941 // TODO: place reference map on call
942}
943
Ian Rogersdd7624d2014-03-14 17:43:00 -0700944void MipsAssembler::CallFromThread32(ThreadOffset<4> /*offset*/, ManagedRegister /*mscratch*/) {
Ian Rogers468532e2013-08-05 10:56:33 -0700945 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700946}
947
948void MipsAssembler::GetCurrentThread(ManagedRegister tr) {
949 Move(tr.AsMips().AsCoreRegister(), S1);
950}
951
952void MipsAssembler::GetCurrentThread(FrameOffset offset,
953 ManagedRegister /*mscratch*/) {
954 StoreToOffset(kStoreWord, S1, SP, offset.Int32Value());
955}
956
jeffhao7fbee072012-08-24 17:56:54 -0700957void MipsAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
958 MipsManagedRegister scratch = mscratch.AsMips();
959 MipsExceptionSlowPath* slow = new MipsExceptionSlowPath(scratch, stack_adjust);
960 buffer_.EnqueueSlowPath(slow);
961 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
Ian Rogersdd7624d2014-03-14 17:43:00 -0700962 S1, Thread::ExceptionOffset<4>().Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700963 EmitBranch(scratch.AsCoreRegister(), ZERO, slow->Entry(), false);
964}
965
966void MipsExceptionSlowPath::Emit(Assembler* sasm) {
967 MipsAssembler* sp_asm = down_cast<MipsAssembler*>(sasm);
968#define __ sp_asm->
969 __ Bind(&entry_, false);
970 if (stack_adjust_ != 0) { // Fix up the frame.
971 __ DecreaseFrameSize(stack_adjust_);
972 }
973 // Pass exception object as argument
974 // Don't care about preserving A0 as this call won't return
975 __ Move(A0, scratch_.AsCoreRegister());
976 // Set up call to Thread::Current()->pDeliverException
Ian Rogersdd7624d2014-03-14 17:43:00 -0700977 __ LoadFromOffset(kLoadWord, T9, S1, QUICK_ENTRYPOINT_OFFSET(4, pDeliverException).Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700978 __ Jr(T9);
979 // Call never returns
980 __ Break();
981#undef __
982}
983
984} // namespace mips
985} // namespace art