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 <vector>
21 
22 #include "base/macros.h"
23 #include "constants_mips.h"
24 #include "globals.h"
25 #include "managed_register_mips.h"
26 #include "utils/assembler.h"
27 #include "offsets.h"
28 #include "utils.h"
29 
30 namespace art {
31 namespace mips {
32 
33 enum LoadOperandType {
34   kLoadSignedByte,
35   kLoadUnsignedByte,
36   kLoadSignedHalfword,
37   kLoadUnsignedHalfword,
38   kLoadWord,
39   kLoadWordPair,
40   kLoadSWord,
41   kLoadDWord
42 };
43 
44 enum StoreOperandType {
45   kStoreByte,
46   kStoreHalfword,
47   kStoreWord,
48   kStoreWordPair,
49   kStoreSWord,
50   kStoreDWord
51 };
52 
53 class MipsAssembler FINAL : public Assembler {
54  public:
MipsAssembler()55   MipsAssembler() {}
~MipsAssembler()56   virtual ~MipsAssembler() {}
57 
58   // Emit Machine Instructions.
59   void Add(Register rd, Register rs, Register rt);
60   void Addu(Register rd, Register rs, Register rt);
61   void Addi(Register rt, Register rs, uint16_t imm16);
62   void Addiu(Register rt, Register rs, uint16_t imm16);
63   void Sub(Register rd, Register rs, Register rt);
64   void Subu(Register rd, Register rs, Register rt);
65   void Mult(Register rs, Register rt);
66   void Multu(Register rs, Register rt);
67   void Div(Register rs, Register rt);
68   void Divu(Register rs, Register rt);
69 
70   void And(Register rd, Register rs, Register rt);
71   void Andi(Register rt, Register rs, uint16_t imm16);
72   void Or(Register rd, Register rs, Register rt);
73   void Ori(Register rt, Register rs, uint16_t imm16);
74   void Xor(Register rd, Register rs, Register rt);
75   void Xori(Register rt, Register rs, uint16_t imm16);
76   void Nor(Register rd, Register rs, Register rt);
77 
78   void Sll(Register rd, Register rs, int shamt);
79   void Srl(Register rd, Register rs, int shamt);
80   void Sra(Register rd, Register rs, int shamt);
81   void Sllv(Register rd, Register rs, Register rt);
82   void Srlv(Register rd, Register rs, Register rt);
83   void Srav(Register rd, Register rs, Register rt);
84 
85   void Lb(Register rt, Register rs, uint16_t imm16);
86   void Lh(Register rt, Register rs, uint16_t imm16);
87   void Lw(Register rt, Register rs, uint16_t imm16);
88   void Lbu(Register rt, Register rs, uint16_t imm16);
89   void Lhu(Register rt, Register rs, uint16_t imm16);
90   void Lui(Register rt, uint16_t imm16);
91   void Mfhi(Register rd);
92   void Mflo(Register rd);
93 
94   void Sb(Register rt, Register rs, uint16_t imm16);
95   void Sh(Register rt, Register rs, uint16_t imm16);
96   void Sw(Register rt, Register rs, uint16_t imm16);
97 
98   void Slt(Register rd, Register rs, Register rt);
99   void Sltu(Register rd, Register rs, Register rt);
100   void Slti(Register rt, Register rs, uint16_t imm16);
101   void Sltiu(Register rt, Register rs, uint16_t imm16);
102 
103   void Beq(Register rt, Register rs, uint16_t imm16);
104   void Bne(Register rt, Register rs, uint16_t imm16);
105   void J(uint32_t address);
106   void Jal(uint32_t address);
107   void Jr(Register rs);
108   void Jalr(Register rs);
109 
110   void AddS(FRegister fd, FRegister fs, FRegister ft);
111   void SubS(FRegister fd, FRegister fs, FRegister ft);
112   void MulS(FRegister fd, FRegister fs, FRegister ft);
113   void DivS(FRegister fd, FRegister fs, FRegister ft);
114   void AddD(DRegister fd, DRegister fs, DRegister ft);
115   void SubD(DRegister fd, DRegister fs, DRegister ft);
116   void MulD(DRegister fd, DRegister fs, DRegister ft);
117   void DivD(DRegister fd, DRegister fs, DRegister ft);
118   void MovS(FRegister fd, FRegister fs);
119   void MovD(DRegister fd, DRegister fs);
120 
121   void Mfc1(Register rt, FRegister fs);
122   void Mtc1(FRegister ft, Register rs);
123   void Lwc1(FRegister ft, Register rs, uint16_t imm16);
124   void Ldc1(DRegister ft, Register rs, uint16_t imm16);
125   void Swc1(FRegister ft, Register rs, uint16_t imm16);
126   void Sdc1(DRegister ft, Register rs, uint16_t imm16);
127 
128   void Break();
129   void Nop();
130   void Move(Register rt, Register rs);
131   void Clear(Register rt);
132   void Not(Register rt, Register rs);
133   void Mul(Register rd, Register rs, Register rt);
134   void Div(Register rd, Register rs, Register rt);
135   void Rem(Register rd, Register rs, Register rt);
136 
137   void AddConstant(Register rt, Register rs, int32_t value);
138   void LoadImmediate(Register rt, int32_t value);
139 
140   void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
141   void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
142   void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
143   void LoadDFromOffset(DRegister reg, Register base, int32_t offset);
144   void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset);
145   void StoreFToOffset(FRegister reg, Register base, int32_t offset);
146   void StoreDToOffset(DRegister reg, Register base, int32_t offset);
147 
148   // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
149   void Emit(int32_t value);
150   void EmitBranch(Register rt, Register rs, Label* label, bool equal);
151   void EmitJump(Label* label, bool link);
152   void Bind(Label* label, bool is_jump);
153 
154   //
155   // Overridden common assembler high-level functionality
156   //
157 
158   // Emit code that will create an activation on the stack
159   void BuildFrame(size_t frame_size, ManagedRegister method_reg,
160                   const std::vector<ManagedRegister>& callee_save_regs,
161                   const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
162 
163   // Emit code that will remove an activation from the stack
164   void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
165       OVERRIDE;
166 
167   void IncreaseFrameSize(size_t adjust) OVERRIDE;
168   void DecreaseFrameSize(size_t adjust) OVERRIDE;
169 
170   // Store routines
171   void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE;
172   void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
173   void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE;
174 
175   void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE;
176 
177   void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister mscratch)
178       OVERRIDE;
179 
180   void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
181                                   ManagedRegister mscratch) OVERRIDE;
182 
183   void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE;
184 
185   void StoreSpanning(FrameOffset dest, ManagedRegister msrc, FrameOffset in_off,
186                      ManagedRegister mscratch) OVERRIDE;
187 
188   // Load routines
189   void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE;
190 
191   void LoadFromThread32(ManagedRegister mdest, ThreadOffset<4> src, size_t size) OVERRIDE;
192 
193   void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
194 
195   void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs) OVERRIDE;
196 
197   void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE;
198 
199   void LoadRawPtrFromThread32(ManagedRegister mdest, ThreadOffset<4> offs) OVERRIDE;
200 
201   // Copying routines
202   void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE;
203 
204   void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
205                               ManagedRegister mscratch) OVERRIDE;
206 
207   void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
208                             ManagedRegister mscratch) OVERRIDE;
209 
210   void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE;
211 
212   void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE;
213 
214   void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister mscratch,
215             size_t size) OVERRIDE;
216 
217   void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
218             ManagedRegister mscratch, size_t size) OVERRIDE;
219 
220   void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister mscratch,
221             size_t size) OVERRIDE;
222 
223   void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
224             ManagedRegister mscratch, size_t size) OVERRIDE;
225 
226   void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
227             ManagedRegister mscratch, size_t size) OVERRIDE;
228 
229   void MemoryBarrier(ManagedRegister) OVERRIDE;
230 
231   // Sign extension
232   void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
233 
234   // Zero extension
235   void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
236 
237   // Exploit fast access in managed code to Thread::Current()
238   void GetCurrentThread(ManagedRegister tr) OVERRIDE;
239   void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) OVERRIDE;
240 
241   // Set up out_reg to hold a Object** into the handle scope, or to be NULL if the
242   // value is null and null_allowed. in_reg holds a possibly stale reference
243   // that can be used to avoid loading the handle scope entry to see if the value is
244   // NULL.
245   void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg,
246                        bool null_allowed) OVERRIDE;
247 
248   // Set up out_off to hold a Object** into the handle scope, or to be NULL if the
249   // value is null and null_allowed.
250   void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister mscratch,
251                        bool null_allowed) OVERRIDE;
252 
253   // src holds a handle scope entry (Object**) load this into dst
254   void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE;
255 
256   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
257   // know that src may not be null.
258   void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
259   void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
260 
261   // Call to address held at [base+offset]
262   void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE;
263   void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE;
264   void CallFromThread32(ThreadOffset<4> offset, ManagedRegister mscratch) OVERRIDE;
265 
266   // Generate code to check if Thread::Current()->exception_ is non-null
267   // and branch to a ExceptionSlowPath if it is.
268   void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) OVERRIDE;
269 
270  private:
271   void EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct);
272   void EmitI(int opcode, Register rs, Register rt, uint16_t imm);
273   void EmitJ(int opcode, int address);
274   void EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct);
275   void EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm);
276 
277   int32_t EncodeBranchOffset(int offset, int32_t inst, bool is_jump);
278   int DecodeBranchOffset(int32_t inst, bool is_jump);
279 
280   DISALLOW_COPY_AND_ASSIGN(MipsAssembler);
281 };
282 
283 // Slowpath entered when Thread::Current()->_exception is non-null
284 class MipsExceptionSlowPath FINAL : public SlowPath {
285  public:
MipsExceptionSlowPath(MipsManagedRegister scratch,size_t stack_adjust)286   explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
287       : scratch_(scratch), stack_adjust_(stack_adjust) {}
288   virtual void Emit(Assembler *sp_asm) OVERRIDE;
289  private:
290   const MipsManagedRegister scratch_;
291   const size_t stack_adjust_;
292 };
293 
294 }  // namespace mips
295 }  // namespace art
296 
297 #endif  // ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
298