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 <utility>
21 #include <vector>
22 
23 #include "arch/mips/instruction_set_features_mips.h"
24 #include "base/macros.h"
25 #include "constants_mips.h"
26 #include "globals.h"
27 #include "managed_register_mips.h"
28 #include "offsets.h"
29 #include "utils/assembler.h"
30 #include "utils/label.h"
31 
32 namespace art {
33 namespace mips {
34 
35 static constexpr size_t kMipsWordSize = 4;
36 static constexpr size_t kMipsDoublewordSize = 8;
37 
38 enum LoadOperandType {
39   kLoadSignedByte,
40   kLoadUnsignedByte,
41   kLoadSignedHalfword,
42   kLoadUnsignedHalfword,
43   kLoadWord,
44   kLoadDoubleword
45 };
46 
47 enum StoreOperandType {
48   kStoreByte,
49   kStoreHalfword,
50   kStoreWord,
51   kStoreDoubleword
52 };
53 
54 // Used to test the values returned by ClassS/ClassD.
55 enum FPClassMaskType {
56   kSignalingNaN      = 0x001,
57   kQuietNaN          = 0x002,
58   kNegativeInfinity  = 0x004,
59   kNegativeNormal    = 0x008,
60   kNegativeSubnormal = 0x010,
61   kNegativeZero      = 0x020,
62   kPositiveInfinity  = 0x040,
63   kPositiveNormal    = 0x080,
64   kPositiveSubnormal = 0x100,
65   kPositiveZero      = 0x200,
66 };
67 
68 class MipsLabel : public Label {
69  public:
MipsLabel()70   MipsLabel() : prev_branch_id_plus_one_(0) {}
71 
MipsLabel(MipsLabel && src)72   MipsLabel(MipsLabel&& src)
73       : Label(std::move(src)), prev_branch_id_plus_one_(src.prev_branch_id_plus_one_) {}
74 
75  private:
76   uint32_t prev_branch_id_plus_one_;  // To get distance from preceding branch, if any.
77 
78   friend class MipsAssembler;
79   DISALLOW_COPY_AND_ASSIGN(MipsLabel);
80 };
81 
82 // Slowpath entered when Thread::Current()->_exception is non-null.
83 class MipsExceptionSlowPath {
84  public:
MipsExceptionSlowPath(MipsManagedRegister scratch,size_t stack_adjust)85   explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
86       : scratch_(scratch), stack_adjust_(stack_adjust) {}
87 
MipsExceptionSlowPath(MipsExceptionSlowPath && src)88   MipsExceptionSlowPath(MipsExceptionSlowPath&& src)
89       : scratch_(src.scratch_),
90         stack_adjust_(src.stack_adjust_),
91         exception_entry_(std::move(src.exception_entry_)) {}
92 
93  private:
Entry()94   MipsLabel* Entry() { return &exception_entry_; }
95   const MipsManagedRegister scratch_;
96   const size_t stack_adjust_;
97   MipsLabel exception_entry_;
98 
99   friend class MipsAssembler;
100   DISALLOW_COPY_AND_ASSIGN(MipsExceptionSlowPath);
101 };
102 
103 class MipsAssembler FINAL : public Assembler {
104  public:
105   explicit MipsAssembler(ArenaAllocator* arena,
106                          const MipsInstructionSetFeatures* instruction_set_features = nullptr)
Assembler(arena)107       : Assembler(arena),
108         overwriting_(false),
109         overwrite_location_(0),
110         last_position_adjustment_(0),
111         last_old_position_(0),
112         last_branch_id_(0),
113         isa_features_(instruction_set_features) {
114     cfi().DelayEmittingAdvancePCs();
115   }
116 
~MipsAssembler()117   virtual ~MipsAssembler() {
118     for (auto& branch : branches_) {
119       CHECK(branch.IsResolved());
120     }
121   }
122 
123   // Emit Machine Instructions.
124   void Addu(Register rd, Register rs, Register rt);
125   void Addiu(Register rt, Register rs, uint16_t imm16);
126   void Subu(Register rd, Register rs, Register rt);
127 
128   void MultR2(Register rs, Register rt);  // R2
129   void MultuR2(Register rs, Register rt);  // R2
130   void DivR2(Register rs, Register rt);  // R2
131   void DivuR2(Register rs, Register rt);  // R2
132   void MulR2(Register rd, Register rs, Register rt);  // R2
133   void DivR2(Register rd, Register rs, Register rt);  // R2
134   void ModR2(Register rd, Register rs, Register rt);  // R2
135   void DivuR2(Register rd, Register rs, Register rt);  // R2
136   void ModuR2(Register rd, Register rs, Register rt);  // R2
137   void MulR6(Register rd, Register rs, Register rt);  // R6
138   void MuhR6(Register rd, Register rs, Register rt);  // R6
139   void MuhuR6(Register rd, Register rs, Register rt);  // R6
140   void DivR6(Register rd, Register rs, Register rt);  // R6
141   void ModR6(Register rd, Register rs, Register rt);  // R6
142   void DivuR6(Register rd, Register rs, Register rt);  // R6
143   void ModuR6(Register rd, Register rs, Register rt);  // R6
144 
145   void And(Register rd, Register rs, Register rt);
146   void Andi(Register rt, Register rs, uint16_t imm16);
147   void Or(Register rd, Register rs, Register rt);
148   void Ori(Register rt, Register rs, uint16_t imm16);
149   void Xor(Register rd, Register rs, Register rt);
150   void Xori(Register rt, Register rs, uint16_t imm16);
151   void Nor(Register rd, Register rs, Register rt);
152 
153   void Movz(Register rd, Register rs, Register rt);  // R2
154   void Movn(Register rd, Register rs, Register rt);  // R2
155   void Seleqz(Register rd, Register rs, Register rt);  // R6
156   void Selnez(Register rd, Register rs, Register rt);  // R6
157   void ClzR6(Register rd, Register rs);
158   void ClzR2(Register rd, Register rs);
159   void CloR6(Register rd, Register rs);
160   void CloR2(Register rd, Register rs);
161 
162   void Seb(Register rd, Register rt);  // R2+
163   void Seh(Register rd, Register rt);  // R2+
164   void Wsbh(Register rd, Register rt);  // R2+
165   void Bitswap(Register rd, Register rt);  // R6
166 
167   void Sll(Register rd, Register rt, int shamt);
168   void Srl(Register rd, Register rt, int shamt);
169   void Rotr(Register rd, Register rt, int shamt);  // R2+
170   void Sra(Register rd, Register rt, int shamt);
171   void Sllv(Register rd, Register rt, Register rs);
172   void Srlv(Register rd, Register rt, Register rs);
173   void Rotrv(Register rd, Register rt, Register rs);  // R2+
174   void Srav(Register rd, Register rt, Register rs);
175   void Ext(Register rd, Register rt, int pos, int size);  // R2+
176   void Ins(Register rd, Register rt, int pos, int size);  // R2+
177 
178   void Lb(Register rt, Register rs, uint16_t imm16);
179   void Lh(Register rt, Register rs, uint16_t imm16);
180   void Lw(Register rt, Register rs, uint16_t imm16);
181   void Lwl(Register rt, Register rs, uint16_t imm16);
182   void Lwr(Register rt, Register rs, uint16_t imm16);
183   void Lbu(Register rt, Register rs, uint16_t imm16);
184   void Lhu(Register rt, Register rs, uint16_t imm16);
185   void Lui(Register rt, uint16_t imm16);
186   void Sync(uint32_t stype);
187   void Mfhi(Register rd);  // R2
188   void Mflo(Register rd);  // R2
189 
190   void Sb(Register rt, Register rs, uint16_t imm16);
191   void Sh(Register rt, Register rs, uint16_t imm16);
192   void Sw(Register rt, Register rs, uint16_t imm16);
193   void Swl(Register rt, Register rs, uint16_t imm16);
194   void Swr(Register rt, Register rs, uint16_t imm16);
195 
196   void LlR2(Register rt, Register base, int16_t imm16 = 0);
197   void ScR2(Register rt, Register base, int16_t imm16 = 0);
198   void LlR6(Register rt, Register base, int16_t imm9 = 0);
199   void ScR6(Register rt, Register base, int16_t imm9 = 0);
200 
201   void Slt(Register rd, Register rs, Register rt);
202   void Sltu(Register rd, Register rs, Register rt);
203   void Slti(Register rt, Register rs, uint16_t imm16);
204   void Sltiu(Register rt, Register rs, uint16_t imm16);
205 
206   void B(uint16_t imm16);
207   void Beq(Register rs, Register rt, uint16_t imm16);
208   void Bne(Register rs, Register rt, uint16_t imm16);
209   void Beqz(Register rt, uint16_t imm16);
210   void Bnez(Register rt, uint16_t imm16);
211   void Bltz(Register rt, uint16_t imm16);
212   void Bgez(Register rt, uint16_t imm16);
213   void Blez(Register rt, uint16_t imm16);
214   void Bgtz(Register rt, uint16_t imm16);
215   void Bc1f(uint16_t imm16);  // R2
216   void Bc1f(int cc, uint16_t imm16);  // R2
217   void Bc1t(uint16_t imm16);  // R2
218   void Bc1t(int cc, uint16_t imm16);  // R2
219   void J(uint32_t addr26);
220   void Jal(uint32_t addr26);
221   void Jalr(Register rd, Register rs);
222   void Jalr(Register rs);
223   void Jr(Register rs);
224   void Nal();
225   void Auipc(Register rs, uint16_t imm16);  // R6
226   void Addiupc(Register rs, uint32_t imm19);  // R6
227   void Bc(uint32_t imm26);  // R6
228   void Jic(Register rt, uint16_t imm16);  // R6
229   void Jialc(Register rt, uint16_t imm16);  // R6
230   void Bltc(Register rs, Register rt, uint16_t imm16);  // R6
231   void Bltzc(Register rt, uint16_t imm16);  // R6
232   void Bgtzc(Register rt, uint16_t imm16);  // R6
233   void Bgec(Register rs, Register rt, uint16_t imm16);  // R6
234   void Bgezc(Register rt, uint16_t imm16);  // R6
235   void Blezc(Register rt, uint16_t imm16);  // R6
236   void Bltuc(Register rs, Register rt, uint16_t imm16);  // R6
237   void Bgeuc(Register rs, Register rt, uint16_t imm16);  // R6
238   void Beqc(Register rs, Register rt, uint16_t imm16);  // R6
239   void Bnec(Register rs, Register rt, uint16_t imm16);  // R6
240   void Beqzc(Register rs, uint32_t imm21);  // R6
241   void Bnezc(Register rs, uint32_t imm21);  // R6
242   void Bc1eqz(FRegister ft, uint16_t imm16);  // R6
243   void Bc1nez(FRegister ft, uint16_t imm16);  // R6
244 
245   void AddS(FRegister fd, FRegister fs, FRegister ft);
246   void SubS(FRegister fd, FRegister fs, FRegister ft);
247   void MulS(FRegister fd, FRegister fs, FRegister ft);
248   void DivS(FRegister fd, FRegister fs, FRegister ft);
249   void AddD(FRegister fd, FRegister fs, FRegister ft);
250   void SubD(FRegister fd, FRegister fs, FRegister ft);
251   void MulD(FRegister fd, FRegister fs, FRegister ft);
252   void DivD(FRegister fd, FRegister fs, FRegister ft);
253   void SqrtS(FRegister fd, FRegister fs);
254   void SqrtD(FRegister fd, FRegister fs);
255   void AbsS(FRegister fd, FRegister fs);
256   void AbsD(FRegister fd, FRegister fs);
257   void MovS(FRegister fd, FRegister fs);
258   void MovD(FRegister fd, FRegister fs);
259   void NegS(FRegister fd, FRegister fs);
260   void NegD(FRegister fd, FRegister fs);
261 
262   void CunS(FRegister fs, FRegister ft);  // R2
263   void CunS(int cc, FRegister fs, FRegister ft);  // R2
264   void CeqS(FRegister fs, FRegister ft);  // R2
265   void CeqS(int cc, FRegister fs, FRegister ft);  // R2
266   void CueqS(FRegister fs, FRegister ft);  // R2
267   void CueqS(int cc, FRegister fs, FRegister ft);  // R2
268   void ColtS(FRegister fs, FRegister ft);  // R2
269   void ColtS(int cc, FRegister fs, FRegister ft);  // R2
270   void CultS(FRegister fs, FRegister ft);  // R2
271   void CultS(int cc, FRegister fs, FRegister ft);  // R2
272   void ColeS(FRegister fs, FRegister ft);  // R2
273   void ColeS(int cc, FRegister fs, FRegister ft);  // R2
274   void CuleS(FRegister fs, FRegister ft);  // R2
275   void CuleS(int cc, FRegister fs, FRegister ft);  // R2
276   void CunD(FRegister fs, FRegister ft);  // R2
277   void CunD(int cc, FRegister fs, FRegister ft);  // R2
278   void CeqD(FRegister fs, FRegister ft);  // R2
279   void CeqD(int cc, FRegister fs, FRegister ft);  // R2
280   void CueqD(FRegister fs, FRegister ft);  // R2
281   void CueqD(int cc, FRegister fs, FRegister ft);  // R2
282   void ColtD(FRegister fs, FRegister ft);  // R2
283   void ColtD(int cc, FRegister fs, FRegister ft);  // R2
284   void CultD(FRegister fs, FRegister ft);  // R2
285   void CultD(int cc, FRegister fs, FRegister ft);  // R2
286   void ColeD(FRegister fs, FRegister ft);  // R2
287   void ColeD(int cc, FRegister fs, FRegister ft);  // R2
288   void CuleD(FRegister fs, FRegister ft);  // R2
289   void CuleD(int cc, FRegister fs, FRegister ft);  // R2
290   void CmpUnS(FRegister fd, FRegister fs, FRegister ft);  // R6
291   void CmpEqS(FRegister fd, FRegister fs, FRegister ft);  // R6
292   void CmpUeqS(FRegister fd, FRegister fs, FRegister ft);  // R6
293   void CmpLtS(FRegister fd, FRegister fs, FRegister ft);  // R6
294   void CmpUltS(FRegister fd, FRegister fs, FRegister ft);  // R6
295   void CmpLeS(FRegister fd, FRegister fs, FRegister ft);  // R6
296   void CmpUleS(FRegister fd, FRegister fs, FRegister ft);  // R6
297   void CmpOrS(FRegister fd, FRegister fs, FRegister ft);  // R6
298   void CmpUneS(FRegister fd, FRegister fs, FRegister ft);  // R6
299   void CmpNeS(FRegister fd, FRegister fs, FRegister ft);  // R6
300   void CmpUnD(FRegister fd, FRegister fs, FRegister ft);  // R6
301   void CmpEqD(FRegister fd, FRegister fs, FRegister ft);  // R6
302   void CmpUeqD(FRegister fd, FRegister fs, FRegister ft);  // R6
303   void CmpLtD(FRegister fd, FRegister fs, FRegister ft);  // R6
304   void CmpUltD(FRegister fd, FRegister fs, FRegister ft);  // R6
305   void CmpLeD(FRegister fd, FRegister fs, FRegister ft);  // R6
306   void CmpUleD(FRegister fd, FRegister fs, FRegister ft);  // R6
307   void CmpOrD(FRegister fd, FRegister fs, FRegister ft);  // R6
308   void CmpUneD(FRegister fd, FRegister fs, FRegister ft);  // R6
309   void CmpNeD(FRegister fd, FRegister fs, FRegister ft);  // R6
310   void Movf(Register rd, Register rs, int cc = 0);  // R2
311   void Movt(Register rd, Register rs, int cc = 0);  // R2
312   void MovfS(FRegister fd, FRegister fs, int cc = 0);  // R2
313   void MovfD(FRegister fd, FRegister fs, int cc = 0);  // R2
314   void MovtS(FRegister fd, FRegister fs, int cc = 0);  // R2
315   void MovtD(FRegister fd, FRegister fs, int cc = 0);  // R2
316   void SelS(FRegister fd, FRegister fs, FRegister ft);  // R6
317   void SelD(FRegister fd, FRegister fs, FRegister ft);  // R6
318   void ClassS(FRegister fd, FRegister fs);  // R6
319   void ClassD(FRegister fd, FRegister fs);  // R6
320   void MinS(FRegister fd, FRegister fs, FRegister ft);  // R6
321   void MinD(FRegister fd, FRegister fs, FRegister ft);  // R6
322   void MaxS(FRegister fd, FRegister fs, FRegister ft);  // R6
323   void MaxD(FRegister fd, FRegister fs, FRegister ft);  // R6
324 
325   void TruncLS(FRegister fd, FRegister fs);  // R2+, FR=1
326   void TruncLD(FRegister fd, FRegister fs);  // R2+, FR=1
327   void TruncWS(FRegister fd, FRegister fs);
328   void TruncWD(FRegister fd, FRegister fs);
329   void Cvtsw(FRegister fd, FRegister fs);
330   void Cvtdw(FRegister fd, FRegister fs);
331   void Cvtsd(FRegister fd, FRegister fs);
332   void Cvtds(FRegister fd, FRegister fs);
333   void Cvtsl(FRegister fd, FRegister fs);  // R2+, FR=1
334   void Cvtdl(FRegister fd, FRegister fs);  // R2+, FR=1
335   void FloorWS(FRegister fd, FRegister fs);
336   void FloorWD(FRegister fd, FRegister fs);
337 
338   void Mfc1(Register rt, FRegister fs);
339   void Mtc1(Register rt, FRegister fs);
340   void Mfhc1(Register rt, FRegister fs);
341   void Mthc1(Register rt, FRegister fs);
342   void MoveFromFpuHigh(Register rt, FRegister fs);
343   void MoveToFpuHigh(Register rt, FRegister fs);
344   void Lwc1(FRegister ft, Register rs, uint16_t imm16);
345   void Ldc1(FRegister ft, Register rs, uint16_t imm16);
346   void Swc1(FRegister ft, Register rs, uint16_t imm16);
347   void Sdc1(FRegister ft, Register rs, uint16_t imm16);
348 
349   void Break();
350   void Nop();
351   void Move(Register rd, Register rs);
352   void Clear(Register rd);
353   void Not(Register rd, Register rs);
354 
355   // Higher level composite instructions.
356   void LoadConst32(Register rd, int32_t value);
357   void LoadConst64(Register reg_hi, Register reg_lo, int64_t value);
358   void LoadDConst64(FRegister rd, int64_t value, Register temp);
359   void LoadSConst32(FRegister r, int32_t value, Register temp);
360   void StoreConst32ToOffset(int32_t value, Register base, int32_t offset, Register temp);
361   void StoreConst64ToOffset(int64_t value, Register base, int32_t offset, Register temp);
362   void Addiu32(Register rt, Register rs, int32_t value, Register rtmp = AT);
363 
364   // These will generate R2 branches or R6 branches as appropriate.
365   void Bind(MipsLabel* label);
366   void B(MipsLabel* label);
367   void Jalr(MipsLabel* label, Register indirect_reg);
368   void Beq(Register rs, Register rt, MipsLabel* label);
369   void Bne(Register rs, Register rt, MipsLabel* label);
370   void Beqz(Register rt, MipsLabel* label);
371   void Bnez(Register rt, MipsLabel* label);
372   void Bltz(Register rt, MipsLabel* label);
373   void Bgez(Register rt, MipsLabel* label);
374   void Blez(Register rt, MipsLabel* label);
375   void Bgtz(Register rt, MipsLabel* label);
376   void Blt(Register rs, Register rt, MipsLabel* label);
377   void Bge(Register rs, Register rt, MipsLabel* label);
378   void Bltu(Register rs, Register rt, MipsLabel* label);
379   void Bgeu(Register rs, Register rt, MipsLabel* label);
380   void Bc1f(MipsLabel* label);  // R2
381   void Bc1f(int cc, MipsLabel* label);  // R2
382   void Bc1t(MipsLabel* label);  // R2
383   void Bc1t(int cc, MipsLabel* label);  // R2
384   void Bc1eqz(FRegister ft, MipsLabel* label);  // R6
385   void Bc1nez(FRegister ft, MipsLabel* label);  // R6
386 
387   void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
388   void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
389   void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
390   void LoadDFromOffset(FRegister reg, Register base, int32_t offset);
391   void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset);
392   void StoreSToOffset(FRegister reg, Register base, int32_t offset);
393   void StoreDToOffset(FRegister reg, Register base, int32_t offset);
394 
395   // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
396   void Emit(uint32_t value);
397 
398   // Push/pop composite routines.
399   void Push(Register rs);
400   void Pop(Register rd);
401   void PopAndReturn(Register rd, Register rt);
402 
Bind(Label * label)403   void Bind(Label* label) OVERRIDE {
404     Bind(down_cast<MipsLabel*>(label));
405   }
Jump(Label * label ATTRIBUTE_UNUSED)406   void Jump(Label* label ATTRIBUTE_UNUSED) OVERRIDE {
407     UNIMPLEMENTED(FATAL) << "Do not use Jump for MIPS";
408   }
409 
410   //
411   // Overridden common assembler high-level functionality.
412   //
413 
414   // Emit code that will create an activation on the stack.
415   void BuildFrame(size_t frame_size,
416                   ManagedRegister method_reg,
417                   const std::vector<ManagedRegister>& callee_save_regs,
418                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
419 
420   // Emit code that will remove an activation from the stack.
421   void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
422       OVERRIDE;
423 
424   void IncreaseFrameSize(size_t adjust) OVERRIDE;
425   void DecreaseFrameSize(size_t adjust) OVERRIDE;
426 
427   // Store routines.
428   void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE;
429   void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
430   void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
431 
432   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE;
433 
434   void StoreImmediateToThread32(ThreadOffset<kMipsWordSize> dest,
435                                 uint32_t imm,
436                                 ManagedRegister mscratch) OVERRIDE;
437 
438   void StoreStackOffsetToThread32(ThreadOffset<kMipsWordSize> thr_offs,
439                                   FrameOffset fr_offs,
440                                   ManagedRegister mscratch) OVERRIDE;
441 
442   void StoreStackPointerToThread32(ThreadOffset<kMipsWordSize> thr_offs) OVERRIDE;
443 
444   void StoreSpanning(FrameOffset dest,
445                      ManagedRegister msrc,
446                      FrameOffset in_off,
447                      ManagedRegister mscratch) OVERRIDE;
448 
449   // Load routines.
450   void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE;
451 
452   void LoadFromThread32(ManagedRegister mdest,
453                         ThreadOffset<kMipsWordSize> src,
454                         size_t size) OVERRIDE;
455 
456   void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
457 
458   void LoadRef(ManagedRegister mdest,
459                ManagedRegister base,
460                MemberOffset offs,
461                bool unpoison_reference) OVERRIDE;
462 
463   void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE;
464 
465   void LoadRawPtrFromThread32(ManagedRegister mdest, ThreadOffset<kMipsWordSize> offs) OVERRIDE;
466 
467   // Copying routines.
468   void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE;
469 
470   void CopyRawPtrFromThread32(FrameOffset fr_offs,
471                               ThreadOffset<kMipsWordSize> thr_offs,
472                               ManagedRegister mscratch) OVERRIDE;
473 
474   void CopyRawPtrToThread32(ThreadOffset<kMipsWordSize> thr_offs,
475                             FrameOffset fr_offs,
476                             ManagedRegister mscratch) OVERRIDE;
477 
478   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE;
479 
480   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE;
481 
482   void Copy(FrameOffset dest,
483             ManagedRegister src_base,
484             Offset src_offset,
485             ManagedRegister mscratch,
486             size_t size) OVERRIDE;
487 
488   void Copy(ManagedRegister dest_base,
489             Offset dest_offset,
490             FrameOffset src,
491             ManagedRegister mscratch,
492             size_t size) OVERRIDE;
493 
494   void Copy(FrameOffset dest,
495             FrameOffset src_base,
496             Offset src_offset,
497             ManagedRegister mscratch,
498             size_t size) OVERRIDE;
499 
500   void Copy(ManagedRegister dest,
501             Offset dest_offset,
502             ManagedRegister src,
503             Offset src_offset,
504             ManagedRegister mscratch,
505             size_t size) OVERRIDE;
506 
507   void Copy(FrameOffset dest,
508             Offset dest_offset,
509             FrameOffset src,
510             Offset src_offset,
511             ManagedRegister mscratch,
512             size_t size) OVERRIDE;
513 
514   void MemoryBarrier(ManagedRegister) OVERRIDE;
515 
516   // Sign extension.
517   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
518 
519   // Zero extension.
520   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
521 
522   // Exploit fast access in managed code to Thread::Current().
523   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
524   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) OVERRIDE;
525 
526   // Set up out_reg to hold a Object** into the handle scope, or to be null if the
527   // value is null and null_allowed. in_reg holds a possibly stale reference
528   // that can be used to avoid loading the handle scope entry to see if the value is
529   // null.
530   void CreateHandleScopeEntry(ManagedRegister out_reg,
531                               FrameOffset handlescope_offset,
532                               ManagedRegister in_reg,
533                               bool null_allowed) OVERRIDE;
534 
535   // Set up out_off to hold a Object** into the handle scope, or to be null if the
536   // value is null and null_allowed.
537   void CreateHandleScopeEntry(FrameOffset out_off,
538                               FrameOffset handlescope_offset,
539                               ManagedRegister mscratch,
540                               bool null_allowed) OVERRIDE;
541 
542   // src holds a handle scope entry (Object**) load this into dst.
543   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
544 
545   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
546   // know that src may not be null.
547   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
548   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
549 
550   // Call to address held at [base+offset].
551   void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE;
552   void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE;
553   void CallFromThread32(ThreadOffset<kMipsWordSize> offset, ManagedRegister mscratch) OVERRIDE;
554 
555   // Generate code to check if Thread::Current()->exception_ is non-null
556   // and branch to a ExceptionSlowPath if it is.
557   void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) OVERRIDE;
558 
559   // Emit slow paths queued during assembly and promote short branches to long if needed.
560   void FinalizeCode() OVERRIDE;
561 
562   // Emit branches and finalize all instructions.
563   void FinalizeInstructions(const MemoryRegion& region);
564 
565   // Returns the (always-)current location of a label (can be used in class CodeGeneratorMIPS,
566   // must be used instead of MipsLabel::GetPosition()).
567   uint32_t GetLabelLocation(MipsLabel* label) const;
568 
569   // Get the final position of a label after local fixup based on the old position
570   // recorded before FinalizeCode().
571   uint32_t GetAdjustedPosition(uint32_t old_position);
572 
573   enum BranchCondition {
574     kCondLT,
575     kCondGE,
576     kCondLE,
577     kCondGT,
578     kCondLTZ,
579     kCondGEZ,
580     kCondLEZ,
581     kCondGTZ,
582     kCondEQ,
583     kCondNE,
584     kCondEQZ,
585     kCondNEZ,
586     kCondLTU,
587     kCondGEU,
588     kCondF,    // Floating-point predicate false.
589     kCondT,    // Floating-point predicate true.
590     kUncond,
591   };
592   friend std::ostream& operator<<(std::ostream& os, const BranchCondition& rhs);
593 
594  private:
595   class Branch {
596    public:
597     enum Type {
598       // R2 short branches.
599       kUncondBranch,
600       kCondBranch,
601       kCall,
602       // R2 long branches.
603       kLongUncondBranch,
604       kLongCondBranch,
605       kLongCall,
606       // R6 short branches.
607       kR6UncondBranch,
608       kR6CondBranch,
609       kR6Call,
610       // R6 long branches.
611       kR6LongUncondBranch,
612       kR6LongCondBranch,
613       kR6LongCall,
614     };
615     // Bit sizes of offsets defined as enums to minimize chance of typos.
616     enum OffsetBits {
617       kOffset16 = 16,
618       kOffset18 = 18,
619       kOffset21 = 21,
620       kOffset23 = 23,
621       kOffset28 = 28,
622       kOffset32 = 32,
623     };
624 
625     static constexpr uint32_t kUnresolved = 0xffffffff;  // Unresolved target_
626     static constexpr int32_t kMaxBranchLength = 32;
627     static constexpr int32_t kMaxBranchSize = kMaxBranchLength * sizeof(uint32_t);
628 
629     struct BranchInfo {
630       // Branch length as a number of 4-byte-long instructions.
631       uint32_t length;
632       // Ordinal number (0-based) of the first (or the only) instruction that contains the branch's
633       // PC-relative offset (or its most significant 16-bit half, which goes first).
634       uint32_t instr_offset;
635       // Different MIPS instructions with PC-relative offsets apply said offsets to slightly
636       // different origins, e.g. to PC or PC+4. Encode the origin distance (as a number of 4-byte
637       // instructions) from the instruction containing the offset.
638       uint32_t pc_org;
639       // How large (in bits) a PC-relative offset can be for a given type of branch (kR6CondBranch
640       // is an exception: use kOffset23 for beqzc/bnezc).
641       OffsetBits offset_size;
642       // Some MIPS instructions with PC-relative offsets shift the offset by 2. Encode the shift
643       // count.
644       int offset_shift;
645     };
646     static const BranchInfo branch_info_[/* Type */];
647 
648     // Unconditional branch.
649     Branch(bool is_r6, uint32_t location, uint32_t target);
650     // Conditional branch.
651     Branch(bool is_r6,
652            uint32_t location,
653            uint32_t target,
654            BranchCondition condition,
655            Register lhs_reg,
656            Register rhs_reg = ZERO);
657     // Call (branch and link) that stores the target address in a given register (i.e. T9).
658     Branch(bool is_r6, uint32_t location, uint32_t target, Register indirect_reg);
659 
660     // Some conditional branches with lhs = rhs are effectively NOPs, while some
661     // others are effectively unconditional. MIPSR6 conditional branches require lhs != rhs.
662     // So, we need a way to identify such branches in order to emit no instructions for them
663     // or change them to unconditional.
664     static bool IsNop(BranchCondition condition, Register lhs, Register rhs);
665     static bool IsUncond(BranchCondition condition, Register lhs, Register rhs);
666 
667     static BranchCondition OppositeCondition(BranchCondition cond);
668 
669     Type GetType() const;
670     BranchCondition GetCondition() const;
671     Register GetLeftRegister() const;
672     Register GetRightRegister() const;
673     uint32_t GetTarget() const;
674     uint32_t GetLocation() const;
675     uint32_t GetOldLocation() const;
676     uint32_t GetLength() const;
677     uint32_t GetOldLength() const;
678     uint32_t GetSize() const;
679     uint32_t GetOldSize() const;
680     uint32_t GetEndLocation() const;
681     uint32_t GetOldEndLocation() const;
682     bool IsLong() const;
683     bool IsResolved() const;
684 
685     // Returns the bit size of the signed offset that the branch instruction can handle.
686     OffsetBits GetOffsetSize() const;
687 
688     // Calculates the distance between two byte locations in the assembler buffer and
689     // returns the number of bits needed to represent the distance as a signed integer.
690     //
691     // Branch instructions have signed offsets of 16, 19 (addiupc), 21 (beqzc/bnezc),
692     // and 26 (bc) bits, which are additionally shifted left 2 positions at run time.
693     //
694     // Composite branches (made of several instructions) with longer reach have 32-bit
695     // offsets encoded as 2 16-bit "halves" in two instructions (high half goes first).
696     // The composite branches cover the range of PC + +/-2GB on MIPS32 CPUs. However,
697     // the range is not end-to-end on MIPS64 (unless addresses are forced to zero- or
698     // sign-extend from 32 to 64 bits by the appropriate CPU configuration).
699     // Consider the following implementation of a long unconditional branch, for
700     // example:
701     //
702     //   auipc at, offset_31_16  // at = pc + sign_extend(offset_31_16) << 16
703     //   jic   at, offset_15_0   // pc = at + sign_extend(offset_15_0)
704     //
705     // Both of the above instructions take 16-bit signed offsets as immediate operands.
706     // When bit 15 of offset_15_0 is 1, it effectively causes subtraction of 0x10000
707     // due to sign extension. This must be compensated for by incrementing offset_31_16
708     // by 1. offset_31_16 can only be incremented by 1 if it's not 0x7FFF. If it is
709     // 0x7FFF, adding 1 will overflow the positive offset into the negative range.
710     // Therefore, the long branch range is something like from PC - 0x80000000 to
711     // PC + 0x7FFF7FFF, IOW, shorter by 32KB on one side.
712     //
713     // The returned values are therefore: 18, 21, 23, 28 and 32. There's also a special
714     // case with the addiu instruction and a 16 bit offset.
715     static OffsetBits GetOffsetSizeNeeded(uint32_t location, uint32_t target);
716 
717     // Resolve a branch when the target is known.
718     void Resolve(uint32_t target);
719 
720     // Relocate a branch by a given delta if needed due to expansion of this or another
721     // branch at a given location by this delta (just changes location_ and target_).
722     void Relocate(uint32_t expand_location, uint32_t delta);
723 
724     // If the branch is short, changes its type to long.
725     void PromoteToLong();
726 
727     // If necessary, updates the type by promoting a short branch to a long branch
728     // based on the branch location and target. Returns the amount (in bytes) by
729     // which the branch size has increased.
730     // max_short_distance caps the maximum distance between location_ and target_
731     // that is allowed for short branches. This is for debugging/testing purposes.
732     // max_short_distance = 0 forces all short branches to become long.
733     // Use the implicit default argument when not debugging/testing.
734     uint32_t PromoteIfNeeded(uint32_t max_short_distance = std::numeric_limits<uint32_t>::max());
735 
736     // Returns the location of the instruction(s) containing the offset.
737     uint32_t GetOffsetLocation() const;
738 
739     // Calculates and returns the offset ready for encoding in the branch instruction(s).
740     uint32_t GetOffset() const;
741 
742    private:
743     // Completes branch construction by determining and recording its type.
744     void InitializeType(bool is_call, bool is_r6);
745     // Helper for the above.
746     void InitShortOrLong(OffsetBits ofs_size, Type short_type, Type long_type);
747 
748     uint32_t old_location_;      // Offset into assembler buffer in bytes.
749     uint32_t location_;          // Offset into assembler buffer in bytes.
750     uint32_t target_;            // Offset into assembler buffer in bytes.
751 
752     uint32_t lhs_reg_;           // Left-hand side register in conditional branches or
753                                  // indirect call register.
754     uint32_t rhs_reg_;           // Right-hand side register in conditional branches.
755     BranchCondition condition_;  // Condition for conditional branches.
756 
757     Type type_;                  // Current type of the branch.
758     Type old_type_;              // Initial type of the branch.
759   };
760   friend std::ostream& operator<<(std::ostream& os, const Branch::Type& rhs);
761   friend std::ostream& operator<<(std::ostream& os, const Branch::OffsetBits& rhs);
762 
763   void EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct);
764   void EmitI(int opcode, Register rs, Register rt, uint16_t imm);
765   void EmitI21(int opcode, Register rs, uint32_t imm21);
766   void EmitI26(int opcode, uint32_t imm26);
767   void EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct);
768   void EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm);
769   void EmitBcondR2(BranchCondition cond, Register rs, Register rt, uint16_t imm16);
770   void EmitBcondR6(BranchCondition cond, Register rs, Register rt, uint32_t imm16_21);
771 
772   void Buncond(MipsLabel* label);
773   void Bcond(MipsLabel* label, BranchCondition condition, Register lhs, Register rhs = ZERO);
774   void Call(MipsLabel* label, Register indirect_reg);
775   void FinalizeLabeledBranch(MipsLabel* label);
776 
777   Branch* GetBranch(uint32_t branch_id);
778   const Branch* GetBranch(uint32_t branch_id) const;
779 
780   void PromoteBranches();
781   void EmitBranch(Branch* branch);
782   void EmitBranches();
783   void PatchCFI(size_t number_of_delayed_adjust_pcs);
784 
785   // Emits exception block.
786   void EmitExceptionPoll(MipsExceptionSlowPath* exception);
787 
IsR6()788   bool IsR6() const {
789     if (isa_features_ != nullptr) {
790       return isa_features_->IsR6();
791     } else {
792       return false;
793     }
794   }
795 
Is32BitFPU()796   bool Is32BitFPU() const {
797     if (isa_features_ != nullptr) {
798       return isa_features_->Is32BitFloatingPoint();
799     } else {
800       return true;
801     }
802   }
803 
804   // List of exception blocks to generate at the end of the code cache.
805   std::vector<MipsExceptionSlowPath> exception_blocks_;
806 
807   std::vector<Branch> branches_;
808 
809   // Whether appending instructions at the end of the buffer or overwriting the existing ones.
810   bool overwriting_;
811   // The current overwrite location.
812   uint32_t overwrite_location_;
813 
814   // Data for AdjustedPosition(), see the description there.
815   uint32_t last_position_adjustment_;
816   uint32_t last_old_position_;
817   uint32_t last_branch_id_;
818 
819   const MipsInstructionSetFeatures* isa_features_;
820 
821   DISALLOW_COPY_AND_ASSIGN(MipsAssembler);
822 };
823 
824 }  // namespace mips
825 }  // namespace art
826 
827 #endif  // ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
828