blob: 2262af49b33273d8c8a4f151599e1bcc3af224a9 [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
Ian Rogers166db042013-07-26 12:05:57 -070017#ifndef ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
18#define ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
jeffhao7fbee072012-08-24 17:56:54 -070019
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020020#include <utility>
jeffhao7fbee072012-08-24 17:56:54 -070021#include <vector>
Elliott Hughes76160052012-12-12 16:31:20 -080022
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020023#include "arch/mips/instruction_set_features_mips.h"
Elliott Hughes76160052012-12-12 16:31:20 -080024#include "base/macros.h"
jeffhao7fbee072012-08-24 17:56:54 -070025#include "constants_mips.h"
26#include "globals.h"
27#include "managed_register_mips.h"
jeffhao7fbee072012-08-24 17:56:54 -070028#include "offsets.h"
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020029#include "utils/assembler.h"
30#include "utils/label.h"
jeffhao7fbee072012-08-24 17:56:54 -070031
32namespace art {
33namespace mips {
jeffhao7fbee072012-08-24 17:56:54 -070034
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020035static constexpr size_t kMipsWordSize = 4;
36static constexpr size_t kMipsDoublewordSize = 8;
37
jeffhao7fbee072012-08-24 17:56:54 -070038enum LoadOperandType {
39 kLoadSignedByte,
40 kLoadUnsignedByte,
41 kLoadSignedHalfword,
42 kLoadUnsignedHalfword,
43 kLoadWord,
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020044 kLoadDoubleword
jeffhao7fbee072012-08-24 17:56:54 -070045};
46
47enum StoreOperandType {
48 kStoreByte,
49 kStoreHalfword,
50 kStoreWord,
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020051 kStoreDoubleword
52};
53
54class MipsLabel : public Label {
55 public:
56 MipsLabel() : prev_branch_id_plus_one_(0) {}
57
58 MipsLabel(MipsLabel&& src)
59 : Label(std::move(src)), prev_branch_id_plus_one_(src.prev_branch_id_plus_one_) {}
60
61 private:
62 uint32_t prev_branch_id_plus_one_; // To get distance from preceding branch, if any.
63
64 friend class MipsAssembler;
65 DISALLOW_COPY_AND_ASSIGN(MipsLabel);
66};
67
68// Slowpath entered when Thread::Current()->_exception is non-null.
69class MipsExceptionSlowPath {
70 public:
71 explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
72 : scratch_(scratch), stack_adjust_(stack_adjust) {}
73
74 MipsExceptionSlowPath(MipsExceptionSlowPath&& src)
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -080075 : scratch_(src.scratch_),
76 stack_adjust_(src.stack_adjust_),
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020077 exception_entry_(std::move(src.exception_entry_)) {}
78
79 private:
80 MipsLabel* Entry() { return &exception_entry_; }
81 const MipsManagedRegister scratch_;
82 const size_t stack_adjust_;
83 MipsLabel exception_entry_;
84
85 friend class MipsAssembler;
86 DISALLOW_COPY_AND_ASSIGN(MipsExceptionSlowPath);
jeffhao7fbee072012-08-24 17:56:54 -070087};
88
Ian Rogersdd7624d2014-03-14 17:43:00 -070089class MipsAssembler FINAL : public Assembler {
jeffhao7fbee072012-08-24 17:56:54 -070090 public:
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +020091 explicit MipsAssembler(const MipsInstructionSetFeatures* instruction_set_features = nullptr)
92 : overwriting_(false),
93 overwrite_location_(0),
94 last_position_adjustment_(0),
95 last_old_position_(0),
96 last_branch_id_(0),
Vladimir Marko10ef6942015-10-22 15:25:54 +010097 isa_features_(instruction_set_features) {
98 cfi().DelayEmittingAdvancePCs();
99 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200100
101 virtual ~MipsAssembler() {
102 for (auto& branch : branches_) {
103 CHECK(branch.IsResolved());
104 }
105 }
jeffhao7fbee072012-08-24 17:56:54 -0700106
107 // Emit Machine Instructions.
jeffhao7fbee072012-08-24 17:56:54 -0700108 void Addu(Register rd, Register rs, Register rt);
jeffhao7fbee072012-08-24 17:56:54 -0700109 void Addiu(Register rt, Register rs, uint16_t imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700110 void Subu(Register rd, Register rs, Register rt);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200111
112 void MultR2(Register rs, Register rt); // R2
113 void MultuR2(Register rs, Register rt); // R2
114 void DivR2(Register rs, Register rt); // R2
115 void DivuR2(Register rs, Register rt); // R2
116 void MulR2(Register rd, Register rs, Register rt); // R2
117 void DivR2(Register rd, Register rs, Register rt); // R2
118 void ModR2(Register rd, Register rs, Register rt); // R2
119 void DivuR2(Register rd, Register rs, Register rt); // R2
120 void ModuR2(Register rd, Register rs, Register rt); // R2
121 void MulR6(Register rd, Register rs, Register rt); // R6
Alexey Frunze7e99e052015-11-24 19:28:01 -0800122 void MuhR6(Register rd, Register rs, Register rt); // R6
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200123 void MuhuR6(Register rd, Register rs, Register rt); // R6
124 void DivR6(Register rd, Register rs, Register rt); // R6
125 void ModR6(Register rd, Register rs, Register rt); // R6
126 void DivuR6(Register rd, Register rs, Register rt); // R6
127 void ModuR6(Register rd, Register rs, Register rt); // R6
jeffhao7fbee072012-08-24 17:56:54 -0700128
129 void And(Register rd, Register rs, Register rt);
130 void Andi(Register rt, Register rs, uint16_t imm16);
131 void Or(Register rd, Register rs, Register rt);
132 void Ori(Register rt, Register rs, uint16_t imm16);
133 void Xor(Register rd, Register rs, Register rt);
134 void Xori(Register rt, Register rs, uint16_t imm16);
135 void Nor(Register rd, Register rs, Register rt);
136
Chris Larsene3845472015-11-18 12:27:15 -0800137 void Movz(Register rd, Register rs, Register rt); // R2
138 void Movn(Register rd, Register rs, Register rt); // R2
139 void Seleqz(Register rd, Register rs, Register rt); // R6
140 void Selnez(Register rd, Register rs, Register rt); // R6
141 void ClzR6(Register rd, Register rs);
142 void ClzR2(Register rd, Register rs);
143 void CloR6(Register rd, Register rs);
144 void CloR2(Register rd, Register rs);
145
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200146 void Seb(Register rd, Register rt); // R2+
147 void Seh(Register rd, Register rt); // R2+
Chris Larsen3f8bf652015-10-28 10:08:56 -0700148 void Wsbh(Register rd, Register rt); // R2+
Chris Larsen70014c82015-11-18 12:26:08 -0800149 void Bitswap(Register rd, Register rt); // R6
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200150
151 void Sll(Register rd, Register rt, int shamt);
152 void Srl(Register rd, Register rt, int shamt);
Chris Larsen3f8bf652015-10-28 10:08:56 -0700153 void Rotr(Register rd, Register rt, int shamt); // R2+
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200154 void Sra(Register rd, Register rt, int shamt);
155 void Sllv(Register rd, Register rt, Register rs);
156 void Srlv(Register rd, Register rt, Register rs);
Chris Larsene16ce5a2015-11-18 12:30:20 -0800157 void Rotrv(Register rd, Register rt, Register rs); // R2+
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200158 void Srav(Register rd, Register rt, Register rs);
Alexey Frunze5c7aed32015-11-25 19:41:54 -0800159 void Ext(Register rd, Register rt, int pos, int size); // R2+
160 void Ins(Register rd, Register rt, int pos, int size); // R2+
jeffhao7fbee072012-08-24 17:56:54 -0700161
162 void Lb(Register rt, Register rs, uint16_t imm16);
163 void Lh(Register rt, Register rs, uint16_t imm16);
164 void Lw(Register rt, Register rs, uint16_t imm16);
Chris Larsen3acee732015-11-18 13:31:08 -0800165 void Lwl(Register rt, Register rs, uint16_t imm16);
166 void Lwr(Register rt, Register rs, uint16_t imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700167 void Lbu(Register rt, Register rs, uint16_t imm16);
168 void Lhu(Register rt, Register rs, uint16_t imm16);
169 void Lui(Register rt, uint16_t imm16);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200170 void Sync(uint32_t stype);
171 void Mfhi(Register rd); // R2
172 void Mflo(Register rd); // R2
jeffhao7fbee072012-08-24 17:56:54 -0700173
174 void Sb(Register rt, Register rs, uint16_t imm16);
175 void Sh(Register rt, Register rs, uint16_t imm16);
176 void Sw(Register rt, Register rs, uint16_t imm16);
Chris Larsen3acee732015-11-18 13:31:08 -0800177 void Swl(Register rt, Register rs, uint16_t imm16);
178 void Swr(Register rt, Register rs, uint16_t imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700179
180 void Slt(Register rd, Register rs, Register rt);
181 void Sltu(Register rd, Register rs, Register rt);
182 void Slti(Register rt, Register rs, uint16_t imm16);
183 void Sltiu(Register rt, Register rs, uint16_t imm16);
184
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200185 void B(uint16_t imm16);
186 void Beq(Register rs, Register rt, uint16_t imm16);
187 void Bne(Register rs, Register rt, uint16_t imm16);
188 void Beqz(Register rt, uint16_t imm16);
189 void Bnez(Register rt, uint16_t imm16);
190 void Bltz(Register rt, uint16_t imm16);
191 void Bgez(Register rt, uint16_t imm16);
192 void Blez(Register rt, uint16_t imm16);
193 void Bgtz(Register rt, uint16_t imm16);
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800194 void Bc1f(int cc, uint16_t imm16); // R2
195 void Bc1t(int cc, uint16_t imm16); // R2
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200196 void J(uint32_t addr26);
197 void Jal(uint32_t addr26);
198 void Jalr(Register rd, Register rs);
jeffhao7fbee072012-08-24 17:56:54 -0700199 void Jalr(Register rs);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200200 void Jr(Register rs);
201 void Nal();
202 void Auipc(Register rs, uint16_t imm16); // R6
203 void Addiupc(Register rs, uint32_t imm19); // R6
204 void Bc(uint32_t imm26); // R6
205 void Jic(Register rt, uint16_t imm16); // R6
206 void Jialc(Register rt, uint16_t imm16); // R6
207 void Bltc(Register rs, Register rt, uint16_t imm16); // R6
208 void Bltzc(Register rt, uint16_t imm16); // R6
209 void Bgtzc(Register rt, uint16_t imm16); // R6
210 void Bgec(Register rs, Register rt, uint16_t imm16); // R6
211 void Bgezc(Register rt, uint16_t imm16); // R6
212 void Blezc(Register rt, uint16_t imm16); // R6
213 void Bltuc(Register rs, Register rt, uint16_t imm16); // R6
214 void Bgeuc(Register rs, Register rt, uint16_t imm16); // R6
215 void Beqc(Register rs, Register rt, uint16_t imm16); // R6
216 void Bnec(Register rs, Register rt, uint16_t imm16); // R6
217 void Beqzc(Register rs, uint32_t imm21); // R6
218 void Bnezc(Register rs, uint32_t imm21); // R6
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800219 void Bc1eqz(FRegister ft, uint16_t imm16); // R6
220 void Bc1nez(FRegister ft, uint16_t imm16); // R6
jeffhao7fbee072012-08-24 17:56:54 -0700221
222 void AddS(FRegister fd, FRegister fs, FRegister ft);
223 void SubS(FRegister fd, FRegister fs, FRegister ft);
224 void MulS(FRegister fd, FRegister fs, FRegister ft);
225 void DivS(FRegister fd, FRegister fs, FRegister ft);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200226 void AddD(FRegister fd, FRegister fs, FRegister ft);
227 void SubD(FRegister fd, FRegister fs, FRegister ft);
228 void MulD(FRegister fd, FRegister fs, FRegister ft);
229 void DivD(FRegister fd, FRegister fs, FRegister ft);
jeffhao7fbee072012-08-24 17:56:54 -0700230 void MovS(FRegister fd, FRegister fs);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200231 void MovD(FRegister fd, FRegister fs);
232 void NegS(FRegister fd, FRegister fs);
233 void NegD(FRegister fd, FRegister fs);
234
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800235 void CunS(int cc, FRegister fs, FRegister ft); // R2
236 void CeqS(int cc, FRegister fs, FRegister ft); // R2
237 void CueqS(int cc, FRegister fs, FRegister ft); // R2
238 void ColtS(int cc, FRegister fs, FRegister ft); // R2
239 void CultS(int cc, FRegister fs, FRegister ft); // R2
240 void ColeS(int cc, FRegister fs, FRegister ft); // R2
241 void CuleS(int cc, FRegister fs, FRegister ft); // R2
242 void CunD(int cc, FRegister fs, FRegister ft); // R2
243 void CeqD(int cc, FRegister fs, FRegister ft); // R2
244 void CueqD(int cc, FRegister fs, FRegister ft); // R2
245 void ColtD(int cc, FRegister fs, FRegister ft); // R2
246 void CultD(int cc, FRegister fs, FRegister ft); // R2
247 void ColeD(int cc, FRegister fs, FRegister ft); // R2
248 void CuleD(int cc, FRegister fs, FRegister ft); // R2
249 void CmpUnS(FRegister fd, FRegister fs, FRegister ft); // R6
250 void CmpEqS(FRegister fd, FRegister fs, FRegister ft); // R6
251 void CmpUeqS(FRegister fd, FRegister fs, FRegister ft); // R6
252 void CmpLtS(FRegister fd, FRegister fs, FRegister ft); // R6
253 void CmpUltS(FRegister fd, FRegister fs, FRegister ft); // R6
254 void CmpLeS(FRegister fd, FRegister fs, FRegister ft); // R6
255 void CmpUleS(FRegister fd, FRegister fs, FRegister ft); // R6
256 void CmpOrS(FRegister fd, FRegister fs, FRegister ft); // R6
257 void CmpUneS(FRegister fd, FRegister fs, FRegister ft); // R6
258 void CmpNeS(FRegister fd, FRegister fs, FRegister ft); // R6
259 void CmpUnD(FRegister fd, FRegister fs, FRegister ft); // R6
260 void CmpEqD(FRegister fd, FRegister fs, FRegister ft); // R6
261 void CmpUeqD(FRegister fd, FRegister fs, FRegister ft); // R6
262 void CmpLtD(FRegister fd, FRegister fs, FRegister ft); // R6
263 void CmpUltD(FRegister fd, FRegister fs, FRegister ft); // R6
264 void CmpLeD(FRegister fd, FRegister fs, FRegister ft); // R6
265 void CmpUleD(FRegister fd, FRegister fs, FRegister ft); // R6
266 void CmpOrD(FRegister fd, FRegister fs, FRegister ft); // R6
267 void CmpUneD(FRegister fd, FRegister fs, FRegister ft); // R6
268 void CmpNeD(FRegister fd, FRegister fs, FRegister ft); // R6
269 void Movf(Register rd, Register rs, int cc); // R2
270 void Movt(Register rd, Register rs, int cc); // R2
271
Alexey Frunzebaf60b72015-12-22 15:15:03 -0800272 void TruncLS(FRegister fd, FRegister fs); // R2+, FR=1
273 void TruncLD(FRegister fd, FRegister fs); // R2+, FR=1
274 void TruncWS(FRegister fd, FRegister fs);
275 void TruncWD(FRegister fd, FRegister fs);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200276 void Cvtsw(FRegister fd, FRegister fs);
277 void Cvtdw(FRegister fd, FRegister fs);
278 void Cvtsd(FRegister fd, FRegister fs);
279 void Cvtds(FRegister fd, FRegister fs);
Alexey Frunzebaf60b72015-12-22 15:15:03 -0800280 void Cvtsl(FRegister fd, FRegister fs); // R2+, FR=1
281 void Cvtdl(FRegister fd, FRegister fs); // R2+, FR=1
jeffhao7fbee072012-08-24 17:56:54 -0700282
283 void Mfc1(Register rt, FRegister fs);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200284 void Mtc1(Register rt, FRegister fs);
285 void Mfhc1(Register rt, FRegister fs);
286 void Mthc1(Register rt, FRegister fs);
Alexey Frunzebb9863a2016-01-11 15:51:16 -0800287 void MoveFromFpuHigh(Register rt, FRegister fs);
288 void MoveToFpuHigh(Register rt, FRegister fs);
jeffhao7fbee072012-08-24 17:56:54 -0700289 void Lwc1(FRegister ft, Register rs, uint16_t imm16);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200290 void Ldc1(FRegister ft, Register rs, uint16_t imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700291 void Swc1(FRegister ft, Register rs, uint16_t imm16);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200292 void Sdc1(FRegister ft, Register rs, uint16_t imm16);
jeffhao7fbee072012-08-24 17:56:54 -0700293
294 void Break();
jeffhao07030602012-09-26 14:33:14 -0700295 void Nop();
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200296 void Move(Register rd, Register rs);
297 void Clear(Register rd);
298 void Not(Register rd, Register rs);
jeffhao7fbee072012-08-24 17:56:54 -0700299
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200300 // Higher level composite instructions.
301 void LoadConst32(Register rd, int32_t value);
302 void LoadConst64(Register reg_hi, Register reg_lo, int64_t value);
303 void LoadDConst64(FRegister rd, int64_t value, Register temp);
304 void LoadSConst32(FRegister r, int32_t value, Register temp);
305 void StoreConst32ToOffset(int32_t value, Register base, int32_t offset, Register temp);
306 void StoreConst64ToOffset(int64_t value, Register base, int32_t offset, Register temp);
307 void Addiu32(Register rt, Register rs, int32_t value, Register rtmp = AT);
308
309 // These will generate R2 branches or R6 branches as appropriate.
310 void Bind(MipsLabel* label);
311 void B(MipsLabel* label);
312 void Jalr(MipsLabel* label, Register indirect_reg);
313 void Beq(Register rs, Register rt, MipsLabel* label);
314 void Bne(Register rs, Register rt, MipsLabel* label);
315 void Beqz(Register rt, MipsLabel* label);
316 void Bnez(Register rt, MipsLabel* label);
317 void Bltz(Register rt, MipsLabel* label);
318 void Bgez(Register rt, MipsLabel* label);
319 void Blez(Register rt, MipsLabel* label);
320 void Bgtz(Register rt, MipsLabel* label);
321 void Blt(Register rs, Register rt, MipsLabel* label);
322 void Bge(Register rs, Register rt, MipsLabel* label);
323 void Bltu(Register rs, Register rt, MipsLabel* label);
324 void Bgeu(Register rs, Register rt, MipsLabel* label);
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800325 void Bc1f(int cc, MipsLabel* label); // R2
326 void Bc1t(int cc, MipsLabel* label); // R2
327 void Bc1eqz(FRegister ft, MipsLabel* label); // R6
328 void Bc1nez(FRegister ft, MipsLabel* label); // R6
jeffhao7fbee072012-08-24 17:56:54 -0700329
330 void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
331 void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
332 void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200333 void LoadDFromOffset(FRegister reg, Register base, int32_t offset);
jeffhao7fbee072012-08-24 17:56:54 -0700334 void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset);
Goran Jakovljevicff734982015-08-24 12:58:55 +0000335 void StoreSToOffset(FRegister reg, Register base, int32_t offset);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200336 void StoreDToOffset(FRegister reg, Register base, int32_t offset);
jeffhao7fbee072012-08-24 17:56:54 -0700337
jeffhao7fbee072012-08-24 17:56:54 -0700338 // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200339 void Emit(uint32_t value);
340
341 // Push/pop composite routines.
342 void Push(Register rs);
343 void Pop(Register rd);
344 void PopAndReturn(Register rd, Register rt);
jeffhao7fbee072012-08-24 17:56:54 -0700345
Andreas Gampe85b62f22015-09-09 13:15:38 -0700346 void Bind(Label* label) OVERRIDE {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200347 Bind(down_cast<MipsLabel*>(label));
Andreas Gampe85b62f22015-09-09 13:15:38 -0700348 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200349 void Jump(Label* label ATTRIBUTE_UNUSED) OVERRIDE {
350 UNIMPLEMENTED(FATAL) << "Do not use Jump for MIPS";
Andreas Gampe85b62f22015-09-09 13:15:38 -0700351 }
352
jeffhao7fbee072012-08-24 17:56:54 -0700353 //
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200354 // Overridden common assembler high-level functionality.
jeffhao7fbee072012-08-24 17:56:54 -0700355 //
356
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200357 // Emit code that will create an activation on the stack.
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800358 void BuildFrame(size_t frame_size,
359 ManagedRegister method_reg,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700360 const std::vector<ManagedRegister>& callee_save_regs,
361 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700362
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200363 // Emit code that will remove an activation from the stack.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700364 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
365 OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700366
Ian Rogersdd7624d2014-03-14 17:43:00 -0700367 void IncreaseFrameSize(size_t adjust) OVERRIDE;
368 void DecreaseFrameSize(size_t adjust) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700369
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200370 // Store routines.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700371 void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE;
372 void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
373 void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700374
Ian Rogersdd7624d2014-03-14 17:43:00 -0700375 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700376
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800377 void StoreImmediateToThread32(ThreadOffset<kMipsWordSize> dest,
378 uint32_t imm,
379 ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700380
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800381 void StoreStackOffsetToThread32(ThreadOffset<kMipsWordSize> thr_offs,
382 FrameOffset fr_offs,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700383 ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700384
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800385 void StoreStackPointerToThread32(ThreadOffset<kMipsWordSize> thr_offs) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700386
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800387 void StoreSpanning(FrameOffset dest,
388 ManagedRegister msrc,
389 FrameOffset in_off,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700390 ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700391
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200392 // Load routines.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700393 void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700394
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800395 void LoadFromThread32(ManagedRegister mdest,
396 ThreadOffset<kMipsWordSize> src,
397 size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700398
Mathieu Chartiere401d142015-04-22 13:56:20 -0700399 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700400
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800401 void LoadRef(ManagedRegister mdest,
402 ManagedRegister base,
403 MemberOffset offs,
Roland Levillain4d027112015-07-01 15:41:14 +0100404 bool unpoison_reference) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700405
Ian Rogersdd7624d2014-03-14 17:43:00 -0700406 void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700407
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800408 void LoadRawPtrFromThread32(ManagedRegister mdest, ThreadOffset<kMipsWordSize> offs) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700409
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200410 // Copying routines.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700411 void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700412
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800413 void CopyRawPtrFromThread32(FrameOffset fr_offs,
414 ThreadOffset<kMipsWordSize> thr_offs,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700415 ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700416
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800417 void CopyRawPtrToThread32(ThreadOffset<kMipsWordSize> thr_offs,
418 FrameOffset fr_offs,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700419 ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700420
Ian Rogersdd7624d2014-03-14 17:43:00 -0700421 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700422
Ian Rogersdd7624d2014-03-14 17:43:00 -0700423 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700424
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800425 void Copy(FrameOffset dest,
426 ManagedRegister src_base,
427 Offset src_offset,
428 ManagedRegister mscratch,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700429 size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700430
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800431 void Copy(ManagedRegister dest_base,
432 Offset dest_offset,
433 FrameOffset src,
434 ManagedRegister mscratch,
Ian Rogersdd7624d2014-03-14 17:43:00 -0700435 size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700436
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800437 void Copy(FrameOffset dest,
438 FrameOffset src_base,
439 Offset src_offset,
440 ManagedRegister mscratch,
441 size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700442
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800443 void Copy(ManagedRegister dest,
444 Offset dest_offset,
445 ManagedRegister src,
446 Offset src_offset,
447 ManagedRegister mscratch,
448 size_t size) OVERRIDE;
449
450 void Copy(FrameOffset dest,
451 Offset dest_offset,
452 FrameOffset src,
453 Offset src_offset,
454 ManagedRegister mscratch,
455 size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700456
Ian Rogersdd7624d2014-03-14 17:43:00 -0700457 void MemoryBarrier(ManagedRegister) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700458
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200459 // Sign extension.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700460 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700461
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200462 // Zero extension.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700463 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700464
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200465 // Exploit fast access in managed code to Thread::Current().
Ian Rogersdd7624d2014-03-14 17:43:00 -0700466 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
467 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700468
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700469 // Set up out_reg to hold a Object** into the handle scope, or to be null if the
jeffhao7fbee072012-08-24 17:56:54 -0700470 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700471 // that can be used to avoid loading the handle scope entry to see if the value is
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700472 // null.
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800473 void CreateHandleScopeEntry(ManagedRegister out_reg,
474 FrameOffset handlescope_offset,
475 ManagedRegister in_reg,
476 bool null_allowed) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700477
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700478 // Set up out_off to hold a Object** into the handle scope, or to be null if the
jeffhao7fbee072012-08-24 17:56:54 -0700479 // value is null and null_allowed.
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800480 void CreateHandleScopeEntry(FrameOffset out_off,
481 FrameOffset handlescope_offset,
482 ManagedRegister mscratch,
483 bool null_allowed) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700484
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200485 // src holds a handle scope entry (Object**) load this into dst.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700486 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700487
488 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
489 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700490 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
491 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700492
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200493 // Call to address held at [base+offset].
Ian Rogersdd7624d2014-03-14 17:43:00 -0700494 void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE;
495 void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800496 void CallFromThread32(ThreadOffset<kMipsWordSize> offset, ManagedRegister mscratch) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700497
jeffhao7fbee072012-08-24 17:56:54 -0700498 // Generate code to check if Thread::Current()->exception_ is non-null
499 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700500 void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) OVERRIDE;
jeffhao7fbee072012-08-24 17:56:54 -0700501
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200502 // Emit slow paths queued during assembly and promote short branches to long if needed.
503 void FinalizeCode() OVERRIDE;
504
505 // Emit branches and finalize all instructions.
506 void FinalizeInstructions(const MemoryRegion& region);
507
508 // Returns the (always-)current location of a label (can be used in class CodeGeneratorMIPS,
509 // must be used instead of MipsLabel::GetPosition()).
510 uint32_t GetLabelLocation(MipsLabel* label) const;
511
512 // Get the final position of a label after local fixup based on the old position
513 // recorded before FinalizeCode().
514 uint32_t GetAdjustedPosition(uint32_t old_position);
515
516 enum BranchCondition {
517 kCondLT,
518 kCondGE,
519 kCondLE,
520 kCondGT,
521 kCondLTZ,
522 kCondGEZ,
523 kCondLEZ,
524 kCondGTZ,
525 kCondEQ,
526 kCondNE,
527 kCondEQZ,
528 kCondNEZ,
529 kCondLTU,
530 kCondGEU,
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800531 kCondF, // Floating-point predicate false.
532 kCondT, // Floating-point predicate true.
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200533 kUncond,
534 };
535 friend std::ostream& operator<<(std::ostream& os, const BranchCondition& rhs);
536
jeffhao7fbee072012-08-24 17:56:54 -0700537 private:
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200538 class Branch {
539 public:
540 enum Type {
541 // R2 short branches.
542 kUncondBranch,
543 kCondBranch,
544 kCall,
545 // R2 long branches.
546 kLongUncondBranch,
547 kLongCondBranch,
548 kLongCall,
549 // R6 short branches.
550 kR6UncondBranch,
551 kR6CondBranch,
552 kR6Call,
553 // R6 long branches.
554 kR6LongUncondBranch,
555 kR6LongCondBranch,
556 kR6LongCall,
557 };
558 // Bit sizes of offsets defined as enums to minimize chance of typos.
559 enum OffsetBits {
560 kOffset16 = 16,
561 kOffset18 = 18,
562 kOffset21 = 21,
563 kOffset23 = 23,
564 kOffset28 = 28,
565 kOffset32 = 32,
566 };
567
568 static constexpr uint32_t kUnresolved = 0xffffffff; // Unresolved target_
569 static constexpr int32_t kMaxBranchLength = 32;
570 static constexpr int32_t kMaxBranchSize = kMaxBranchLength * sizeof(uint32_t);
571
572 struct BranchInfo {
573 // Branch length as a number of 4-byte-long instructions.
574 uint32_t length;
575 // Ordinal number (0-based) of the first (or the only) instruction that contains the branch's
576 // PC-relative offset (or its most significant 16-bit half, which goes first).
577 uint32_t instr_offset;
578 // Different MIPS instructions with PC-relative offsets apply said offsets to slightly
579 // different origins, e.g. to PC or PC+4. Encode the origin distance (as a number of 4-byte
580 // instructions) from the instruction containing the offset.
581 uint32_t pc_org;
582 // How large (in bits) a PC-relative offset can be for a given type of branch (kR6CondBranch
583 // is an exception: use kOffset23 for beqzc/bnezc).
584 OffsetBits offset_size;
585 // Some MIPS instructions with PC-relative offsets shift the offset by 2. Encode the shift
586 // count.
587 int offset_shift;
588 };
589 static const BranchInfo branch_info_[/* Type */];
590
591 // Unconditional branch.
592 Branch(bool is_r6, uint32_t location, uint32_t target);
593 // Conditional branch.
594 Branch(bool is_r6,
595 uint32_t location,
596 uint32_t target,
597 BranchCondition condition,
598 Register lhs_reg,
599 Register rhs_reg = ZERO);
600 // Call (branch and link) that stores the target address in a given register (i.e. T9).
601 Branch(bool is_r6, uint32_t location, uint32_t target, Register indirect_reg);
602
603 // Some conditional branches with lhs = rhs are effectively NOPs, while some
604 // others are effectively unconditional. MIPSR6 conditional branches require lhs != rhs.
605 // So, we need a way to identify such branches in order to emit no instructions for them
606 // or change them to unconditional.
607 static bool IsNop(BranchCondition condition, Register lhs, Register rhs);
608 static bool IsUncond(BranchCondition condition, Register lhs, Register rhs);
609
610 static BranchCondition OppositeCondition(BranchCondition cond);
611
612 Type GetType() const;
613 BranchCondition GetCondition() const;
614 Register GetLeftRegister() const;
615 Register GetRightRegister() const;
616 uint32_t GetTarget() const;
617 uint32_t GetLocation() const;
618 uint32_t GetOldLocation() const;
619 uint32_t GetLength() const;
620 uint32_t GetOldLength() const;
621 uint32_t GetSize() const;
622 uint32_t GetOldSize() const;
623 uint32_t GetEndLocation() const;
624 uint32_t GetOldEndLocation() const;
625 bool IsLong() const;
626 bool IsResolved() const;
627
628 // Returns the bit size of the signed offset that the branch instruction can handle.
629 OffsetBits GetOffsetSize() const;
630
631 // Calculates the distance between two byte locations in the assembler buffer and
632 // returns the number of bits needed to represent the distance as a signed integer.
633 //
634 // Branch instructions have signed offsets of 16, 19 (addiupc), 21 (beqzc/bnezc),
635 // and 26 (bc) bits, which are additionally shifted left 2 positions at run time.
636 //
637 // Composite branches (made of several instructions) with longer reach have 32-bit
638 // offsets encoded as 2 16-bit "halves" in two instructions (high half goes first).
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800639 // The composite branches cover the range of PC + +/-2GB on MIPS32 CPUs. However,
640 // the range is not end-to-end on MIPS64 (unless addresses are forced to zero- or
641 // sign-extend from 32 to 64 bits by the appropriate CPU configuration).
642 // Consider the following implementation of a long unconditional branch, for
643 // example:
644 //
645 // auipc at, offset_31_16 // at = pc + sign_extend(offset_31_16) << 16
646 // jic at, offset_15_0 // pc = at + sign_extend(offset_15_0)
647 //
648 // Both of the above instructions take 16-bit signed offsets as immediate operands.
649 // When bit 15 of offset_15_0 is 1, it effectively causes subtraction of 0x10000
650 // due to sign extension. This must be compensated for by incrementing offset_31_16
651 // by 1. offset_31_16 can only be incremented by 1 if it's not 0x7FFF. If it is
652 // 0x7FFF, adding 1 will overflow the positive offset into the negative range.
653 // Therefore, the long branch range is something like from PC - 0x80000000 to
654 // PC + 0x7FFF7FFF, IOW, shorter by 32KB on one side.
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200655 //
656 // The returned values are therefore: 18, 21, 23, 28 and 32. There's also a special
657 // case with the addiu instruction and a 16 bit offset.
658 static OffsetBits GetOffsetSizeNeeded(uint32_t location, uint32_t target);
659
660 // Resolve a branch when the target is known.
661 void Resolve(uint32_t target);
662
663 // Relocate a branch by a given delta if needed due to expansion of this or another
664 // branch at a given location by this delta (just changes location_ and target_).
665 void Relocate(uint32_t expand_location, uint32_t delta);
666
667 // If the branch is short, changes its type to long.
668 void PromoteToLong();
669
670 // If necessary, updates the type by promoting a short branch to a long branch
671 // based on the branch location and target. Returns the amount (in bytes) by
672 // which the branch size has increased.
673 // max_short_distance caps the maximum distance between location_ and target_
674 // that is allowed for short branches. This is for debugging/testing purposes.
675 // max_short_distance = 0 forces all short branches to become long.
676 // Use the implicit default argument when not debugging/testing.
677 uint32_t PromoteIfNeeded(uint32_t max_short_distance = std::numeric_limits<uint32_t>::max());
678
679 // Returns the location of the instruction(s) containing the offset.
680 uint32_t GetOffsetLocation() const;
681
682 // Calculates and returns the offset ready for encoding in the branch instruction(s).
683 uint32_t GetOffset() const;
684
685 private:
686 // Completes branch construction by determining and recording its type.
687 void InitializeType(bool is_call, bool is_r6);
688 // Helper for the above.
689 void InitShortOrLong(OffsetBits ofs_size, Type short_type, Type long_type);
690
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800691 uint32_t old_location_; // Offset into assembler buffer in bytes.
692 uint32_t location_; // Offset into assembler buffer in bytes.
693 uint32_t target_; // Offset into assembler buffer in bytes.
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200694
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800695 uint32_t lhs_reg_; // Left-hand side register in conditional branches or
696 // indirect call register.
697 uint32_t rhs_reg_; // Right-hand side register in conditional branches.
698 BranchCondition condition_; // Condition for conditional branches.
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200699
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800700 Type type_; // Current type of the branch.
701 Type old_type_; // Initial type of the branch.
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200702 };
703 friend std::ostream& operator<<(std::ostream& os, const Branch::Type& rhs);
704 friend std::ostream& operator<<(std::ostream& os, const Branch::OffsetBits& rhs);
705
jeffhao7fbee072012-08-24 17:56:54 -0700706 void EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct);
707 void EmitI(int opcode, Register rs, Register rt, uint16_t imm);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200708 void EmitI21(int opcode, Register rs, uint32_t imm21);
709 void EmitI26(int opcode, uint32_t imm26);
jeffhao7fbee072012-08-24 17:56:54 -0700710 void EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct);
711 void EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm);
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800712 void EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16);
713 void EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21);
jeffhao7fbee072012-08-24 17:56:54 -0700714
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200715 void Buncond(MipsLabel* label);
716 void Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs = ZERO);
717 void Call(MipsLabel* label, Register indirect_reg);
718 void FinalizeLabeledBranch(MipsLabel* label);
jeffhao7fbee072012-08-24 17:56:54 -0700719
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200720 Branch* GetBranch(uint32_t branch_id);
721 const Branch* GetBranch(uint32_t branch_id) const;
722
723 void PromoteBranches();
724 void EmitBranch(Branch* branch);
725 void EmitBranches();
Vladimir Marko10ef6942015-10-22 15:25:54 +0100726 void PatchCFI(size_t number_of_delayed_adjust_pcs);
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200727
728 // Emits exception block.
729 void EmitExceptionPoll(MipsExceptionSlowPath* exception);
730
731 bool IsR6() const {
732 if (isa_features_ != nullptr) {
733 return isa_features_->IsR6();
734 } else {
735 return false;
736 }
Goran Jakovljevicff734982015-08-24 12:58:55 +0000737 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200738
739 bool Is32BitFPU() const {
740 if (isa_features_ != nullptr) {
741 return isa_features_->Is32BitFloatingPoint();
742 } else {
743 return true;
744 }
Goran Jakovljevicff734982015-08-24 12:58:55 +0000745 }
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200746
747 // List of exception blocks to generate at the end of the code cache.
748 std::vector<MipsExceptionSlowPath> exception_blocks_;
749
750 std::vector<Branch> branches_;
751
752 // Whether appending instructions at the end of the buffer or overwriting the existing ones.
753 bool overwriting_;
754 // The current overwrite location.
755 uint32_t overwrite_location_;
756
757 // Data for AdjustedPosition(), see the description there.
758 uint32_t last_position_adjustment_;
759 uint32_t last_old_position_;
760 uint32_t last_branch_id_;
761
762 const MipsInstructionSetFeatures* isa_features_;
Goran Jakovljevicff734982015-08-24 12:58:55 +0000763
jeffhao7fbee072012-08-24 17:56:54 -0700764 DISALLOW_COPY_AND_ASSIGN(MipsAssembler);
765};
766
jeffhao7fbee072012-08-24 17:56:54 -0700767} // namespace mips
768} // namespace art
769
Ian Rogers166db042013-07-26 12:05:57 -0700770#endif // ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_