1 /*
2  * Copyright (C) 2014 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_MIPS64_ASSEMBLER_MIPS64_H_
18 #define ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_
19 
20 #include <vector>
21 
22 #include "base/macros.h"
23 #include "constants_mips64.h"
24 #include "globals.h"
25 #include "managed_register_mips64.h"
26 #include "utils/assembler.h"
27 #include "offsets.h"
28 
29 namespace art {
30 namespace mips64 {
31 
32 enum LoadOperandType {
33   kLoadSignedByte,
34   kLoadUnsignedByte,
35   kLoadSignedHalfword,
36   kLoadUnsignedHalfword,
37   kLoadWord,
38   kLoadUnsignedWord,
39   kLoadDoubleword
40 };
41 
42 enum StoreOperandType {
43   kStoreByte,
44   kStoreHalfword,
45   kStoreWord,
46   kStoreDoubleword
47 };
48 
49 class Mips64Assembler FINAL : public Assembler {
50  public:
Mips64Assembler()51   Mips64Assembler() {}
~Mips64Assembler()52   virtual ~Mips64Assembler() {}
53 
54   // Emit Machine Instructions.
55   void Add(GpuRegister rd, GpuRegister rs, GpuRegister rt);
56   void Addi(GpuRegister rt, GpuRegister rs, uint16_t imm16);
57   void Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt);
58   void Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
59   void Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // MIPS64
60   void Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16);  // MIPS64
61   void Sub(GpuRegister rd, GpuRegister rs, GpuRegister rt);
62   void Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt);
63   void Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // MIPS64
64 
65   void MultR2(GpuRegister rs, GpuRegister rt);  // R2
66   void MultuR2(GpuRegister rs, GpuRegister rt);  // R2
67   void DivR2(GpuRegister rs, GpuRegister rt);  // R2
68   void DivuR2(GpuRegister rs, GpuRegister rt);  // R2
69   void MulR2(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R2
70   void DivR2(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R2
71   void ModR2(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R2
72   void DivuR2(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R2
73   void ModuR2(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R2
74   void MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R6
75   void DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R6
76   void ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R6
77   void DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R6
78   void ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // R6
79   void Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // MIPS64 R6
80   void Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // MIPS64 R6
81   void Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // MIPS64 R6
82   void Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // MIPS64 R6
83   void Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt);  // MIPS64 R6
84 
85   void And(GpuRegister rd, GpuRegister rs, GpuRegister rt);
86   void Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16);
87   void Or(GpuRegister rd, GpuRegister rs, GpuRegister rt);
88   void Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16);
89   void Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt);
90   void Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16);
91   void Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt);
92 
93   void Seb(GpuRegister rd, GpuRegister rt);  // R2+
94   void Seh(GpuRegister rd, GpuRegister rt);  // R2+
95   void Dext(GpuRegister rs, GpuRegister rt, int pos, int size_less_one);  // MIPS64
96 
97   void Sll(GpuRegister rd, GpuRegister rt, int shamt);
98   void Srl(GpuRegister rd, GpuRegister rt, int shamt);
99   void Sra(GpuRegister rd, GpuRegister rt, int shamt);
100   void Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs);
101   void Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs);
102   void Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs);
103   void Dsll(GpuRegister rd, GpuRegister rt, int shamt);  // MIPS64
104   void Dsrl(GpuRegister rd, GpuRegister rt, int shamt);  // MIPS64
105   void Dsra(GpuRegister rd, GpuRegister rt, int shamt);  // MIPS64
106   void Dsll32(GpuRegister rd, GpuRegister rt, int shamt);  // MIPS64
107   void Dsrl32(GpuRegister rd, GpuRegister rt, int shamt);  // MIPS64
108   void Dsra32(GpuRegister rd, GpuRegister rt, int shamt);  // MIPS64
109   void Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs);  // MIPS64
110   void Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs);  // MIPS64
111   void Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs);  // MIPS64
112 
113   void Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16);
114   void Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16);
115   void Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16);
116   void Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16);  // MIPS64
117   void Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
118   void Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
119   void Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16);  // MIPS64
120   void Lui(GpuRegister rt, uint16_t imm16);
121   void Dahi(GpuRegister rs, uint16_t imm16);  // MIPS64 R6
122   void Dati(GpuRegister rs, uint16_t imm16);  // MIPS64 R6
123   void Sync(uint32_t stype);
124   void Mfhi(GpuRegister rd);  // R2
125   void Mflo(GpuRegister rd);  // R2
126 
127   void Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16);
128   void Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16);
129   void Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16);
130   void Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16);  // MIPS64
131 
132   void Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt);
133   void Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt);
134   void Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16);
135   void Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
136 
137   void Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16);
138   void Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16);
139   void J(uint32_t addr26);
140   void Jal(uint32_t addr26);
141   void Jalr(GpuRegister rd, GpuRegister rs);
142   void Jalr(GpuRegister rs);
143   void Jr(GpuRegister rs);
144   void Auipc(GpuRegister rs, uint16_t imm16);  // R6
145   void Jic(GpuRegister rt, uint16_t imm16);  // R6
146   void Jialc(GpuRegister rt, uint16_t imm16);  // R6
147   void Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16);  // R6
148   void Bltzc(GpuRegister rt, uint16_t imm16);  // R6
149   void Bgtzc(GpuRegister rt, uint16_t imm16);  // R6
150   void Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16);  // R6
151   void Bgezc(GpuRegister rt, uint16_t imm16);  // R6
152   void Blezc(GpuRegister rt, uint16_t imm16);  // R6
153   void Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16);  // R6
154   void Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16);  // R6
155   void Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16);  // R6
156   void Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16);  // R6
157   void Beqzc(GpuRegister rs, uint32_t imm21);  // R6
158   void Bnezc(GpuRegister rs, uint32_t imm21);  // R6
159 
160   void AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
161   void SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
162   void MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
163   void DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft);
164   void AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
165   void SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
166   void MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
167   void DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft);
168   void MovS(FpuRegister fd, FpuRegister fs);
169   void MovD(FpuRegister fd, FpuRegister fs);
170   void NegS(FpuRegister fd, FpuRegister fs);
171   void NegD(FpuRegister fd, FpuRegister fs);
172 
173   void Cvtsw(FpuRegister fd, FpuRegister fs);
174   void Cvtdw(FpuRegister fd, FpuRegister fs);
175   void Cvtsd(FpuRegister fd, FpuRegister fs);
176   void Cvtds(FpuRegister fd, FpuRegister fs);
177 
178   void Mfc1(GpuRegister rt, FpuRegister fs);
179   void Mtc1(GpuRegister rt, FpuRegister fs);
180   void Dmfc1(GpuRegister rt, FpuRegister fs);  // MIPS64
181   void Dmtc1(GpuRegister rt, FpuRegister fs);  // MIPS64
182   void Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
183   void Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
184   void Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
185   void Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16);
186 
187   void Break();
188   void Nop();
189   void Move(GpuRegister rd, GpuRegister rs);
190   void Clear(GpuRegister rd);
191   void Not(GpuRegister rd, GpuRegister rs);
192 
193   // Higher level composite instructions
194   void LoadConst32(GpuRegister rd, int32_t value);
195   void LoadConst64(GpuRegister rd, int64_t value);  // MIPS64
196 
197   void Addiu32(GpuRegister rt, GpuRegister rs, int32_t value, GpuRegister rtmp = AT);
198   void Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp = AT);  // MIPS64
199 
200   void Bind(Label* label);  // R6
201   void B(Label* label);  // R6
202   void Jalr(Label* label, GpuRegister indirect_reg = RA);  // R6
203   // TODO: implement common for R6 and non-R6 interface for conditional branches?
204   void Bltc(GpuRegister rs, GpuRegister rt, Label* label);  // R6
205   void Bltzc(GpuRegister rt, Label* label);  // R6
206   void Bgtzc(GpuRegister rt, Label* label);  // R6
207   void Bgec(GpuRegister rs, GpuRegister rt, Label* label);  // R6
208   void Bgezc(GpuRegister rt, Label* label);  // R6
209   void Blezc(GpuRegister rt, Label* label);  // R6
210   void Bltuc(GpuRegister rs, GpuRegister rt, Label* label);  // R6
211   void Bgeuc(GpuRegister rs, GpuRegister rt, Label* label);  // R6
212   void Beqc(GpuRegister rs, GpuRegister rt, Label* label);  // R6
213   void Bnec(GpuRegister rs, GpuRegister rt, Label* label);  // R6
214   void Beqzc(GpuRegister rs, Label* label);  // R6
215   void Bnezc(GpuRegister rs, Label* label);  // R6
216 
217   void EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, size_t size);
218   void LoadFromOffset(LoadOperandType type, GpuRegister reg, GpuRegister base, int32_t offset);
219   void LoadFpuFromOffset(LoadOperandType type, FpuRegister reg, GpuRegister base, int32_t offset);
220   void StoreToOffset(StoreOperandType type, GpuRegister reg, GpuRegister base, int32_t offset);
221   void StoreFpuToOffset(StoreOperandType type, FpuRegister reg, GpuRegister base, int32_t offset);
222 
223   // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
224   void Emit(uint32_t value);
225 
226   //
227   // Overridden common assembler high-level functionality
228   //
229 
230   // Emit code that will create an activation on the stack
231   void BuildFrame(size_t frame_size, ManagedRegister method_reg,
232                   const std::vector<ManagedRegister>& callee_save_regs,
233                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
234 
235   // Emit code that will remove an activation from the stack
236   void RemoveFrame(size_t frame_size,
237                    const std::vector<ManagedRegister>& callee_save_regs) OVERRIDE;
238 
239   void IncreaseFrameSize(size_t adjust) OVERRIDE;
240   void DecreaseFrameSize(size_t adjust) OVERRIDE;
241 
242   // Store routines
243   void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE;
244   void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
245   void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
246 
247   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE;
248 
249   void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm,
250                                 ManagedRegister mscratch) OVERRIDE;
251 
252   void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
253                                   ManagedRegister mscratch) OVERRIDE;
254 
255   void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE;
256 
257   void StoreSpanning(FrameOffset dest, ManagedRegister msrc, FrameOffset in_off,
258                      ManagedRegister mscratch) OVERRIDE;
259 
260   // Load routines
261   void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE;
262 
263   void LoadFromThread64(ManagedRegister mdest, ThreadOffset<8> src, size_t size) OVERRIDE;
264 
265   void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
266 
267   void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
268                bool poison_reference) OVERRIDE;
269 
270   void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE;
271 
272   void LoadRawPtrFromThread64(ManagedRegister mdest, ThreadOffset<8> offs) OVERRIDE;
273 
274   // Copying routines
275   void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE;
276 
277   void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs,
278                               ManagedRegister mscratch) OVERRIDE;
279 
280   void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
281                             ManagedRegister mscratch) OVERRIDE;
282 
283   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE;
284 
285   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE;
286 
287   void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister mscratch,
288             size_t size) OVERRIDE;
289 
290   void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
291             ManagedRegister mscratch, size_t size) OVERRIDE;
292 
293   void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister mscratch,
294             size_t size) OVERRIDE;
295 
296   void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
297             ManagedRegister mscratch, size_t size) OVERRIDE;
298 
299   void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
300             ManagedRegister mscratch, size_t size) OVERRIDE;
301 
302   void MemoryBarrier(ManagedRegister) OVERRIDE;
303 
304   // Sign extension
305   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
306 
307   // Zero extension
308   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
309 
310   // Exploit fast access in managed code to Thread::Current()
311   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
312   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) OVERRIDE;
313 
314   // Set up out_reg to hold a Object** into the handle scope, or to be null if the
315   // value is null and null_allowed. in_reg holds a possibly stale reference
316   // that can be used to avoid loading the handle scope entry to see if the value is
317   // null.
318   void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
319                               ManagedRegister in_reg, bool null_allowed) OVERRIDE;
320 
321   // Set up out_off to hold a Object** into the handle scope, or to be null if the
322   // value is null and null_allowed.
323   void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister
324                               mscratch, bool null_allowed) OVERRIDE;
325 
326   // src holds a handle scope entry (Object**) load this into dst
327   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
328 
329   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
330   // know that src may not be null.
331   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
332   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
333 
334   // Call to address held at [base+offset]
335   void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE;
336   void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE;
337   void CallFromThread64(ThreadOffset<8> offset, ManagedRegister mscratch) OVERRIDE;
338 
339   // Generate code to check if Thread::Current()->exception_ is non-null
340   // and branch to a ExceptionSlowPath if it is.
341   void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) OVERRIDE;
342 
343  private:
344   void EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd, int shamt, int funct);
345   void EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm);
346   void EmitI21(int opcode, GpuRegister rs, uint32_t imm21);
347   void EmitJ(int opcode, uint32_t addr26);
348   void EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd, int funct);
349   void EmitFI(int opcode, int fmt, FpuRegister rt, uint16_t imm);
350 
351   DISALLOW_COPY_AND_ASSIGN(Mips64Assembler);
352 };
353 
354 // Slowpath entered when Thread::Current()->_exception is non-null
355 class Mips64ExceptionSlowPath FINAL : public SlowPath {
356  public:
Mips64ExceptionSlowPath(Mips64ManagedRegister scratch,size_t stack_adjust)357   explicit Mips64ExceptionSlowPath(Mips64ManagedRegister scratch, size_t stack_adjust)
358       : scratch_(scratch), stack_adjust_(stack_adjust) {}
359   virtual void Emit(Assembler *sp_asm) OVERRIDE;
360  private:
361   const Mips64ManagedRegister scratch_;
362   const size_t stack_adjust_;
363 };
364 
365 }  // namespace mips64
366 }  // namespace art
367 
368 #endif  // ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_
369