• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #ifndef ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
18 #define ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
19 
20 #include <deque>
21 #include <utility>
22 #include <vector>
23 
24 #include "arch/mips/instruction_set_features_mips.h"
25 #include "base/arena_containers.h"
26 #include "base/enums.h"
27 #include "base/macros.h"
28 #include "base/stl_util_identity.h"
29 #include "constants_mips.h"
30 #include "globals.h"
31 #include "managed_register_mips.h"
32 #include "offsets.h"
33 #include "utils/assembler.h"
34 #include "utils/jni_macro_assembler.h"
35 #include "utils/label.h"
36 
37 namespace art {
38 namespace mips {
39 
40 static constexpr size_t kMipsHalfwordSize = 2;
41 static constexpr size_t kMipsWordSize = 4;
42 static constexpr size_t kMipsDoublewordSize = 8;
43 
44 enum LoadOperandType {
45   kLoadSignedByte,
46   kLoadUnsignedByte,
47   kLoadSignedHalfword,
48   kLoadUnsignedHalfword,
49   kLoadWord,
50   kLoadDoubleword,
51   kLoadQuadword
52 };
53 
54 enum StoreOperandType {
55   kStoreByte,
56   kStoreHalfword,
57   kStoreWord,
58   kStoreDoubleword,
59   kStoreQuadword
60 };
61 
62 // Used to test the values returned by ClassS/ClassD.
63 enum FPClassMaskType {
64   kSignalingNaN      = 0x001,
65   kQuietNaN          = 0x002,
66   kNegativeInfinity  = 0x004,
67   kNegativeNormal    = 0x008,
68   kNegativeSubnormal = 0x010,
69   kNegativeZero      = 0x020,
70   kPositiveInfinity  = 0x040,
71   kPositiveNormal    = 0x080,
72   kPositiveSubnormal = 0x100,
73   kPositiveZero      = 0x200,
74 };
75 
76 class MipsLabel : public Label {
77  public:
MipsLabel()78   MipsLabel() : prev_branch_id_plus_one_(0) {}
79 
MipsLabel(MipsLabel && src)80   MipsLabel(MipsLabel&& src)
81       : Label(std::move(src)), prev_branch_id_plus_one_(src.prev_branch_id_plus_one_) {}
82 
83  private:
84   uint32_t prev_branch_id_plus_one_;  // To get distance from preceding branch, if any.
85 
86   friend class MipsAssembler;
87   DISALLOW_COPY_AND_ASSIGN(MipsLabel);
88 };
89 
90 // Assembler literal is a value embedded in code, retrieved using a PC-relative load.
91 class Literal {
92  public:
93   static constexpr size_t kMaxSize = 8;
94 
Literal(uint32_t size,const uint8_t * data)95   Literal(uint32_t size, const uint8_t* data)
96       : label_(), size_(size) {
97     DCHECK_LE(size, Literal::kMaxSize);
98     memcpy(data_, data, size);
99   }
100 
101   template <typename T>
GetValue()102   T GetValue() const {
103     DCHECK_EQ(size_, sizeof(T));
104     T value;
105     memcpy(&value, data_, sizeof(T));
106     return value;
107   }
108 
GetSize()109   uint32_t GetSize() const {
110     return size_;
111   }
112 
GetData()113   const uint8_t* GetData() const {
114     return data_;
115   }
116 
GetLabel()117   MipsLabel* GetLabel() {
118     return &label_;
119   }
120 
GetLabel()121   const MipsLabel* GetLabel() const {
122     return &label_;
123   }
124 
125  private:
126   MipsLabel label_;
127   const uint32_t size_;
128   uint8_t data_[kMaxSize];
129 
130   DISALLOW_COPY_AND_ASSIGN(Literal);
131 };
132 
133 // Jump table: table of labels emitted after the literals. Similar to literals.
134 class JumpTable {
135  public:
JumpTable(std::vector<MipsLabel * > && labels)136   explicit JumpTable(std::vector<MipsLabel*>&& labels)
137       : label_(), labels_(std::move(labels)) {
138   }
139 
GetSize()140   uint32_t GetSize() const {
141     return static_cast<uint32_t>(labels_.size()) * sizeof(uint32_t);
142   }
143 
GetData()144   const std::vector<MipsLabel*>& GetData() const {
145     return labels_;
146   }
147 
GetLabel()148   MipsLabel* GetLabel() {
149     return &label_;
150   }
151 
GetLabel()152   const MipsLabel* GetLabel() const {
153     return &label_;
154   }
155 
156  private:
157   MipsLabel label_;
158   std::vector<MipsLabel*> labels_;
159 
160   DISALLOW_COPY_AND_ASSIGN(JumpTable);
161 };
162 
163 // Slowpath entered when Thread::Current()->_exception is non-null.
164 class MipsExceptionSlowPath {
165  public:
MipsExceptionSlowPath(MipsManagedRegister scratch,size_t stack_adjust)166   explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
167       : scratch_(scratch), stack_adjust_(stack_adjust) {}
168 
MipsExceptionSlowPath(MipsExceptionSlowPath && src)169   MipsExceptionSlowPath(MipsExceptionSlowPath&& src)
170       : scratch_(src.scratch_),
171         stack_adjust_(src.stack_adjust_),
172         exception_entry_(std::move(src.exception_entry_)) {}
173 
174  private:
Entry()175   MipsLabel* Entry() { return &exception_entry_; }
176   const MipsManagedRegister scratch_;
177   const size_t stack_adjust_;
178   MipsLabel exception_entry_;
179 
180   friend class MipsAssembler;
181   DISALLOW_COPY_AND_ASSIGN(MipsExceptionSlowPath);
182 };
183 
184 class MipsAssembler FINAL : public Assembler, public JNIMacroAssembler<PointerSize::k32> {
185  public:
186   using JNIBase = JNIMacroAssembler<PointerSize::k32>;
187 
188   explicit MipsAssembler(ArenaAllocator* arena,
189                          const MipsInstructionSetFeatures* instruction_set_features = nullptr)
Assembler(arena)190       : Assembler(arena),
191         overwriting_(false),
192         overwrite_location_(0),
193         reordering_(true),
194         ds_fsm_state_(kExpectingLabel),
195         ds_fsm_target_pc_(0),
196         literals_(arena->Adapter(kArenaAllocAssembler)),
197         jump_tables_(arena->Adapter(kArenaAllocAssembler)),
198         last_position_adjustment_(0),
199         last_old_position_(0),
200         last_branch_id_(0),
201         has_msa_(instruction_set_features != nullptr ? instruction_set_features->HasMsa() : false),
202         isa_features_(instruction_set_features) {
203     cfi().DelayEmittingAdvancePCs();
204   }
205 
CodeSize()206   size_t CodeSize() const OVERRIDE { return Assembler::CodeSize(); }
207   size_t CodePosition() OVERRIDE;
cfi()208   DebugFrameOpCodeWriterForAssembler& cfi() { return Assembler::cfi(); }
209 
~MipsAssembler()210   virtual ~MipsAssembler() {
211     for (auto& branch : branches_) {
212       CHECK(branch.IsResolved());
213     }
214   }
215 
216   // Emit Machine Instructions.
217   void Addu(Register rd, Register rs, Register rt);
218   void Addiu(Register rt, Register rs, uint16_t imm16);
219   void Subu(Register rd, Register rs, Register rt);
220 
221   void MultR2(Register rs, Register rt);  // R2
222   void MultuR2(Register rs, Register rt);  // R2
223   void DivR2(Register rs, Register rt);  // R2
224   void DivuR2(Register rs, Register rt);  // R2
225   void MulR2(Register rd, Register rs, Register rt);  // R2
226   void DivR2(Register rd, Register rs, Register rt);  // R2
227   void ModR2(Register rd, Register rs, Register rt);  // R2
228   void DivuR2(Register rd, Register rs, Register rt);  // R2
229   void ModuR2(Register rd, Register rs, Register rt);  // R2
230   void MulR6(Register rd, Register rs, Register rt);  // R6
231   void MuhR6(Register rd, Register rs, Register rt);  // R6
232   void MuhuR6(Register rd, Register rs, Register rt);  // R6
233   void DivR6(Register rd, Register rs, Register rt);  // R6
234   void ModR6(Register rd, Register rs, Register rt);  // R6
235   void DivuR6(Register rd, Register rs, Register rt);  // R6
236   void ModuR6(Register rd, Register rs, Register rt);  // R6
237 
238   void And(Register rd, Register rs, Register rt);
239   void Andi(Register rt, Register rs, uint16_t imm16);
240   void Or(Register rd, Register rs, Register rt);
241   void Ori(Register rt, Register rs, uint16_t imm16);
242   void Xor(Register rd, Register rs, Register rt);
243   void Xori(Register rt, Register rs, uint16_t imm16);
244   void Nor(Register rd, Register rs, Register rt);
245 
246   void Movz(Register rd, Register rs, Register rt);  // R2
247   void Movn(Register rd, Register rs, Register rt);  // R2
248   void Seleqz(Register rd, Register rs, Register rt);  // R6
249   void Selnez(Register rd, Register rs, Register rt);  // R6
250   void ClzR6(Register rd, Register rs);
251   void ClzR2(Register rd, Register rs);
252   void CloR6(Register rd, Register rs);
253   void CloR2(Register rd, Register rs);
254 
255   void Seb(Register rd, Register rt);  // R2+
256   void Seh(Register rd, Register rt);  // R2+
257   void Wsbh(Register rd, Register rt);  // R2+
258   void Bitswap(Register rd, Register rt);  // R6
259 
260   void Sll(Register rd, Register rt, int shamt);
261   void Srl(Register rd, Register rt, int shamt);
262   void Rotr(Register rd, Register rt, int shamt);  // R2+
263   void Sra(Register rd, Register rt, int shamt);
264   void Sllv(Register rd, Register rt, Register rs);
265   void Srlv(Register rd, Register rt, Register rs);
266   void Rotrv(Register rd, Register rt, Register rs);  // R2+
267   void Srav(Register rd, Register rt, Register rs);
268   void Ext(Register rd, Register rt, int pos, int size);  // R2+
269   void Ins(Register rd, Register rt, int pos, int size);  // R2+
270   void Lsa(Register rd, Register rs, Register rt, int saPlusOne);  // R6
271   void ShiftAndAdd(Register dst, Register src_idx, Register src_base, int shamt, Register tmp = AT);
272 
273   void Lb(Register rt, Register rs, uint16_t imm16);
274   void Lh(Register rt, Register rs, uint16_t imm16);
275   void Lw(Register rt, Register rs, uint16_t imm16);
276   void Lwl(Register rt, Register rs, uint16_t imm16);
277   void Lwr(Register rt, Register rs, uint16_t imm16);
278   void Lbu(Register rt, Register rs, uint16_t imm16);
279   void Lhu(Register rt, Register rs, uint16_t imm16);
280   void Lwpc(Register rs, uint32_t imm19);  // R6
281   void Lui(Register rt, uint16_t imm16);
282   void Aui(Register rt, Register rs, uint16_t imm16);  // R6
283   void Sync(uint32_t stype);
284   void Mfhi(Register rd);  // R2
285   void Mflo(Register rd);  // R2
286 
287   void Sb(Register rt, Register rs, uint16_t imm16);
288   void Sh(Register rt, Register rs, uint16_t imm16);
289   void Sw(Register rt, Register rs, uint16_t imm16);
290   void Swl(Register rt, Register rs, uint16_t imm16);
291   void Swr(Register rt, Register rs, uint16_t imm16);
292 
293   void LlR2(Register rt, Register base, int16_t imm16 = 0);
294   void ScR2(Register rt, Register base, int16_t imm16 = 0);
295   void LlR6(Register rt, Register base, int16_t imm9 = 0);
296   void ScR6(Register rt, Register base, int16_t imm9 = 0);
297 
298   void Slt(Register rd, Register rs, Register rt);
299   void Sltu(Register rd, Register rs, Register rt);
300   void Slti(Register rt, Register rs, uint16_t imm16);
301   void Sltiu(Register rt, Register rs, uint16_t imm16);
302 
303   // Branches and jumps to immediate offsets/addresses do not take care of their
304   // delay/forbidden slots and generally should not be used directly. This applies
305   // to the following R2 and R6 branch/jump instructions with imm16, imm21, addr26
306   // offsets/addresses.
307   // Use branches/jumps to labels instead.
308   void B(uint16_t imm16);
309   void Bal(uint16_t imm16);
310   void Beq(Register rs, Register rt, uint16_t imm16);
311   void Bne(Register rs, Register rt, uint16_t imm16);
312   void Beqz(Register rt, uint16_t imm16);
313   void Bnez(Register rt, uint16_t imm16);
314   void Bltz(Register rt, uint16_t imm16);
315   void Bgez(Register rt, uint16_t imm16);
316   void Blez(Register rt, uint16_t imm16);
317   void Bgtz(Register rt, uint16_t imm16);
318   void Bc1f(uint16_t imm16);  // R2
319   void Bc1f(int cc, uint16_t imm16);  // R2
320   void Bc1t(uint16_t imm16);  // R2
321   void Bc1t(int cc, uint16_t imm16);  // R2
322   void J(uint32_t addr26);
323   void Jal(uint32_t addr26);
324   // Jalr() and Jr() fill their delay slots when reordering is enabled.
325   // When reordering is disabled, the delay slots must be filled manually.
326   // You may use NopIfNoReordering() to fill them when reordering is disabled.
327   void Jalr(Register rd, Register rs);
328   void Jalr(Register rs);
329   void Jr(Register rs);
330   // Nal() does not fill its delay slot. It must be filled manually.
331   void Nal();
332   void Auipc(Register rs, uint16_t imm16);  // R6
333   void Addiupc(Register rs, uint32_t imm19);  // R6
334   void Bc(uint32_t imm26);  // R6
335   void Balc(uint32_t imm26);  // R6
336   void Jic(Register rt, uint16_t imm16);  // R6
337   void Jialc(Register rt, uint16_t imm16);  // R6
338   void Bltc(Register rs, Register rt, uint16_t imm16);  // R6
339   void Bltzc(Register rt, uint16_t imm16);  // R6
340   void Bgtzc(Register rt, uint16_t imm16);  // R6
341   void Bgec(Register rs, Register rt, uint16_t imm16);  // R6
342   void Bgezc(Register rt, uint16_t imm16);  // R6
343   void Blezc(Register rt, uint16_t imm16);  // R6
344   void Bltuc(Register rs, Register rt, uint16_t imm16);  // R6
345   void Bgeuc(Register rs, Register rt, uint16_t imm16);  // R6
346   void Beqc(Register rs, Register rt, uint16_t imm16);  // R6
347   void Bnec(Register rs, Register rt, uint16_t imm16);  // R6
348   void Beqzc(Register rs, uint32_t imm21);  // R6
349   void Bnezc(Register rs, uint32_t imm21);  // R6
350   void Bc1eqz(FRegister ft, uint16_t imm16);  // R6
351   void Bc1nez(FRegister ft, uint16_t imm16);  // R6
352 
353   void AddS(FRegister fd, FRegister fs, FRegister ft);
354   void SubS(FRegister fd, FRegister fs, FRegister ft);
355   void MulS(FRegister fd, FRegister fs, FRegister ft);
356   void DivS(FRegister fd, FRegister fs, FRegister ft);
357   void AddD(FRegister fd, FRegister fs, FRegister ft);
358   void SubD(FRegister fd, FRegister fs, FRegister ft);
359   void MulD(FRegister fd, FRegister fs, FRegister ft);
360   void DivD(FRegister fd, FRegister fs, FRegister ft);
361   void SqrtS(FRegister fd, FRegister fs);
362   void SqrtD(FRegister fd, FRegister fs);
363   void AbsS(FRegister fd, FRegister fs);
364   void AbsD(FRegister fd, FRegister fs);
365   void MovS(FRegister fd, FRegister fs);
366   void MovD(FRegister fd, FRegister fs);
367   void NegS(FRegister fd, FRegister fs);
368   void NegD(FRegister fd, FRegister fs);
369 
370   void CunS(FRegister fs, FRegister ft);  // R2
371   void CunS(int cc, FRegister fs, FRegister ft);  // R2
372   void CeqS(FRegister fs, FRegister ft);  // R2
373   void CeqS(int cc, FRegister fs, FRegister ft);  // R2
374   void CueqS(FRegister fs, FRegister ft);  // R2
375   void CueqS(int cc, FRegister fs, FRegister ft);  // R2
376   void ColtS(FRegister fs, FRegister ft);  // R2
377   void ColtS(int cc, FRegister fs, FRegister ft);  // R2
378   void CultS(FRegister fs, FRegister ft);  // R2
379   void CultS(int cc, FRegister fs, FRegister ft);  // R2
380   void ColeS(FRegister fs, FRegister ft);  // R2
381   void ColeS(int cc, FRegister fs, FRegister ft);  // R2
382   void CuleS(FRegister fs, FRegister ft);  // R2
383   void CuleS(int cc, FRegister fs, FRegister ft);  // R2
384   void CunD(FRegister fs, FRegister ft);  // R2
385   void CunD(int cc, FRegister fs, FRegister ft);  // R2
386   void CeqD(FRegister fs, FRegister ft);  // R2
387   void CeqD(int cc, FRegister fs, FRegister ft);  // R2
388   void CueqD(FRegister fs, FRegister ft);  // R2
389   void CueqD(int cc, FRegister fs, FRegister ft);  // R2
390   void ColtD(FRegister fs, FRegister ft);  // R2
391   void ColtD(int cc, FRegister fs, FRegister ft);  // R2
392   void CultD(FRegister fs, FRegister ft);  // R2
393   void CultD(int cc, FRegister fs, FRegister ft);  // R2
394   void ColeD(FRegister fs, FRegister ft);  // R2
395   void ColeD(int cc, FRegister fs, FRegister ft);  // R2
396   void CuleD(FRegister fs, FRegister ft);  // R2
397   void CuleD(int cc, FRegister fs, FRegister ft);  // R2
398   void CmpUnS(FRegister fd, FRegister fs, FRegister ft);  // R6
399   void CmpEqS(FRegister fd, FRegister fs, FRegister ft);  // R6
400   void CmpUeqS(FRegister fd, FRegister fs, FRegister ft);  // R6
401   void CmpLtS(FRegister fd, FRegister fs, FRegister ft);  // R6
402   void CmpUltS(FRegister fd, FRegister fs, FRegister ft);  // R6
403   void CmpLeS(FRegister fd, FRegister fs, FRegister ft);  // R6
404   void CmpUleS(FRegister fd, FRegister fs, FRegister ft);  // R6
405   void CmpOrS(FRegister fd, FRegister fs, FRegister ft);  // R6
406   void CmpUneS(FRegister fd, FRegister fs, FRegister ft);  // R6
407   void CmpNeS(FRegister fd, FRegister fs, FRegister ft);  // R6
408   void CmpUnD(FRegister fd, FRegister fs, FRegister ft);  // R6
409   void CmpEqD(FRegister fd, FRegister fs, FRegister ft);  // R6
410   void CmpUeqD(FRegister fd, FRegister fs, FRegister ft);  // R6
411   void CmpLtD(FRegister fd, FRegister fs, FRegister ft);  // R6
412   void CmpUltD(FRegister fd, FRegister fs, FRegister ft);  // R6
413   void CmpLeD(FRegister fd, FRegister fs, FRegister ft);  // R6
414   void CmpUleD(FRegister fd, FRegister fs, FRegister ft);  // R6
415   void CmpOrD(FRegister fd, FRegister fs, FRegister ft);  // R6
416   void CmpUneD(FRegister fd, FRegister fs, FRegister ft);  // R6
417   void CmpNeD(FRegister fd, FRegister fs, FRegister ft);  // R6
418   void Movf(Register rd, Register rs, int cc = 0);  // R2
419   void Movt(Register rd, Register rs, int cc = 0);  // R2
420   void MovfS(FRegister fd, FRegister fs, int cc = 0);  // R2
421   void MovfD(FRegister fd, FRegister fs, int cc = 0);  // R2
422   void MovtS(FRegister fd, FRegister fs, int cc = 0);  // R2
423   void MovtD(FRegister fd, FRegister fs, int cc = 0);  // R2
424   void MovzS(FRegister fd, FRegister fs, Register rt);  // R2
425   void MovzD(FRegister fd, FRegister fs, Register rt);  // R2
426   void MovnS(FRegister fd, FRegister fs, Register rt);  // R2
427   void MovnD(FRegister fd, FRegister fs, Register rt);  // R2
428   void SelS(FRegister fd, FRegister fs, FRegister ft);  // R6
429   void SelD(FRegister fd, FRegister fs, FRegister ft);  // R6
430   void SeleqzS(FRegister fd, FRegister fs, FRegister ft);  // R6
431   void SeleqzD(FRegister fd, FRegister fs, FRegister ft);  // R6
432   void SelnezS(FRegister fd, FRegister fs, FRegister ft);  // R6
433   void SelnezD(FRegister fd, FRegister fs, FRegister ft);  // R6
434   void ClassS(FRegister fd, FRegister fs);  // R6
435   void ClassD(FRegister fd, FRegister fs);  // R6
436   void MinS(FRegister fd, FRegister fs, FRegister ft);  // R6
437   void MinD(FRegister fd, FRegister fs, FRegister ft);  // R6
438   void MaxS(FRegister fd, FRegister fs, FRegister ft);  // R6
439   void MaxD(FRegister fd, FRegister fs, FRegister ft);  // R6
440 
441   void TruncLS(FRegister fd, FRegister fs);  // R2+, FR=1
442   void TruncLD(FRegister fd, FRegister fs);  // R2+, FR=1
443   void TruncWS(FRegister fd, FRegister fs);
444   void TruncWD(FRegister fd, FRegister fs);
445   void Cvtsw(FRegister fd, FRegister fs);
446   void Cvtdw(FRegister fd, FRegister fs);
447   void Cvtsd(FRegister fd, FRegister fs);
448   void Cvtds(FRegister fd, FRegister fs);
449   void Cvtsl(FRegister fd, FRegister fs);  // R2+, FR=1
450   void Cvtdl(FRegister fd, FRegister fs);  // R2+, FR=1
451   void FloorWS(FRegister fd, FRegister fs);
452   void FloorWD(FRegister fd, FRegister fs);
453 
454   void Mfc1(Register rt, FRegister fs);
455   void Mtc1(Register rt, FRegister fs);
456   void Mfhc1(Register rt, FRegister fs);
457   void Mthc1(Register rt, FRegister fs);
458   void MoveFromFpuHigh(Register rt, FRegister fs);
459   void MoveToFpuHigh(Register rt, FRegister fs);
460   void Lwc1(FRegister ft, Register rs, uint16_t imm16);
461   void Ldc1(FRegister ft, Register rs, uint16_t imm16);
462   void Swc1(FRegister ft, Register rs, uint16_t imm16);
463   void Sdc1(FRegister ft, Register rs, uint16_t imm16);
464 
465   void Break();
466   void Nop();
467   void NopIfNoReordering();
468   void Move(Register rd, Register rs);
469   void Clear(Register rd);
470   void Not(Register rd, Register rs);
471 
472   // MSA instructions.
473   void AndV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
474   void OrV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
475   void NorV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
476   void XorV(VectorRegister wd, VectorRegister ws, VectorRegister wt);
477 
478   void AddvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
479   void AddvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
480   void AddvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
481   void AddvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
482   void SubvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
483   void SubvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
484   void SubvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
485   void SubvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
486   void MulvB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
487   void MulvH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
488   void MulvW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
489   void MulvD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
490   void Div_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
491   void Div_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
492   void Div_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
493   void Div_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
494   void Div_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
495   void Div_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
496   void Div_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
497   void Div_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
498   void Mod_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
499   void Mod_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
500   void Mod_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
501   void Mod_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
502   void Mod_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
503   void Mod_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
504   void Mod_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
505   void Mod_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
506   void Add_aB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
507   void Add_aH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
508   void Add_aW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
509   void Add_aD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
510   void Ave_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
511   void Ave_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
512   void Ave_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
513   void Ave_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
514   void Ave_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
515   void Ave_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
516   void Ave_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
517   void Ave_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
518   void Aver_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
519   void Aver_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
520   void Aver_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
521   void Aver_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
522   void Aver_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
523   void Aver_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
524   void Aver_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
525   void Aver_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
526   void Max_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
527   void Max_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
528   void Max_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
529   void Max_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
530   void Max_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
531   void Max_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
532   void Max_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
533   void Max_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
534   void Min_sB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
535   void Min_sH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
536   void Min_sW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
537   void Min_sD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
538   void Min_uB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
539   void Min_uH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
540   void Min_uW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
541   void Min_uD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
542 
543   void FaddW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
544   void FaddD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
545   void FsubW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
546   void FsubD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
547   void FmulW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
548   void FmulD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
549   void FdivW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
550   void FdivD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
551   void FmaxW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
552   void FmaxD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
553   void FminW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
554   void FminD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
555 
556   void Ffint_sW(VectorRegister wd, VectorRegister ws);
557   void Ffint_sD(VectorRegister wd, VectorRegister ws);
558   void Ftint_sW(VectorRegister wd, VectorRegister ws);
559   void Ftint_sD(VectorRegister wd, VectorRegister ws);
560 
561   void SllB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
562   void SllH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
563   void SllW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
564   void SllD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
565   void SraB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
566   void SraH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
567   void SraW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
568   void SraD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
569   void SrlB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
570   void SrlH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
571   void SrlW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
572   void SrlD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
573 
574   // Immediate shift instructions, where shamtN denotes shift amount (must be between 0 and 2^N-1).
575   void SlliB(VectorRegister wd, VectorRegister ws, int shamt3);
576   void SlliH(VectorRegister wd, VectorRegister ws, int shamt4);
577   void SlliW(VectorRegister wd, VectorRegister ws, int shamt5);
578   void SlliD(VectorRegister wd, VectorRegister ws, int shamt6);
579   void SraiB(VectorRegister wd, VectorRegister ws, int shamt3);
580   void SraiH(VectorRegister wd, VectorRegister ws, int shamt4);
581   void SraiW(VectorRegister wd, VectorRegister ws, int shamt5);
582   void SraiD(VectorRegister wd, VectorRegister ws, int shamt6);
583   void SrliB(VectorRegister wd, VectorRegister ws, int shamt3);
584   void SrliH(VectorRegister wd, VectorRegister ws, int shamt4);
585   void SrliW(VectorRegister wd, VectorRegister ws, int shamt5);
586   void SrliD(VectorRegister wd, VectorRegister ws, int shamt6);
587 
588   void MoveV(VectorRegister wd, VectorRegister ws);
589   void SplatiB(VectorRegister wd, VectorRegister ws, int n4);
590   void SplatiH(VectorRegister wd, VectorRegister ws, int n3);
591   void SplatiW(VectorRegister wd, VectorRegister ws, int n2);
592   void SplatiD(VectorRegister wd, VectorRegister ws, int n1);
593   void FillB(VectorRegister wd, Register rs);
594   void FillH(VectorRegister wd, Register rs);
595   void FillW(VectorRegister wd, Register rs);
596 
597   void LdiB(VectorRegister wd, int imm8);
598   void LdiH(VectorRegister wd, int imm10);
599   void LdiW(VectorRegister wd, int imm10);
600   void LdiD(VectorRegister wd, int imm10);
601   void LdB(VectorRegister wd, Register rs, int offset);
602   void LdH(VectorRegister wd, Register rs, int offset);
603   void LdW(VectorRegister wd, Register rs, int offset);
604   void LdD(VectorRegister wd, Register rs, int offset);
605   void StB(VectorRegister wd, Register rs, int offset);
606   void StH(VectorRegister wd, Register rs, int offset);
607   void StW(VectorRegister wd, Register rs, int offset);
608   void StD(VectorRegister wd, Register rs, int offset);
609 
610   void IlvrB(VectorRegister wd, VectorRegister ws, VectorRegister wt);
611   void IlvrH(VectorRegister wd, VectorRegister ws, VectorRegister wt);
612   void IlvrW(VectorRegister wd, VectorRegister ws, VectorRegister wt);
613   void IlvrD(VectorRegister wd, VectorRegister ws, VectorRegister wt);
614 
615   // Helper for replicating floating point value in all destination elements.
616   void ReplicateFPToVectorRegister(VectorRegister dst, FRegister src, bool is_double);
617 
618   // Higher level composite instructions.
619   void LoadConst32(Register rd, int32_t value);
620   void LoadConst64(Register reg_hi, Register reg_lo, int64_t value);
621   void LoadDConst64(FRegister rd, int64_t value, Register temp);
622   void LoadSConst32(FRegister r, int32_t value, Register temp);
623   void Addiu32(Register rt, Register rs, int32_t value, Register rtmp = AT);
624 
625   // These will generate R2 branches or R6 branches as appropriate and take care of
626   // the delay/forbidden slots.
627   void Bind(MipsLabel* label);
628   void B(MipsLabel* label);
629   void Bal(MipsLabel* label);
630   void Beq(Register rs, Register rt, MipsLabel* label);
631   void Bne(Register rs, Register rt, MipsLabel* label);
632   void Beqz(Register rt, MipsLabel* label);
633   void Bnez(Register rt, MipsLabel* label);
634   void Bltz(Register rt, MipsLabel* label);
635   void Bgez(Register rt, MipsLabel* label);
636   void Blez(Register rt, MipsLabel* label);
637   void Bgtz(Register rt, MipsLabel* label);
638   void Blt(Register rs, Register rt, MipsLabel* label);
639   void Bge(Register rs, Register rt, MipsLabel* label);
640   void Bltu(Register rs, Register rt, MipsLabel* label);
641   void Bgeu(Register rs, Register rt, MipsLabel* label);
642   void Bc1f(MipsLabel* label);  // R2
643   void Bc1f(int cc, MipsLabel* label);  // R2
644   void Bc1t(MipsLabel* label);  // R2
645   void Bc1t(int cc, MipsLabel* label);  // R2
646   void Bc1eqz(FRegister ft, MipsLabel* label);  // R6
647   void Bc1nez(FRegister ft, MipsLabel* label);  // R6
648 
649   void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
650   void AdjustBaseAndOffset(Register& base,
651                            int32_t& offset,
652                            bool is_doubleword,
653                            bool is_float = false);
654   void AdjustBaseOffsetAndElementSizeShift(Register& base,
655                                            int32_t& offset,
656                                            int& element_size_shift);
657 
658  private:
659   // This will be used as an argument for loads/stores
660   // when there is no need for implicit null checks.
661   struct NoImplicitNullChecker {
operatorNoImplicitNullChecker662     void operator()() const {}
663   };
664 
665  public:
666   template <typename ImplicitNullChecker = NoImplicitNullChecker>
667   void StoreConstToOffset(StoreOperandType type,
668                           int64_t value,
669                           Register base,
670                           int32_t offset,
671                           Register temp,
672                           ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
673     // We permit `base` and `temp` to coincide (however, we check that neither is AT),
674     // in which case the `base` register may be overwritten in the process.
675     CHECK_NE(temp, AT);  // Must not use AT as temp, so as not to overwrite the adjusted base.
676     AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword));
677     uint32_t low = Low32Bits(value);
678     uint32_t high = High32Bits(value);
679     Register reg;
680     // If the adjustment left `base` unchanged and equal to `temp`, we can't use `temp`
681     // to load and hold the value but we can use AT instead as AT hasn't been used yet.
682     // Otherwise, `temp` can be used for the value. And if `temp` is the same as the
683     // original `base` (that is, `base` prior to the adjustment), the original `base`
684     // register will be overwritten.
685     if (base == temp) {
686       temp = AT;
687     }
688     if (low == 0) {
689       reg = ZERO;
690     } else {
691       reg = temp;
692       LoadConst32(reg, low);
693     }
694     switch (type) {
695       case kStoreByte:
696         Sb(reg, base, offset);
697         break;
698       case kStoreHalfword:
699         Sh(reg, base, offset);
700         break;
701       case kStoreWord:
702         Sw(reg, base, offset);
703         break;
704       case kStoreDoubleword:
705         Sw(reg, base, offset);
706         null_checker();
707         if (high == 0) {
708           reg = ZERO;
709         } else {
710           reg = temp;
711           if (high != low) {
712             LoadConst32(reg, high);
713           }
714         }
715         Sw(reg, base, offset + kMipsWordSize);
716         break;
717       default:
718         LOG(FATAL) << "UNREACHABLE";
719     }
720     if (type != kStoreDoubleword) {
721       null_checker();
722     }
723   }
724 
725   template <typename ImplicitNullChecker = NoImplicitNullChecker>
726   void LoadFromOffset(LoadOperandType type,
727                       Register reg,
728                       Register base,
729                       int32_t offset,
730                       ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
731     AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kLoadDoubleword));
732     switch (type) {
733       case kLoadSignedByte:
734         Lb(reg, base, offset);
735         break;
736       case kLoadUnsignedByte:
737         Lbu(reg, base, offset);
738         break;
739       case kLoadSignedHalfword:
740         Lh(reg, base, offset);
741         break;
742       case kLoadUnsignedHalfword:
743         Lhu(reg, base, offset);
744         break;
745       case kLoadWord:
746         Lw(reg, base, offset);
747         break;
748       case kLoadDoubleword:
749         if (reg == base) {
750           // This will clobber the base when loading the lower register. Since we have to load the
751           // higher register as well, this will fail. Solution: reverse the order.
752           Lw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
753           null_checker();
754           Lw(reg, base, offset);
755         } else {
756           Lw(reg, base, offset);
757           null_checker();
758           Lw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
759         }
760         break;
761       default:
762         LOG(FATAL) << "UNREACHABLE";
763     }
764     if (type != kLoadDoubleword) {
765       null_checker();
766     }
767   }
768 
769   template <typename ImplicitNullChecker = NoImplicitNullChecker>
770   void LoadSFromOffset(FRegister reg,
771                        Register base,
772                        int32_t offset,
773                        ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
774     AdjustBaseAndOffset(base, offset, /* is_doubleword */ false, /* is_float */ true);
775     Lwc1(reg, base, offset);
776     null_checker();
777   }
778 
779   template <typename ImplicitNullChecker = NoImplicitNullChecker>
780   void LoadDFromOffset(FRegister reg,
781                        Register base,
782                        int32_t offset,
783                        ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
784     AdjustBaseAndOffset(base, offset, /* is_doubleword */ true, /* is_float */ true);
785     if (IsAligned<kMipsDoublewordSize>(offset)) {
786       Ldc1(reg, base, offset);
787       null_checker();
788     } else {
789       if (Is32BitFPU()) {
790         Lwc1(reg, base, offset);
791         null_checker();
792         Lwc1(static_cast<FRegister>(reg + 1), base, offset + kMipsWordSize);
793       } else {
794         // 64-bit FPU.
795         Lwc1(reg, base, offset);
796         null_checker();
797         Lw(T8, base, offset + kMipsWordSize);
798         Mthc1(T8, reg);
799       }
800     }
801   }
802 
803   template <typename ImplicitNullChecker = NoImplicitNullChecker>
804   void LoadQFromOffset(FRegister reg,
805                        Register base,
806                        int32_t offset,
807                        ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
808     int element_size_shift = -1;
809     AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift);
810     switch (element_size_shift) {
811       case TIMES_1: LdB(static_cast<VectorRegister>(reg), base, offset); break;
812       case TIMES_2: LdH(static_cast<VectorRegister>(reg), base, offset); break;
813       case TIMES_4: LdW(static_cast<VectorRegister>(reg), base, offset); break;
814       case TIMES_8: LdD(static_cast<VectorRegister>(reg), base, offset); break;
815       default:
816         LOG(FATAL) << "UNREACHABLE";
817     }
818     null_checker();
819   }
820 
821   template <typename ImplicitNullChecker = NoImplicitNullChecker>
822   void StoreToOffset(StoreOperandType type,
823                      Register reg,
824                      Register base,
825                      int32_t offset,
826                      ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
827     // Must not use AT as `reg`, so as not to overwrite the value being stored
828     // with the adjusted `base`.
829     CHECK_NE(reg, AT);
830     AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword));
831     switch (type) {
832       case kStoreByte:
833         Sb(reg, base, offset);
834         break;
835       case kStoreHalfword:
836         Sh(reg, base, offset);
837         break;
838       case kStoreWord:
839         Sw(reg, base, offset);
840         break;
841       case kStoreDoubleword:
842         CHECK_NE(reg, base);
843         CHECK_NE(static_cast<Register>(reg + 1), base);
844         Sw(reg, base, offset);
845         null_checker();
846         Sw(static_cast<Register>(reg + 1), base, offset + kMipsWordSize);
847         break;
848       default:
849         LOG(FATAL) << "UNREACHABLE";
850     }
851     if (type != kStoreDoubleword) {
852       null_checker();
853     }
854   }
855 
856   template <typename ImplicitNullChecker = NoImplicitNullChecker>
857   void StoreSToOffset(FRegister reg,
858                       Register base,
859                       int32_t offset,
860                       ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
861     AdjustBaseAndOffset(base, offset, /* is_doubleword */ false, /* is_float */ true);
862     Swc1(reg, base, offset);
863     null_checker();
864   }
865 
866   template <typename ImplicitNullChecker = NoImplicitNullChecker>
867   void StoreDToOffset(FRegister reg,
868                       Register base,
869                       int32_t offset,
870                       ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
871     AdjustBaseAndOffset(base, offset, /* is_doubleword */ true, /* is_float */ true);
872     if (IsAligned<kMipsDoublewordSize>(offset)) {
873       Sdc1(reg, base, offset);
874       null_checker();
875     } else {
876       if (Is32BitFPU()) {
877         Swc1(reg, base, offset);
878         null_checker();
879         Swc1(static_cast<FRegister>(reg + 1), base, offset + kMipsWordSize);
880       } else {
881         // 64-bit FPU.
882         Mfhc1(T8, reg);
883         Swc1(reg, base, offset);
884         null_checker();
885         Sw(T8, base, offset + kMipsWordSize);
886       }
887     }
888   }
889 
890   template <typename ImplicitNullChecker = NoImplicitNullChecker>
891   void StoreQToOffset(FRegister reg,
892                       Register base,
893                       int32_t offset,
894                       ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
895     int element_size_shift = -1;
896     AdjustBaseOffsetAndElementSizeShift(base, offset, element_size_shift);
897     switch (element_size_shift) {
898       case TIMES_1: StB(static_cast<VectorRegister>(reg), base, offset); break;
899       case TIMES_2: StH(static_cast<VectorRegister>(reg), base, offset); break;
900       case TIMES_4: StW(static_cast<VectorRegister>(reg), base, offset); break;
901       case TIMES_8: StD(static_cast<VectorRegister>(reg), base, offset); break;
902       default:
903         LOG(FATAL) << "UNREACHABLE";
904     }
905     null_checker();
906   }
907 
908   void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
909   void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
910   void LoadDFromOffset(FRegister reg, Register base, int32_t offset);
911   void LoadQFromOffset(FRegister reg, Register base, int32_t offset);
912   void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset);
913   void StoreSToOffset(FRegister reg, Register base, int32_t offset);
914   void StoreDToOffset(FRegister reg, Register base, int32_t offset);
915   void StoreQToOffset(FRegister reg, Register base, int32_t offset);
916 
917   // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
918   void Emit(uint32_t value);
919 
920   // Push/pop composite routines.
921   void Push(Register rs);
922   void Pop(Register rd);
923   void PopAndReturn(Register rd, Register rt);
924 
925   //
926   // Heap poisoning.
927   //
928 
929   // Poison a heap reference contained in `src` and store it in `dst`.
PoisonHeapReference(Register dst,Register src)930   void PoisonHeapReference(Register dst, Register src) {
931     // dst = -src.
932     Subu(dst, ZERO, src);
933   }
934   // Poison a heap reference contained in `reg`.
PoisonHeapReference(Register reg)935   void PoisonHeapReference(Register reg) {
936     // reg = -reg.
937     PoisonHeapReference(reg, reg);
938   }
939   // Unpoison a heap reference contained in `reg`.
UnpoisonHeapReference(Register reg)940   void UnpoisonHeapReference(Register reg) {
941     // reg = -reg.
942     Subu(reg, ZERO, reg);
943   }
944   // Poison a heap reference contained in `reg` if heap poisoning is enabled.
MaybePoisonHeapReference(Register reg)945   void MaybePoisonHeapReference(Register reg) {
946     if (kPoisonHeapReferences) {
947       PoisonHeapReference(reg);
948     }
949   }
950   // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
MaybeUnpoisonHeapReference(Register reg)951   void MaybeUnpoisonHeapReference(Register reg) {
952     if (kPoisonHeapReferences) {
953       UnpoisonHeapReference(reg);
954     }
955   }
956 
Bind(Label * label)957   void Bind(Label* label) OVERRIDE {
958     Bind(down_cast<MipsLabel*>(label));
959   }
Jump(Label * label ATTRIBUTE_UNUSED)960   void Jump(Label* label ATTRIBUTE_UNUSED) OVERRIDE {
961     UNIMPLEMENTED(FATAL) << "Do not use Jump for MIPS";
962   }
963 
964   // Don't warn about a different virtual Bind/Jump in the base class.
965   using JNIBase::Bind;
966   using JNIBase::Jump;
967 
968   // Create a new label that can be used with Jump/Bind calls.
CreateLabel()969   std::unique_ptr<JNIMacroLabel> CreateLabel() OVERRIDE {
970     LOG(FATAL) << "Not implemented on MIPS32";
971     UNREACHABLE();
972   }
973   // Emit an unconditional jump to the label.
Jump(JNIMacroLabel * label ATTRIBUTE_UNUSED)974   void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED) OVERRIDE {
975     LOG(FATAL) << "Not implemented on MIPS32";
976     UNREACHABLE();
977   }
978   // Emit a conditional jump to the label by applying a unary condition test to the register.
Jump(JNIMacroLabel * label ATTRIBUTE_UNUSED,JNIMacroUnaryCondition cond ATTRIBUTE_UNUSED,ManagedRegister test ATTRIBUTE_UNUSED)979   void Jump(JNIMacroLabel* label ATTRIBUTE_UNUSED,
980             JNIMacroUnaryCondition cond ATTRIBUTE_UNUSED,
981             ManagedRegister test ATTRIBUTE_UNUSED) OVERRIDE {
982     LOG(FATAL) << "Not implemented on MIPS32";
983     UNREACHABLE();
984   }
985 
986   // Code at this offset will serve as the target for the Jump call.
Bind(JNIMacroLabel * label ATTRIBUTE_UNUSED)987   void Bind(JNIMacroLabel* label ATTRIBUTE_UNUSED) OVERRIDE {
988     LOG(FATAL) << "Not implemented on MIPS32";
989     UNREACHABLE();
990   }
991 
992   // Create a new literal with a given value.
993   // NOTE: Force the template parameter to be explicitly specified.
994   template <typename T>
NewLiteral(typename Identity<T>::type value)995   Literal* NewLiteral(typename Identity<T>::type value) {
996     static_assert(std::is_integral<T>::value, "T must be an integral type.");
997     return NewLiteral(sizeof(value), reinterpret_cast<const uint8_t*>(&value));
998   }
999 
1000   // Load label address using the base register (for R2 only) or using PC-relative loads
1001   // (for R6 only; base_reg must be ZERO). To be used with data labels in the literal /
1002   // jump table area only and not with regular code labels.
1003   void LoadLabelAddress(Register dest_reg, Register base_reg, MipsLabel* label);
1004 
1005   // Create a new literal with the given data.
1006   Literal* NewLiteral(size_t size, const uint8_t* data);
1007 
1008   // Load literal using the base register (for R2 only) or using PC-relative loads
1009   // (for R6 only; base_reg must be ZERO).
1010   void LoadLiteral(Register dest_reg, Register base_reg, Literal* literal);
1011 
1012   // Create a jump table for the given labels that will be emitted when finalizing.
1013   // When the table is emitted, offsets will be relative to the location of the table.
1014   // The table location is determined by the location of its label (the label precedes
1015   // the table data) and should be loaded using LoadLabelAddress().
1016   JumpTable* CreateJumpTable(std::vector<MipsLabel*>&& labels);
1017 
1018   //
1019   // Overridden common assembler high-level functionality.
1020   //
1021 
1022   // Emit code that will create an activation on the stack.
1023   void BuildFrame(size_t frame_size,
1024                   ManagedRegister method_reg,
1025                   ArrayRef<const ManagedRegister> callee_save_regs,
1026                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
1027 
1028   // Emit code that will remove an activation from the stack.
1029   void RemoveFrame(size_t frame_size, ArrayRef<const ManagedRegister> callee_save_regs)
1030       OVERRIDE;
1031 
1032   void IncreaseFrameSize(size_t adjust) OVERRIDE;
1033   void DecreaseFrameSize(size_t adjust) OVERRIDE;
1034 
1035   // Store routines.
1036   void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE;
1037   void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
1038   void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
1039 
1040   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE;
1041 
1042   void StoreStackOffsetToThread(ThreadOffset32 thr_offs,
1043                                 FrameOffset fr_offs,
1044                                 ManagedRegister mscratch) OVERRIDE;
1045 
1046   void StoreStackPointerToThread(ThreadOffset32 thr_offs) OVERRIDE;
1047 
1048   void StoreSpanning(FrameOffset dest,
1049                      ManagedRegister msrc,
1050                      FrameOffset in_off,
1051                      ManagedRegister mscratch) OVERRIDE;
1052 
1053   // Load routines.
1054   void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE;
1055 
1056   void LoadFromThread(ManagedRegister mdest, ThreadOffset32 src, size_t size) OVERRIDE;
1057 
1058   void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
1059 
1060   void LoadRef(ManagedRegister mdest,
1061                ManagedRegister base,
1062                MemberOffset offs,
1063                bool unpoison_reference) OVERRIDE;
1064 
1065   void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE;
1066 
1067   void LoadRawPtrFromThread(ManagedRegister mdest, ThreadOffset32 offs) OVERRIDE;
1068 
1069   // Copying routines.
1070   void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE;
1071 
1072   void CopyRawPtrFromThread(FrameOffset fr_offs,
1073                             ThreadOffset32 thr_offs,
1074                             ManagedRegister mscratch) OVERRIDE;
1075 
1076   void CopyRawPtrToThread(ThreadOffset32 thr_offs,
1077                           FrameOffset fr_offs,
1078                           ManagedRegister mscratch) OVERRIDE;
1079 
1080   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE;
1081 
1082   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE;
1083 
1084   void Copy(FrameOffset dest,
1085             ManagedRegister src_base,
1086             Offset src_offset,
1087             ManagedRegister mscratch,
1088             size_t size) OVERRIDE;
1089 
1090   void Copy(ManagedRegister dest_base,
1091             Offset dest_offset,
1092             FrameOffset src,
1093             ManagedRegister mscratch,
1094             size_t size) OVERRIDE;
1095 
1096   void Copy(FrameOffset dest,
1097             FrameOffset src_base,
1098             Offset src_offset,
1099             ManagedRegister mscratch,
1100             size_t size) OVERRIDE;
1101 
1102   void Copy(ManagedRegister dest,
1103             Offset dest_offset,
1104             ManagedRegister src,
1105             Offset src_offset,
1106             ManagedRegister mscratch,
1107             size_t size) OVERRIDE;
1108 
1109   void Copy(FrameOffset dest,
1110             Offset dest_offset,
1111             FrameOffset src,
1112             Offset src_offset,
1113             ManagedRegister mscratch,
1114             size_t size) OVERRIDE;
1115 
1116   void MemoryBarrier(ManagedRegister) OVERRIDE;
1117 
1118   // Sign extension.
1119   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
1120 
1121   // Zero extension.
1122   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
1123 
1124   // Exploit fast access in managed code to Thread::Current().
1125   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
1126   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) OVERRIDE;
1127 
1128   // Set up out_reg to hold a Object** into the handle scope, or to be null if the
1129   // value is null and null_allowed. in_reg holds a possibly stale reference
1130   // that can be used to avoid loading the handle scope entry to see if the value is
1131   // null.
1132   void CreateHandleScopeEntry(ManagedRegister out_reg,
1133                               FrameOffset handlescope_offset,
1134                               ManagedRegister in_reg,
1135                               bool null_allowed) OVERRIDE;
1136 
1137   // Set up out_off to hold a Object** into the handle scope, or to be null if the
1138   // value is null and null_allowed.
1139   void CreateHandleScopeEntry(FrameOffset out_off,
1140                               FrameOffset handlescope_offset,
1141                               ManagedRegister mscratch,
1142                               bool null_allowed) OVERRIDE;
1143 
1144   // src holds a handle scope entry (Object**) load this into dst.
1145   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
1146 
1147   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
1148   // know that src may not be null.
1149   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
1150   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
1151 
1152   // Call to address held at [base+offset].
1153   void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE;
1154   void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE;
1155   void CallFromThread(ThreadOffset32 offset, ManagedRegister mscratch) OVERRIDE;
1156 
1157   // Generate code to check if Thread::Current()->exception_ is non-null
1158   // and branch to a ExceptionSlowPath if it is.
1159   void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) OVERRIDE;
1160 
1161   // Emit slow paths queued during assembly and promote short branches to long if needed.
1162   void FinalizeCode() OVERRIDE;
1163 
1164   // Emit branches and finalize all instructions.
1165   void FinalizeInstructions(const MemoryRegion& region);
1166 
1167   // Returns the (always-)current location of a label (can be used in class CodeGeneratorMIPS,
1168   // must be used instead of MipsLabel::GetPosition()).
1169   uint32_t GetLabelLocation(const MipsLabel* label) const;
1170 
1171   // Get the final position of a label after local fixup based on the old position
1172   // recorded before FinalizeCode().
1173   uint32_t GetAdjustedPosition(uint32_t old_position);
1174 
1175   // R2 doesn't have PC-relative addressing, which we need to access literals. We simulate it by
1176   // reading the PC value into a general-purpose register with the NAL instruction and then loading
1177   // literals through this base register. The code generator calls this method (at most once per
1178   // method being compiled) to bind a label to the location for which the PC value is acquired.
1179   // The assembler then computes literal offsets relative to this label.
1180   void BindPcRelBaseLabel();
1181 
1182   // Returns the location of the label bound with BindPcRelBaseLabel().
1183   uint32_t GetPcRelBaseLabelLocation() const;
1184 
1185   // Note that PC-relative literal loads are handled as pseudo branches because they need very
1186   // similar relocation and may similarly expand in size to accomodate for larger offsets relative
1187   // to PC.
1188   enum BranchCondition {
1189     kCondLT,
1190     kCondGE,
1191     kCondLE,
1192     kCondGT,
1193     kCondLTZ,
1194     kCondGEZ,
1195     kCondLEZ,
1196     kCondGTZ,
1197     kCondEQ,
1198     kCondNE,
1199     kCondEQZ,
1200     kCondNEZ,
1201     kCondLTU,
1202     kCondGEU,
1203     kCondF,    // Floating-point predicate false.
1204     kCondT,    // Floating-point predicate true.
1205     kUncond,
1206   };
1207   friend std::ostream& operator<<(std::ostream& os, const BranchCondition& rhs);
1208 
1209   // Enables or disables instruction reordering (IOW, automatic filling of delay slots)
1210   // similarly to ".set reorder" / ".set noreorder" in traditional MIPS assembly.
1211   // Returns the last state, which may be useful for temporary enabling/disabling of
1212   // reordering.
1213   bool SetReorder(bool enable);
1214 
1215  private:
1216   // Description of the last instruction in terms of input and output registers.
1217   // Used to make the decision of moving the instruction into a delay slot.
1218   struct DelaySlot {
1219     DelaySlot();
1220     // Encoded instruction that may be used to fill the delay slot or 0
1221     // (0 conveniently represents NOP).
1222     uint32_t instruction_;
1223     // Mask of output GPRs for the instruction.
1224     uint32_t gpr_outs_mask_;
1225     // Mask of input GPRs for the instruction.
1226     uint32_t gpr_ins_mask_;
1227     // Mask of output FPRs for the instruction.
1228     uint32_t fpr_outs_mask_;
1229     // Mask of input FPRs for the instruction.
1230     uint32_t fpr_ins_mask_;
1231     // Mask of output FPU condition code flags for the instruction.
1232     uint32_t cc_outs_mask_;
1233     // Mask of input FPU condition code flags for the instruction.
1234     uint32_t cc_ins_mask_;
1235     // Branches never operate on the LO and HI registers, hence there's
1236     // no mask for LO and HI.
1237   };
1238 
1239   // Delay slot finite state machine's (DS FSM's) state. The FSM state is updated
1240   // upon every new instruction and label generated. The FSM detects instructions
1241   // suitable for delay slots and immediately preceded with labels. These are target
1242   // instructions for branches. If an unconditional R2 branch does not get its delay
1243   // slot filled with the immediately preceding instruction, it may instead get the
1244   // slot filled with the target instruction (the branch will need its offset
1245   // incremented past the target instruction). We call this "absorption". The FSM
1246   // records PCs of the target instructions suitable for this optimization.
1247   enum DsFsmState {
1248     kExpectingLabel,
1249     kExpectingInstruction,
1250     kExpectingCommit
1251   };
1252   friend std::ostream& operator<<(std::ostream& os, const DsFsmState& rhs);
1253 
1254   class Branch {
1255    public:
1256     enum Type {
1257       // R2 short branches.
1258       kUncondBranch,
1259       kCondBranch,
1260       kCall,
1261       // R2 near label.
1262       kLabel,
1263       // R2 near literal.
1264       kLiteral,
1265       // R2 long branches.
1266       kLongUncondBranch,
1267       kLongCondBranch,
1268       kLongCall,
1269       // R2 far label.
1270       kFarLabel,
1271       // R2 far literal.
1272       kFarLiteral,
1273       // R6 short branches.
1274       kR6UncondBranch,
1275       kR6CondBranch,
1276       kR6Call,
1277       // R6 near label.
1278       kR6Label,
1279       // R6 near literal.
1280       kR6Literal,
1281       // R6 long branches.
1282       kR6LongUncondBranch,
1283       kR6LongCondBranch,
1284       kR6LongCall,
1285       // R6 far label.
1286       kR6FarLabel,
1287       // R6 far literal.
1288       kR6FarLiteral,
1289     };
1290     // Bit sizes of offsets defined as enums to minimize chance of typos.
1291     enum OffsetBits {
1292       kOffset16 = 16,
1293       kOffset18 = 18,
1294       kOffset21 = 21,
1295       kOffset23 = 23,
1296       kOffset28 = 28,
1297       kOffset32 = 32,
1298     };
1299 
1300     static constexpr uint32_t kUnresolved = 0xffffffff;  // Unresolved target_
1301     static constexpr int32_t kMaxBranchLength = 32;
1302     static constexpr int32_t kMaxBranchSize = kMaxBranchLength * sizeof(uint32_t);
1303     // The following two instruction encodings can never legally occur in branch delay
1304     // slots and are used as markers.
1305     //
1306     // kUnfilledDelaySlot means that the branch may use either the preceding or the target
1307     // instruction to fill its delay slot (the latter is only possible with unconditional
1308     // R2 branches and is termed here as "absorption").
1309     static constexpr uint32_t kUnfilledDelaySlot = 0x10000000;  // beq zero, zero, 0.
1310     // kUnfillableDelaySlot means that the branch cannot use an instruction (other than NOP)
1311     // to fill its delay slot. This is only used for unconditional R2 branches to prevent
1312     // absorption of the target instruction when reordering is disabled.
1313     static constexpr uint32_t kUnfillableDelaySlot = 0x13FF0000;  // beq ra, ra, 0.
1314 
1315     struct BranchInfo {
1316       // Branch length as a number of 4-byte-long instructions.
1317       uint32_t length;
1318       // Ordinal number (0-based) of the first (or the only) instruction that contains the branch's
1319       // PC-relative offset (or its most significant 16-bit half, which goes first).
1320       uint32_t instr_offset;
1321       // Different MIPS instructions with PC-relative offsets apply said offsets to slightly
1322       // different origins, e.g. to PC or PC+4. Encode the origin distance (as a number of 4-byte
1323       // instructions) from the instruction containing the offset.
1324       uint32_t pc_org;
1325       // How large (in bits) a PC-relative offset can be for a given type of branch (kR6CondBranch
1326       // is an exception: use kOffset23 for beqzc/bnezc).
1327       OffsetBits offset_size;
1328       // Some MIPS instructions with PC-relative offsets shift the offset by 2. Encode the shift
1329       // count.
1330       int offset_shift;
1331     };
1332     static const BranchInfo branch_info_[/* Type */];
1333 
1334     // Unconditional branch or call.
1335     Branch(bool is_r6, uint32_t location, uint32_t target, bool is_call);
1336     // Conditional branch.
1337     Branch(bool is_r6,
1338            uint32_t location,
1339            uint32_t target,
1340            BranchCondition condition,
1341            Register lhs_reg,
1342            Register rhs_reg);
1343     // Label address (in literal area) or literal.
1344     Branch(bool is_r6,
1345            uint32_t location,
1346            Register dest_reg,
1347            Register base_reg,
1348            Type label_or_literal_type);
1349 
1350     // Some conditional branches with lhs = rhs are effectively NOPs, while some
1351     // others are effectively unconditional. MIPSR6 conditional branches require lhs != rhs.
1352     // So, we need a way to identify such branches in order to emit no instructions for them
1353     // or change them to unconditional.
1354     static bool IsNop(BranchCondition condition, Register lhs, Register rhs);
1355     static bool IsUncond(BranchCondition condition, Register lhs, Register rhs);
1356 
1357     static BranchCondition OppositeCondition(BranchCondition cond);
1358 
1359     Type GetType() const;
1360     BranchCondition GetCondition() const;
1361     Register GetLeftRegister() const;
1362     Register GetRightRegister() const;
1363     uint32_t GetTarget() const;
1364     uint32_t GetLocation() const;
1365     uint32_t GetOldLocation() const;
1366     uint32_t GetPrecedingInstructionLength(Type type) const;
1367     uint32_t GetPrecedingInstructionSize(Type type) const;
1368     uint32_t GetLength() const;
1369     uint32_t GetOldLength() const;
1370     uint32_t GetSize() const;
1371     uint32_t GetOldSize() const;
1372     uint32_t GetEndLocation() const;
1373     uint32_t GetOldEndLocation() const;
1374     bool IsLong() const;
1375     bool IsResolved() const;
1376 
1377     // Various helpers for branch delay slot management.
1378     bool CanHaveDelayedInstruction(const DelaySlot& delay_slot) const;
1379     void SetDelayedInstruction(uint32_t instruction);
1380     uint32_t GetDelayedInstruction() const;
1381     void DecrementLocations();
1382 
1383     // Returns the bit size of the signed offset that the branch instruction can handle.
1384     OffsetBits GetOffsetSize() const;
1385 
1386     // Calculates the distance between two byte locations in the assembler buffer and
1387     // returns the number of bits needed to represent the distance as a signed integer.
1388     //
1389     // Branch instructions have signed offsets of 16, 19 (addiupc), 21 (beqzc/bnezc),
1390     // and 26 (bc) bits, which are additionally shifted left 2 positions at run time.
1391     //
1392     // Composite branches (made of several instructions) with longer reach have 32-bit
1393     // offsets encoded as 2 16-bit "halves" in two instructions (high half goes first).
1394     // The composite branches cover the range of PC + +/-2GB on MIPS32 CPUs. However,
1395     // the range is not end-to-end on MIPS64 (unless addresses are forced to zero- or
1396     // sign-extend from 32 to 64 bits by the appropriate CPU configuration).
1397     // Consider the following implementation of a long unconditional branch, for
1398     // example:
1399     //
1400     //   auipc at, offset_31_16  // at = pc + sign_extend(offset_31_16) << 16
1401     //   jic   at, offset_15_0   // pc = at + sign_extend(offset_15_0)
1402     //
1403     // Both of the above instructions take 16-bit signed offsets as immediate operands.
1404     // When bit 15 of offset_15_0 is 1, it effectively causes subtraction of 0x10000
1405     // due to sign extension. This must be compensated for by incrementing offset_31_16
1406     // by 1. offset_31_16 can only be incremented by 1 if it's not 0x7FFF. If it is
1407     // 0x7FFF, adding 1 will overflow the positive offset into the negative range.
1408     // Therefore, the long branch range is something like from PC - 0x80000000 to
1409     // PC + 0x7FFF7FFF, IOW, shorter by 32KB on one side.
1410     //
1411     // The returned values are therefore: 18, 21, 23, 28 and 32. There's also a special
1412     // case with the addiu instruction and a 16 bit offset.
1413     static OffsetBits GetOffsetSizeNeeded(uint32_t location, uint32_t target);
1414 
1415     // Resolve a branch when the target is known.
1416     void Resolve(uint32_t target);
1417 
1418     // Relocate a branch by a given delta if needed due to expansion of this or another
1419     // branch at a given location by this delta (just changes location_ and target_).
1420     void Relocate(uint32_t expand_location, uint32_t delta);
1421 
1422     // If the branch is short, changes its type to long.
1423     void PromoteToLong();
1424 
1425     // If necessary, updates the type by promoting a short branch to a long branch
1426     // based on the branch location and target. Returns the amount (in bytes) by
1427     // which the branch size has increased.
1428     // max_short_distance caps the maximum distance between location_ and target_
1429     // that is allowed for short branches. This is for debugging/testing purposes.
1430     // max_short_distance = 0 forces all short branches to become long.
1431     // Use the implicit default argument when not debugging/testing.
1432     uint32_t PromoteIfNeeded(uint32_t location,
1433                              uint32_t max_short_distance = std::numeric_limits<uint32_t>::max());
1434 
1435     // Returns the location of the instruction(s) containing the offset.
1436     uint32_t GetOffsetLocation() const;
1437 
1438     // Calculates and returns the offset ready for encoding in the branch instruction(s).
1439     uint32_t GetOffset(uint32_t location) const;
1440 
1441    private:
1442     // Completes branch construction by determining and recording its type.
1443     void InitializeType(Type initial_type, bool is_r6);
1444     // Helper for the above.
1445     void InitShortOrLong(OffsetBits ofs_size, Type short_type, Type long_type);
1446 
1447     uint32_t old_location_;         // Offset into assembler buffer in bytes.
1448     uint32_t location_;             // Offset into assembler buffer in bytes.
1449     uint32_t target_;               // Offset into assembler buffer in bytes.
1450 
1451     uint32_t lhs_reg_;              // Left-hand side register in conditional branches or
1452                                     // FPU condition code. Destination register in literals.
1453     uint32_t rhs_reg_;              // Right-hand side register in conditional branches.
1454                                     // Base register in literals (ZERO on R6).
1455     BranchCondition condition_;     // Condition for conditional branches.
1456 
1457     Type type_;                     // Current type of the branch.
1458     Type old_type_;                 // Initial type of the branch.
1459 
1460     uint32_t delayed_instruction_;  // Encoded instruction for the delay slot or
1461                                     // kUnfilledDelaySlot if none but fillable or
1462                                     // kUnfillableDelaySlot if none and unfillable
1463                                     // (the latter is only used for unconditional R2
1464                                     // branches).
1465   };
1466   friend std::ostream& operator<<(std::ostream& os, const Branch::Type& rhs);
1467   friend std::ostream& operator<<(std::ostream& os, const Branch::OffsetBits& rhs);
1468 
1469   uint32_t EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct);
1470   uint32_t EmitI(int opcode, Register rs, Register rt, uint16_t imm);
1471   uint32_t EmitI21(int opcode, Register rs, uint32_t imm21);
1472   uint32_t EmitI26(int opcode, uint32_t imm26);
1473   uint32_t EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct);
1474   uint32_t EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm);
1475   void EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16);
1476   void EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21);
1477   uint32_t EmitMsa3R(int operation,
1478                      int df,
1479                      VectorRegister wt,
1480                      VectorRegister ws,
1481                      VectorRegister wd,
1482                      int minor_opcode);
1483   uint32_t EmitMsaBIT(int operation,
1484                       int df_m,
1485                       VectorRegister ws,
1486                       VectorRegister wd,
1487                       int minor_opcode);
1488   uint32_t EmitMsaELM(int operation,
1489                       int df_n,
1490                       VectorRegister ws,
1491                       VectorRegister wd,
1492                       int minor_opcode);
1493   uint32_t EmitMsaMI10(int s10, Register rs, VectorRegister wd, int minor_opcode, int df);
1494   uint32_t EmitMsaI10(int operation, int df, int i10, VectorRegister wd, int minor_opcode);
1495   uint32_t EmitMsa2R(int operation, int df, VectorRegister ws, VectorRegister wd, int minor_opcode);
1496   uint32_t EmitMsa2RF(int operation,
1497                       int df,
1498                       VectorRegister ws,
1499                       VectorRegister wd,
1500                       int minor_opcode);
1501 
1502   void Buncond(MipsLabel* label);
1503   void Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs = ZERO);
1504   void Call(MipsLabel* label);
1505   void FinalizeLabeledBranch(MipsLabel* label);
1506 
1507   // Various helpers for branch delay slot management.
1508   void DsFsmInstr(uint32_t instruction,
1509                   uint32_t gpr_outs_mask,
1510                   uint32_t gpr_ins_mask,
1511                   uint32_t fpr_outs_mask,
1512                   uint32_t fpr_ins_mask,
1513                   uint32_t cc_outs_mask,
1514                   uint32_t cc_ins_mask);
1515   void DsFsmInstrNop(uint32_t instruction);
1516   void DsFsmInstrRrr(uint32_t instruction, Register out, Register in1, Register in2);
1517   void DsFsmInstrRrrr(uint32_t instruction, Register in1_out, Register in2, Register in3);
1518   void DsFsmInstrFff(uint32_t instruction, FRegister out, FRegister in1, FRegister in2);
1519   void DsFsmInstrFfff(uint32_t instruction, FRegister in1_out, FRegister in2, FRegister in3);
1520   void DsFsmInstrFffr(uint32_t instruction, FRegister in1_out, FRegister in2, Register in3);
1521   void DsFsmInstrRf(uint32_t instruction, Register out, FRegister in);
1522   void DsFsmInstrFr(uint32_t instruction, FRegister out, Register in);
1523   void DsFsmInstrFR(uint32_t instruction, FRegister in1, Register in2);
1524   void DsFsmInstrCff(uint32_t instruction, int cc_out, FRegister in1, FRegister in2);
1525   void DsFsmInstrRrrc(uint32_t instruction, Register in1_out, Register in2, int cc_in);
1526   void DsFsmInstrFffc(uint32_t instruction, FRegister in1_out, FRegister in2, int cc_in);
1527   void DsFsmLabel();
1528   void DsFsmCommitLabel();
1529   void DsFsmDropLabel();
1530   void MoveInstructionToDelaySlot(Branch& branch);
1531   bool CanExchangeWithSlt(Register rs, Register rt) const;
1532   void ExchangeWithSlt(const DelaySlot& forwarded_slot);
1533   void GenerateSltForCondBranch(bool unsigned_slt, Register rs, Register rt);
1534 
1535   Branch* GetBranch(uint32_t branch_id);
1536   const Branch* GetBranch(uint32_t branch_id) const;
1537   uint32_t GetBranchLocationOrPcRelBase(const MipsAssembler::Branch* branch) const;
1538   uint32_t GetBranchOrPcRelBaseForEncoding(const MipsAssembler::Branch* branch) const;
1539 
1540   void EmitLiterals();
1541   void ReserveJumpTableSpace();
1542   void EmitJumpTables();
1543   void PromoteBranches();
1544   void EmitBranch(Branch* branch);
1545   void EmitBranches();
1546   void PatchCFI(size_t number_of_delayed_adjust_pcs);
1547 
1548   // Emits exception block.
1549   void EmitExceptionPoll(MipsExceptionSlowPath* exception);
1550 
HasMsa()1551   bool HasMsa() const {
1552     return has_msa_;
1553   }
1554 
IsR6()1555   bool IsR6() const {
1556     if (isa_features_ != nullptr) {
1557       return isa_features_->IsR6();
1558     } else {
1559       return false;
1560     }
1561   }
1562 
Is32BitFPU()1563   bool Is32BitFPU() const {
1564     if (isa_features_ != nullptr) {
1565       return isa_features_->Is32BitFloatingPoint();
1566     } else {
1567       return true;
1568     }
1569   }
1570 
1571   // List of exception blocks to generate at the end of the code cache.
1572   std::vector<MipsExceptionSlowPath> exception_blocks_;
1573 
1574   std::vector<Branch> branches_;
1575 
1576   // Whether appending instructions at the end of the buffer or overwriting the existing ones.
1577   bool overwriting_;
1578   // The current overwrite location.
1579   uint32_t overwrite_location_;
1580 
1581   // Whether instruction reordering (IOW, automatic filling of delay slots) is enabled.
1582   bool reordering_;
1583   // Information about the last instruction that may be used to fill a branch delay slot.
1584   DelaySlot delay_slot_;
1585   // Delay slot FSM state.
1586   DsFsmState ds_fsm_state_;
1587   // PC of the current labeled target instruction.
1588   uint32_t ds_fsm_target_pc_;
1589   // PCs of labeled target instructions.
1590   std::vector<uint32_t> ds_fsm_target_pcs_;
1591 
1592   // Use std::deque<> for literal labels to allow insertions at the end
1593   // without invalidating pointers and references to existing elements.
1594   ArenaDeque<Literal> literals_;
1595 
1596   // Jump table list.
1597   ArenaDeque<JumpTable> jump_tables_;
1598 
1599   // There's no PC-relative addressing on MIPS32R2. So, in order to access literals relative to PC
1600   // we get PC using the NAL instruction. This label marks the position within the assembler buffer
1601   // that PC (from NAL) points to.
1602   MipsLabel pc_rel_base_label_;
1603 
1604   // Data for GetAdjustedPosition(), see the description there.
1605   uint32_t last_position_adjustment_;
1606   uint32_t last_old_position_;
1607   uint32_t last_branch_id_;
1608 
1609   const bool has_msa_;
1610 
1611   const MipsInstructionSetFeatures* isa_features_;
1612 
1613   DISALLOW_COPY_AND_ASSIGN(MipsAssembler);
1614 };
1615 
1616 }  // namespace mips
1617 }  // namespace art
1618 
1619 #endif  // ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
1620