blob: c5fae92f3c33569a51baf5fcd9f34361d6a65605 [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) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000362 EmitFR(0x11, 0x11, ConvertDRegToFReg(ft), ConvertDRegToFReg(fs), ConvertDRegToFReg(fd), 0x0);
jeffhao7fbee072012-08-24 17:56:54 -0700363}
364
365void MipsAssembler::SubD(DRegister fd, DRegister fs, DRegister ft) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000366 EmitFR(0x11, 0x11, ConvertDRegToFReg(ft), ConvertDRegToFReg(fs), ConvertDRegToFReg(fd), 0x1);
jeffhao7fbee072012-08-24 17:56:54 -0700367}
368
369void MipsAssembler::MulD(DRegister fd, DRegister fs, DRegister ft) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000370 EmitFR(0x11, 0x11, ConvertDRegToFReg(ft), ConvertDRegToFReg(fs), ConvertDRegToFReg(fd), 0x2);
jeffhao7fbee072012-08-24 17:56:54 -0700371}
372
373void MipsAssembler::DivD(DRegister fd, DRegister fs, DRegister ft) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000374 EmitFR(0x11, 0x11, ConvertDRegToFReg(ft), ConvertDRegToFReg(fs), ConvertDRegToFReg(fd), 0x3);
jeffhao7fbee072012-08-24 17:56:54 -0700375}
376
377void MipsAssembler::MovS(FRegister fd, FRegister fs) {
378 EmitFR(0x11, 0x10, static_cast<FRegister>(0), fs, fd, 0x6);
379}
380
381void MipsAssembler::MovD(DRegister fd, DRegister fs) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000382 EmitFR(0x11, 0x11, static_cast<FRegister>(0), ConvertDRegToFReg(fs), ConvertDRegToFReg(fd), 0x6);
jeffhao7fbee072012-08-24 17:56:54 -0700383}
384
385void MipsAssembler::Mfc1(Register rt, FRegister fs) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000386 EmitFR(0x11, 0x00, ConvertRegToFReg(rt), fs, static_cast<FRegister>(0), 0x0);
jeffhao7fbee072012-08-24 17:56:54 -0700387}
388
389void MipsAssembler::Mtc1(FRegister ft, Register rs) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000390 EmitFR(0x11, 0x04, ft, ConvertRegToFReg(rs), static_cast<FRegister>(0), 0x0);
jeffhao7fbee072012-08-24 17:56:54 -0700391}
392
393void MipsAssembler::Lwc1(FRegister ft, Register rs, uint16_t imm16) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000394 EmitI(0x31, rs, ConvertFRegToReg(ft), imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700395}
396
397void MipsAssembler::Ldc1(DRegister ft, Register rs, uint16_t imm16) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000398 EmitI(0x35, rs, ConvertDRegToReg(ft), imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700399}
400
401void MipsAssembler::Swc1(FRegister ft, Register rs, uint16_t imm16) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000402 EmitI(0x39, rs, ConvertFRegToReg(ft), imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700403}
404
405void MipsAssembler::Sdc1(DRegister ft, Register rs, uint16_t imm16) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000406 EmitI(0x3d, rs, ConvertDRegToReg(ft), imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700407}
408
409void MipsAssembler::Break() {
410 EmitR(0, static_cast<Register>(0), static_cast<Register>(0),
411 static_cast<Register>(0), 0, 0xD);
412}
413
jeffhao07030602012-09-26 14:33:14 -0700414void MipsAssembler::Nop() {
415 EmitR(0x0, static_cast<Register>(0), static_cast<Register>(0), static_cast<Register>(0), 0, 0x0);
416}
417
jeffhao7fbee072012-08-24 17:56:54 -0700418void MipsAssembler::Move(Register rt, Register rs) {
Andreas Gampe8d365912015-01-13 11:32:32 -0800419 EmitI(0x9, rs, rt, 0); // Addiu
jeffhao7fbee072012-08-24 17:56:54 -0700420}
421
422void MipsAssembler::Clear(Register rt) {
423 EmitR(0, static_cast<Register>(0), static_cast<Register>(0), rt, 0, 0x20);
424}
425
426void MipsAssembler::Not(Register rt, Register rs) {
427 EmitR(0, static_cast<Register>(0), rs, rt, 0, 0x27);
428}
429
430void MipsAssembler::Mul(Register rd, Register rs, Register rt) {
431 Mult(rs, rt);
432 Mflo(rd);
433}
434
435void MipsAssembler::Div(Register rd, Register rs, Register rt) {
436 Div(rs, rt);
437 Mflo(rd);
438}
439
440void MipsAssembler::Rem(Register rd, Register rs, Register rt) {
441 Div(rs, rt);
442 Mfhi(rd);
443}
444
445void MipsAssembler::AddConstant(Register rt, Register rs, int32_t value) {
Andreas Gampe8d365912015-01-13 11:32:32 -0800446 Addiu(rt, rs, value);
jeffhao7fbee072012-08-24 17:56:54 -0700447}
448
449void MipsAssembler::LoadImmediate(Register rt, int32_t value) {
Andreas Gampe8d365912015-01-13 11:32:32 -0800450 Addiu(rt, ZERO, value);
jeffhao7fbee072012-08-24 17:56:54 -0700451}
452
453void MipsAssembler::EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset,
454 size_t size) {
455 MipsManagedRegister dst = m_dst.AsMips();
456 if (dst.IsNoRegister()) {
457 CHECK_EQ(0u, size) << dst;
458 } else if (dst.IsCoreRegister()) {
459 CHECK_EQ(4u, size) << dst;
460 LoadFromOffset(kLoadWord, dst.AsCoreRegister(), src_register, src_offset);
461 } else if (dst.IsRegisterPair()) {
462 CHECK_EQ(8u, size) << dst;
463 LoadFromOffset(kLoadWord, dst.AsRegisterPairLow(), src_register, src_offset);
464 LoadFromOffset(kLoadWord, dst.AsRegisterPairHigh(), src_register, src_offset + 4);
465 } else if (dst.IsFRegister()) {
466 LoadSFromOffset(dst.AsFRegister(), src_register, src_offset);
467 } else {
468 CHECK(dst.IsDRegister()) << dst;
469 LoadDFromOffset(dst.AsDRegister(), src_register, src_offset);
470 }
471}
472
473void MipsAssembler::LoadFromOffset(LoadOperandType type, Register reg, Register base,
474 int32_t offset) {
475 switch (type) {
476 case kLoadSignedByte:
477 Lb(reg, base, offset);
478 break;
479 case kLoadUnsignedByte:
480 Lbu(reg, base, offset);
481 break;
482 case kLoadSignedHalfword:
483 Lh(reg, base, offset);
484 break;
485 case kLoadUnsignedHalfword:
486 Lhu(reg, base, offset);
487 break;
488 case kLoadWord:
489 Lw(reg, base, offset);
490 break;
491 case kLoadWordPair:
492 LOG(FATAL) << "UNREACHABLE";
493 break;
494 default:
495 LOG(FATAL) << "UNREACHABLE";
496 }
497}
498
499void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) {
500 Lwc1(reg, base, offset);
501}
502
503void MipsAssembler::LoadDFromOffset(DRegister reg, Register base, int32_t offset) {
504 Ldc1(reg, base, offset);
505}
506
507void MipsAssembler::StoreToOffset(StoreOperandType type, Register reg, Register base,
508 int32_t offset) {
509 switch (type) {
510 case kStoreByte:
511 Sb(reg, base, offset);
512 break;
513 case kStoreHalfword:
514 Sh(reg, base, offset);
515 break;
516 case kStoreWord:
517 Sw(reg, base, offset);
518 break;
519 case kStoreWordPair:
520 LOG(FATAL) << "UNREACHABLE";
521 break;
522 default:
523 LOG(FATAL) << "UNREACHABLE";
524 }
525}
526
Goran Jakovljevicff734982015-08-24 12:58:55 +0000527void MipsAssembler::StoreSToOffset(FRegister reg, Register base, int32_t offset) {
jeffhao7fbee072012-08-24 17:56:54 -0700528 Swc1(reg, base, offset);
529}
530
531void MipsAssembler::StoreDToOffset(DRegister reg, Register base, int32_t offset) {
532 Sdc1(reg, base, offset);
533}
534
David Srbeckydd973932015-04-07 20:29:48 +0100535static dwarf::Reg DWARFReg(Register reg) {
536 return dwarf::Reg::MipsCore(static_cast<int>(reg));
537}
538
Ian Rogers790a6b72014-04-01 10:36:00 -0700539constexpr size_t kFramePointerSize = 4;
540
jeffhao7fbee072012-08-24 17:56:54 -0700541void MipsAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
542 const std::vector<ManagedRegister>& callee_save_regs,
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700543 const ManagedRegisterEntrySpills& entry_spills) {
jeffhao7fbee072012-08-24 17:56:54 -0700544 CHECK_ALIGNED(frame_size, kStackAlignment);
545
546 // Increase frame to required size.
547 IncreaseFrameSize(frame_size);
548
549 // Push callee saves and return address
Ian Rogers790a6b72014-04-01 10:36:00 -0700550 int stack_offset = frame_size - kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700551 StoreToOffset(kStoreWord, RA, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100552 cfi_.RelOffset(DWARFReg(RA), stack_offset);
jeffhao7fbee072012-08-24 17:56:54 -0700553 for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700554 stack_offset -= kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700555 Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
556 StoreToOffset(kStoreWord, reg, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100557 cfi_.RelOffset(DWARFReg(reg), stack_offset);
jeffhao7fbee072012-08-24 17:56:54 -0700558 }
559
560 // Write out Method*.
561 StoreToOffset(kStoreWord, method_reg.AsMips().AsCoreRegister(), SP, 0);
562
563 // Write out entry spills.
Goran Jakovljevicff734982015-08-24 12:58:55 +0000564 int32_t offset = frame_size + kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700565 for (size_t i = 0; i < entry_spills.size(); ++i) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000566 MipsManagedRegister reg = entry_spills.at(i).AsMips();
567 if (reg.IsNoRegister()) {
568 ManagedRegisterSpill spill = entry_spills.at(i);
569 offset += spill.getSize();
570 } else if (reg.IsCoreRegister()) {
571 StoreToOffset(kStoreWord, reg.AsCoreRegister(), SP, offset);
572 offset += 4;
573 } else if (reg.IsFRegister()) {
574 StoreSToOffset(reg.AsFRegister(), SP, offset);
575 offset += 4;
576 } else if (reg.IsDRegister()) {
577 StoreDToOffset(reg.AsDRegister(), SP, offset);
578 offset += 8;
579 }
jeffhao7fbee072012-08-24 17:56:54 -0700580 }
581}
582
583void MipsAssembler::RemoveFrame(size_t frame_size,
584 const std::vector<ManagedRegister>& callee_save_regs) {
585 CHECK_ALIGNED(frame_size, kStackAlignment);
David Srbeckydd973932015-04-07 20:29:48 +0100586 cfi_.RememberState();
jeffhao7fbee072012-08-24 17:56:54 -0700587
588 // Pop callee saves and return address
Ian Rogers790a6b72014-04-01 10:36:00 -0700589 int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700590 for (size_t i = 0; i < callee_save_regs.size(); ++i) {
591 Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
592 LoadFromOffset(kLoadWord, reg, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100593 cfi_.Restore(DWARFReg(reg));
Ian Rogers790a6b72014-04-01 10:36:00 -0700594 stack_offset += kFramePointerSize;
jeffhao7fbee072012-08-24 17:56:54 -0700595 }
596 LoadFromOffset(kLoadWord, RA, SP, stack_offset);
David Srbeckydd973932015-04-07 20:29:48 +0100597 cfi_.Restore(DWARFReg(RA));
jeffhao7fbee072012-08-24 17:56:54 -0700598
599 // Decrease frame to required size.
600 DecreaseFrameSize(frame_size);
jeffhao07030602012-09-26 14:33:14 -0700601
602 // Then jump to the return address.
603 Jr(RA);
David Srbeckydd973932015-04-07 20:29:48 +0100604
605 // The CFI should be restored for any code that follows the exit block.
606 cfi_.RestoreState();
607 cfi_.DefCFAOffset(frame_size);
jeffhao7fbee072012-08-24 17:56:54 -0700608}
609
610void MipsAssembler::IncreaseFrameSize(size_t adjust) {
611 CHECK_ALIGNED(adjust, kStackAlignment);
612 AddConstant(SP, SP, -adjust);
David Srbeckydd973932015-04-07 20:29:48 +0100613 cfi_.AdjustCFAOffset(adjust);
jeffhao7fbee072012-08-24 17:56:54 -0700614}
615
616void MipsAssembler::DecreaseFrameSize(size_t adjust) {
617 CHECK_ALIGNED(adjust, kStackAlignment);
618 AddConstant(SP, SP, adjust);
David Srbeckydd973932015-04-07 20:29:48 +0100619 cfi_.AdjustCFAOffset(-adjust);
jeffhao7fbee072012-08-24 17:56:54 -0700620}
621
622void MipsAssembler::Store(FrameOffset dest, ManagedRegister msrc, size_t size) {
623 MipsManagedRegister src = msrc.AsMips();
624 if (src.IsNoRegister()) {
625 CHECK_EQ(0u, size);
626 } else if (src.IsCoreRegister()) {
627 CHECK_EQ(4u, size);
628 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
629 } else if (src.IsRegisterPair()) {
630 CHECK_EQ(8u, size);
631 StoreToOffset(kStoreWord, src.AsRegisterPairLow(), SP, dest.Int32Value());
632 StoreToOffset(kStoreWord, src.AsRegisterPairHigh(),
633 SP, dest.Int32Value() + 4);
634 } else if (src.IsFRegister()) {
Goran Jakovljevicff734982015-08-24 12:58:55 +0000635 StoreSToOffset(src.AsFRegister(), SP, dest.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700636 } else {
637 CHECK(src.IsDRegister());
638 StoreDToOffset(src.AsDRegister(), SP, dest.Int32Value());
639 }
640}
641
642void MipsAssembler::StoreRef(FrameOffset dest, ManagedRegister msrc) {
643 MipsManagedRegister src = msrc.AsMips();
644 CHECK(src.IsCoreRegister());
645 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
646}
647
648void MipsAssembler::StoreRawPtr(FrameOffset dest, ManagedRegister msrc) {
649 MipsManagedRegister src = msrc.AsMips();
650 CHECK(src.IsCoreRegister());
651 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
652}
653
654void MipsAssembler::StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
655 ManagedRegister mscratch) {
656 MipsManagedRegister scratch = mscratch.AsMips();
657 CHECK(scratch.IsCoreRegister()) << scratch;
658 LoadImmediate(scratch.AsCoreRegister(), imm);
659 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
660}
661
Ian Rogersdd7624d2014-03-14 17:43:00 -0700662void MipsAssembler::StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm,
jeffhao7fbee072012-08-24 17:56:54 -0700663 ManagedRegister mscratch) {
664 MipsManagedRegister scratch = mscratch.AsMips();
665 CHECK(scratch.IsCoreRegister()) << scratch;
666 LoadImmediate(scratch.AsCoreRegister(), imm);
667 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), S1, dest.Int32Value());
668}
669
Ian Rogersdd7624d2014-03-14 17:43:00 -0700670void MipsAssembler::StoreStackOffsetToThread32(ThreadOffset<4> thr_offs,
jeffhao7fbee072012-08-24 17:56:54 -0700671 FrameOffset fr_offs,
672 ManagedRegister mscratch) {
673 MipsManagedRegister scratch = mscratch.AsMips();
674 CHECK(scratch.IsCoreRegister()) << scratch;
675 AddConstant(scratch.AsCoreRegister(), SP, fr_offs.Int32Value());
676 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
677 S1, thr_offs.Int32Value());
678}
679
Ian Rogersdd7624d2014-03-14 17:43:00 -0700680void MipsAssembler::StoreStackPointerToThread32(ThreadOffset<4> thr_offs) {
jeffhao7fbee072012-08-24 17:56:54 -0700681 StoreToOffset(kStoreWord, SP, S1, thr_offs.Int32Value());
682}
683
684void MipsAssembler::StoreSpanning(FrameOffset dest, ManagedRegister msrc,
685 FrameOffset in_off, ManagedRegister mscratch) {
686 MipsManagedRegister src = msrc.AsMips();
687 MipsManagedRegister scratch = mscratch.AsMips();
688 StoreToOffset(kStoreWord, src.AsCoreRegister(), SP, dest.Int32Value());
689 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, in_off.Int32Value());
690 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
691}
692
693void MipsAssembler::Load(ManagedRegister mdest, FrameOffset src, size_t size) {
694 return EmitLoad(mdest, SP, src.Int32Value(), size);
695}
696
Ian Rogersdd7624d2014-03-14 17:43:00 -0700697void MipsAssembler::LoadFromThread32(ManagedRegister mdest, ThreadOffset<4> src, size_t size) {
jeffhao7fbee072012-08-24 17:56:54 -0700698 return EmitLoad(mdest, S1, src.Int32Value(), size);
699}
700
701void MipsAssembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
702 MipsManagedRegister dest = mdest.AsMips();
703 CHECK(dest.IsCoreRegister());
704 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
705}
706
Mathieu Chartiere401d142015-04-22 13:56:20 -0700707void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
Roland Levillain4d027112015-07-01 15:41:14 +0100708 bool unpoison_reference) {
jeffhao7fbee072012-08-24 17:56:54 -0700709 MipsManagedRegister dest = mdest.AsMips();
710 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
711 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
712 base.AsMips().AsCoreRegister(), offs.Int32Value());
Roland Levillain4d027112015-07-01 15:41:14 +0100713 if (kPoisonHeapReferences && unpoison_reference) {
Hiroshi Yamauchie63a7452014-02-27 14:44:36 -0800714 Subu(dest.AsCoreRegister(), ZERO, dest.AsCoreRegister());
715 }
jeffhao7fbee072012-08-24 17:56:54 -0700716}
717
718void MipsAssembler::LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
719 Offset offs) {
720 MipsManagedRegister dest = mdest.AsMips();
721 CHECK(dest.IsCoreRegister() && dest.IsCoreRegister()) << dest;
722 LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
723 base.AsMips().AsCoreRegister(), offs.Int32Value());
724}
725
Ian Rogersdd7624d2014-03-14 17:43:00 -0700726void MipsAssembler::LoadRawPtrFromThread32(ManagedRegister mdest,
727 ThreadOffset<4> offs) {
jeffhao7fbee072012-08-24 17:56:54 -0700728 MipsManagedRegister dest = mdest.AsMips();
729 CHECK(dest.IsCoreRegister());
730 LoadFromOffset(kLoadWord, dest.AsCoreRegister(), S1, offs.Int32Value());
731}
732
733void MipsAssembler::SignExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
734 UNIMPLEMENTED(FATAL) << "no sign extension necessary for mips";
735}
736
737void MipsAssembler::ZeroExtend(ManagedRegister /*mreg*/, size_t /*size*/) {
738 UNIMPLEMENTED(FATAL) << "no zero extension necessary for mips";
739}
740
741void MipsAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t /*size*/) {
742 MipsManagedRegister dest = mdest.AsMips();
743 MipsManagedRegister src = msrc.AsMips();
744 if (!dest.Equals(src)) {
745 if (dest.IsCoreRegister()) {
746 CHECK(src.IsCoreRegister()) << src;
747 Move(dest.AsCoreRegister(), src.AsCoreRegister());
748 } else if (dest.IsFRegister()) {
749 CHECK(src.IsFRegister()) << src;
750 MovS(dest.AsFRegister(), src.AsFRegister());
751 } else if (dest.IsDRegister()) {
752 CHECK(src.IsDRegister()) << src;
753 MovD(dest.AsDRegister(), src.AsDRegister());
754 } else {
755 CHECK(dest.IsRegisterPair()) << dest;
756 CHECK(src.IsRegisterPair()) << src;
757 // Ensure that the first move doesn't clobber the input of the second
758 if (src.AsRegisterPairHigh() != dest.AsRegisterPairLow()) {
759 Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
760 Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
761 } else {
762 Move(dest.AsRegisterPairHigh(), src.AsRegisterPairHigh());
763 Move(dest.AsRegisterPairLow(), src.AsRegisterPairLow());
764 }
765 }
766 }
767}
768
769void MipsAssembler::CopyRef(FrameOffset dest, FrameOffset src,
770 ManagedRegister mscratch) {
771 MipsManagedRegister scratch = mscratch.AsMips();
772 CHECK(scratch.IsCoreRegister()) << scratch;
773 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
774 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
775}
776
Ian Rogersdd7624d2014-03-14 17:43:00 -0700777void MipsAssembler::CopyRawPtrFromThread32(FrameOffset fr_offs,
778 ThreadOffset<4> thr_offs,
jeffhao7fbee072012-08-24 17:56:54 -0700779 ManagedRegister mscratch) {
780 MipsManagedRegister scratch = mscratch.AsMips();
781 CHECK(scratch.IsCoreRegister()) << scratch;
782 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
783 S1, thr_offs.Int32Value());
784 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
785 SP, fr_offs.Int32Value());
786}
787
Ian Rogersdd7624d2014-03-14 17:43:00 -0700788void MipsAssembler::CopyRawPtrToThread32(ThreadOffset<4> thr_offs,
jeffhao7fbee072012-08-24 17:56:54 -0700789 FrameOffset fr_offs,
790 ManagedRegister mscratch) {
791 MipsManagedRegister scratch = mscratch.AsMips();
792 CHECK(scratch.IsCoreRegister()) << scratch;
793 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
794 SP, fr_offs.Int32Value());
795 StoreToOffset(kStoreWord, scratch.AsCoreRegister(),
796 S1, thr_offs.Int32Value());
797}
798
799void MipsAssembler::Copy(FrameOffset dest, FrameOffset src,
800 ManagedRegister mscratch, size_t size) {
801 MipsManagedRegister scratch = mscratch.AsMips();
802 CHECK(scratch.IsCoreRegister()) << scratch;
803 CHECK(size == 4 || size == 8) << size;
804 if (size == 4) {
805 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
806 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
807 } else if (size == 8) {
808 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value());
809 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
810 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP, src.Int32Value() + 4);
811 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value() + 4);
812 }
813}
814
815void MipsAssembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
816 ManagedRegister mscratch, size_t size) {
817 Register scratch = mscratch.AsMips().AsCoreRegister();
818 CHECK_EQ(size, 4u);
819 LoadFromOffset(kLoadWord, scratch, src_base.AsMips().AsCoreRegister(), src_offset.Int32Value());
820 StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value());
821}
822
823void MipsAssembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
824 ManagedRegister mscratch, size_t size) {
825 Register scratch = mscratch.AsMips().AsCoreRegister();
826 CHECK_EQ(size, 4u);
827 LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value());
828 StoreToOffset(kStoreWord, scratch, dest_base.AsMips().AsCoreRegister(), dest_offset.Int32Value());
829}
830
831void MipsAssembler::Copy(FrameOffset /*dest*/, FrameOffset /*src_base*/, Offset /*src_offset*/,
832 ManagedRegister /*mscratch*/, size_t /*size*/) {
Ian Rogers468532e2013-08-05 10:56:33 -0700833 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700834}
835
836void MipsAssembler::Copy(ManagedRegister dest, Offset dest_offset,
837 ManagedRegister src, Offset src_offset,
838 ManagedRegister mscratch, size_t size) {
839 CHECK_EQ(size, 4u);
840 Register scratch = mscratch.AsMips().AsCoreRegister();
841 LoadFromOffset(kLoadWord, scratch, src.AsMips().AsCoreRegister(), src_offset.Int32Value());
842 StoreToOffset(kStoreWord, scratch, dest.AsMips().AsCoreRegister(), dest_offset.Int32Value());
843}
844
845void MipsAssembler::Copy(FrameOffset /*dest*/, Offset /*dest_offset*/, FrameOffset /*src*/, Offset /*src_offset*/,
846 ManagedRegister /*mscratch*/, size_t /*size*/) {
Ian Rogers468532e2013-08-05 10:56:33 -0700847 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700848}
849
850void MipsAssembler::MemoryBarrier(ManagedRegister) {
Ian Rogers468532e2013-08-05 10:56:33 -0700851 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700852}
853
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700854void MipsAssembler::CreateHandleScopeEntry(ManagedRegister mout_reg,
855 FrameOffset handle_scope_offset,
jeffhao7fbee072012-08-24 17:56:54 -0700856 ManagedRegister min_reg, bool null_allowed) {
857 MipsManagedRegister out_reg = mout_reg.AsMips();
858 MipsManagedRegister in_reg = min_reg.AsMips();
859 CHECK(in_reg.IsNoRegister() || in_reg.IsCoreRegister()) << in_reg;
860 CHECK(out_reg.IsCoreRegister()) << out_reg;
861 if (null_allowed) {
862 Label null_arg;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700863 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
864 // the address in the handle scope holding the reference.
jeffhao7fbee072012-08-24 17:56:54 -0700865 // e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
866 if (in_reg.IsNoRegister()) {
867 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700868 SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700869 in_reg = out_reg;
870 }
871 if (!out_reg.Equals(in_reg)) {
872 LoadImmediate(out_reg.AsCoreRegister(), 0);
873 }
874 EmitBranch(in_reg.AsCoreRegister(), ZERO, &null_arg, true);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700875 AddConstant(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700876 Bind(&null_arg, false);
877 } else {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700878 AddConstant(out_reg.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700879 }
880}
881
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700882void MipsAssembler::CreateHandleScopeEntry(FrameOffset out_off,
883 FrameOffset handle_scope_offset,
jeffhao7fbee072012-08-24 17:56:54 -0700884 ManagedRegister mscratch,
885 bool null_allowed) {
886 MipsManagedRegister scratch = mscratch.AsMips();
887 CHECK(scratch.IsCoreRegister()) << scratch;
888 if (null_allowed) {
889 Label null_arg;
890 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(), SP,
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700891 handle_scope_offset.Int32Value());
892 // Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
893 // the address in the handle scope holding the reference.
894 // e.g. scratch = (scratch == 0) ? 0 : (SP+handle_scope_offset)
jeffhao7fbee072012-08-24 17:56:54 -0700895 EmitBranch(scratch.AsCoreRegister(), ZERO, &null_arg, true);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700896 AddConstant(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700897 Bind(&null_arg, false);
898 } else {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700899 AddConstant(scratch.AsCoreRegister(), SP, handle_scope_offset.Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700900 }
901 StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, out_off.Int32Value());
902}
903
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700904// Given a handle scope entry, load the associated reference.
905void MipsAssembler::LoadReferenceFromHandleScope(ManagedRegister mout_reg,
jeffhao7fbee072012-08-24 17:56:54 -0700906 ManagedRegister min_reg) {
907 MipsManagedRegister out_reg = mout_reg.AsMips();
908 MipsManagedRegister in_reg = min_reg.AsMips();
909 CHECK(out_reg.IsCoreRegister()) << out_reg;
910 CHECK(in_reg.IsCoreRegister()) << in_reg;
911 Label null_arg;
912 if (!out_reg.Equals(in_reg)) {
913 LoadImmediate(out_reg.AsCoreRegister(), 0);
914 }
915 EmitBranch(in_reg.AsCoreRegister(), ZERO, &null_arg, true);
916 LoadFromOffset(kLoadWord, out_reg.AsCoreRegister(),
917 in_reg.AsCoreRegister(), 0);
918 Bind(&null_arg, false);
919}
920
921void MipsAssembler::VerifyObject(ManagedRegister /*src*/, bool /*could_be_null*/) {
922 // TODO: not validating references
923}
924
925void MipsAssembler::VerifyObject(FrameOffset /*src*/, bool /*could_be_null*/) {
926 // TODO: not validating references
927}
928
929void MipsAssembler::Call(ManagedRegister mbase, Offset offset, ManagedRegister mscratch) {
930 MipsManagedRegister base = mbase.AsMips();
931 MipsManagedRegister scratch = mscratch.AsMips();
932 CHECK(base.IsCoreRegister()) << base;
933 CHECK(scratch.IsCoreRegister()) << scratch;
934 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
935 base.AsCoreRegister(), offset.Int32Value());
936 Jalr(scratch.AsCoreRegister());
937 // TODO: place reference map on call
938}
939
940void MipsAssembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
941 MipsManagedRegister scratch = mscratch.AsMips();
942 CHECK(scratch.IsCoreRegister()) << scratch;
943 // Call *(*(SP + base) + offset)
944 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
945 SP, base.Int32Value());
946 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
947 scratch.AsCoreRegister(), offset.Int32Value());
948 Jalr(scratch.AsCoreRegister());
949 // TODO: place reference map on call
950}
951
Ian Rogersdd7624d2014-03-14 17:43:00 -0700952void MipsAssembler::CallFromThread32(ThreadOffset<4> /*offset*/, ManagedRegister /*mscratch*/) {
Ian Rogers468532e2013-08-05 10:56:33 -0700953 UNIMPLEMENTED(FATAL) << "no mips implementation";
jeffhao7fbee072012-08-24 17:56:54 -0700954}
955
956void MipsAssembler::GetCurrentThread(ManagedRegister tr) {
957 Move(tr.AsMips().AsCoreRegister(), S1);
958}
959
960void MipsAssembler::GetCurrentThread(FrameOffset offset,
961 ManagedRegister /*mscratch*/) {
962 StoreToOffset(kStoreWord, S1, SP, offset.Int32Value());
963}
964
jeffhao7fbee072012-08-24 17:56:54 -0700965void MipsAssembler::ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) {
966 MipsManagedRegister scratch = mscratch.AsMips();
967 MipsExceptionSlowPath* slow = new MipsExceptionSlowPath(scratch, stack_adjust);
968 buffer_.EnqueueSlowPath(slow);
969 LoadFromOffset(kLoadWord, scratch.AsCoreRegister(),
Ian Rogersdd7624d2014-03-14 17:43:00 -0700970 S1, Thread::ExceptionOffset<4>().Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700971 EmitBranch(scratch.AsCoreRegister(), ZERO, slow->Entry(), false);
972}
973
974void MipsExceptionSlowPath::Emit(Assembler* sasm) {
975 MipsAssembler* sp_asm = down_cast<MipsAssembler*>(sasm);
976#define __ sp_asm->
977 __ Bind(&entry_, false);
978 if (stack_adjust_ != 0) { // Fix up the frame.
979 __ DecreaseFrameSize(stack_adjust_);
980 }
981 // Pass exception object as argument
982 // Don't care about preserving A0 as this call won't return
983 __ Move(A0, scratch_.AsCoreRegister());
984 // Set up call to Thread::Current()->pDeliverException
Ian Rogersdd7624d2014-03-14 17:43:00 -0700985 __ LoadFromOffset(kLoadWord, T9, S1, QUICK_ENTRYPOINT_OFFSET(4, pDeliverException).Int32Value());
jeffhao7fbee072012-08-24 17:56:54 -0700986 __ Jr(T9);
987 // Call never returns
988 __ Break();
989#undef __
990}
991
992} // namespace mips
993} // namespace art