• 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 <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 #if 0
33 class Operand {
34  public:
35   uint8_t mod() const {
36     return (encoding_at(0) >> 6) & 3;
37   }
38 
39   Register rm() const {
40     return static_cast<Register>(encoding_at(0) & 7);
41   }
42 
43   ScaleFactor scale() const {
44     return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
45   }
46 
47   Register index() const {
48     return static_cast<Register>((encoding_at(1) >> 3) & 7);
49   }
50 
51   Register base() const {
52     return static_cast<Register>(encoding_at(1) & 7);
53   }
54 
55   int8_t disp8() const {
56     CHECK_GE(length_, 2);
57     return static_cast<int8_t>(encoding_[length_ - 1]);
58   }
59 
60   int32_t disp32() const {
61     CHECK_GE(length_, 5);
62     int32_t value;
63     memcpy(&value, &encoding_[length_ - 4], sizeof(value));
64     return value;
65   }
66 
67   bool IsRegister(Register reg) const {
68     return ((encoding_[0] & 0xF8) == 0xC0)  // Addressing mode is register only.
69         && ((encoding_[0] & 0x07) == reg);  // Register codes match.
70   }
71 
72  protected:
73   // Operand can be sub classed (e.g: Address).
74   Operand() : length_(0) { }
75 
76   void SetModRM(int mod, Register rm) {
77     CHECK_EQ(mod & ~3, 0);
78     encoding_[0] = (mod << 6) | rm;
79     length_ = 1;
80   }
81 
82   void SetSIB(ScaleFactor scale, Register index, Register base) {
83     CHECK_EQ(length_, 1);
84     CHECK_EQ(scale & ~3, 0);
85     encoding_[1] = (scale << 6) | (index << 3) | base;
86     length_ = 2;
87   }
88 
89   void SetDisp8(int8_t disp) {
90     CHECK(length_ == 1 || length_ == 2);
91     encoding_[length_++] = static_cast<uint8_t>(disp);
92   }
93 
94   void SetDisp32(int32_t disp) {
95     CHECK(length_ == 1 || length_ == 2);
96     int disp_size = sizeof(disp);
97     memmove(&encoding_[length_], &disp, disp_size);
98     length_ += disp_size;
99   }
100 
101  private:
102   byte length_;
103   byte encoding_[6];
104   byte padding_;
105 
106   explicit Operand(Register reg) { SetModRM(3, reg); }
107 
108   // Get the operand encoding byte at the given index.
109   uint8_t encoding_at(int index) const {
110     CHECK_GE(index, 0);
111     CHECK_LT(index, length_);
112     return encoding_[index];
113   }
114 
115   friend class MipsAssembler;
116 
117   DISALLOW_COPY_AND_ASSIGN(Operand);
118 };
119 
120 
121 class Address : public Operand {
122  public:
123   Address(Register base, int32_t disp) {
124     Init(base, disp);
125   }
126 
127   Address(Register base, Offset disp) {
128     Init(base, disp.Int32Value());
129   }
130 
131   Address(Register base, FrameOffset disp) {
132     CHECK_EQ(base, ESP);
133     Init(ESP, disp.Int32Value());
134   }
135 
136   Address(Register base, MemberOffset disp) {
137     Init(base, disp.Int32Value());
138   }
139 
140   void Init(Register base, int32_t disp) {
141     if (disp == 0 && base != EBP) {
142       SetModRM(0, base);
143       if (base == ESP) SetSIB(TIMES_1, ESP, base);
144     } else if (disp >= -128 && disp <= 127) {
145       SetModRM(1, base);
146       if (base == ESP) SetSIB(TIMES_1, ESP, base);
147       SetDisp8(disp);
148     } else {
149       SetModRM(2, base);
150       if (base == ESP) SetSIB(TIMES_1, ESP, base);
151       SetDisp32(disp);
152     }
153   }
154 
155 
156   Address(Register index, ScaleFactor scale, int32_t disp) {
157     CHECK_NE(index, ESP);  // Illegal addressing mode.
158     SetModRM(0, ESP);
159     SetSIB(scale, index, EBP);
160     SetDisp32(disp);
161   }
162 
163   Address(Register base, Register index, ScaleFactor scale, int32_t disp) {
164     CHECK_NE(index, ESP);  // Illegal addressing mode.
165     if (disp == 0 && base != EBP) {
166       SetModRM(0, ESP);
167       SetSIB(scale, index, base);
168     } else if (disp >= -128 && disp <= 127) {
169       SetModRM(1, ESP);
170       SetSIB(scale, index, base);
171       SetDisp8(disp);
172     } else {
173       SetModRM(2, ESP);
174       SetSIB(scale, index, base);
175       SetDisp32(disp);
176     }
177   }
178 
179   static Address Absolute(uword addr) {
180     Address result;
181     result.SetModRM(0, EBP);
182     result.SetDisp32(addr);
183     return result;
184   }
185 
186   static Address Absolute(ThreadOffset addr) {
187     return Absolute(addr.Int32Value());
188   }
189 
190  private:
191   Address() {}
192 
193   DISALLOW_COPY_AND_ASSIGN(Address);
194 };
195 
196 #endif
197 
198 enum LoadOperandType {
199   kLoadSignedByte,
200   kLoadUnsignedByte,
201   kLoadSignedHalfword,
202   kLoadUnsignedHalfword,
203   kLoadWord,
204   kLoadWordPair,
205   kLoadSWord,
206   kLoadDWord
207 };
208 
209 enum StoreOperandType {
210   kStoreByte,
211   kStoreHalfword,
212   kStoreWord,
213   kStoreWordPair,
214   kStoreSWord,
215   kStoreDWord
216 };
217 
218 class MipsAssembler : public Assembler {
219  public:
MipsAssembler()220   MipsAssembler() {}
~MipsAssembler()221   virtual ~MipsAssembler() {}
222 
223   // Emit Machine Instructions.
224   void Add(Register rd, Register rs, Register rt);
225   void Addu(Register rd, Register rs, Register rt);
226   void Addi(Register rt, Register rs, uint16_t imm16);
227   void Addiu(Register rt, Register rs, uint16_t imm16);
228   void Sub(Register rd, Register rs, Register rt);
229   void Subu(Register rd, Register rs, Register rt);
230   void Mult(Register rs, Register rt);
231   void Multu(Register rs, Register rt);
232   void Div(Register rs, Register rt);
233   void Divu(Register rs, Register rt);
234 
235   void And(Register rd, Register rs, Register rt);
236   void Andi(Register rt, Register rs, uint16_t imm16);
237   void Or(Register rd, Register rs, Register rt);
238   void Ori(Register rt, Register rs, uint16_t imm16);
239   void Xor(Register rd, Register rs, Register rt);
240   void Xori(Register rt, Register rs, uint16_t imm16);
241   void Nor(Register rd, Register rs, Register rt);
242 
243   void Sll(Register rd, Register rs, int shamt);
244   void Srl(Register rd, Register rs, int shamt);
245   void Sra(Register rd, Register rs, int shamt);
246   void Sllv(Register rd, Register rs, Register rt);
247   void Srlv(Register rd, Register rs, Register rt);
248   void Srav(Register rd, Register rs, Register rt);
249 
250   void Lb(Register rt, Register rs, uint16_t imm16);
251   void Lh(Register rt, Register rs, uint16_t imm16);
252   void Lw(Register rt, Register rs, uint16_t imm16);
253   void Lbu(Register rt, Register rs, uint16_t imm16);
254   void Lhu(Register rt, Register rs, uint16_t imm16);
255   void Lui(Register rt, uint16_t imm16);
256   void Mfhi(Register rd);
257   void Mflo(Register rd);
258 
259   void Sb(Register rt, Register rs, uint16_t imm16);
260   void Sh(Register rt, Register rs, uint16_t imm16);
261   void Sw(Register rt, Register rs, uint16_t imm16);
262 
263   void Slt(Register rd, Register rs, Register rt);
264   void Sltu(Register rd, Register rs, Register rt);
265   void Slti(Register rt, Register rs, uint16_t imm16);
266   void Sltiu(Register rt, Register rs, uint16_t imm16);
267 
268   void Beq(Register rt, Register rs, uint16_t imm16);
269   void Bne(Register rt, Register rs, uint16_t imm16);
270   void J(uint32_t address);
271   void Jal(uint32_t address);
272   void Jr(Register rs);
273   void Jalr(Register rs);
274 
275   void AddS(FRegister fd, FRegister fs, FRegister ft);
276   void SubS(FRegister fd, FRegister fs, FRegister ft);
277   void MulS(FRegister fd, FRegister fs, FRegister ft);
278   void DivS(FRegister fd, FRegister fs, FRegister ft);
279   void AddD(DRegister fd, DRegister fs, DRegister ft);
280   void SubD(DRegister fd, DRegister fs, DRegister ft);
281   void MulD(DRegister fd, DRegister fs, DRegister ft);
282   void DivD(DRegister fd, DRegister fs, DRegister ft);
283   void MovS(FRegister fd, FRegister fs);
284   void MovD(DRegister fd, DRegister fs);
285 
286   void Mfc1(Register rt, FRegister fs);
287   void Mtc1(FRegister ft, Register rs);
288   void Lwc1(FRegister ft, Register rs, uint16_t imm16);
289   void Ldc1(DRegister ft, Register rs, uint16_t imm16);
290   void Swc1(FRegister ft, Register rs, uint16_t imm16);
291   void Sdc1(DRegister ft, Register rs, uint16_t imm16);
292 
293   void Break();
294   void Nop();
295   void Move(Register rt, Register rs);
296   void Clear(Register rt);
297   void Not(Register rt, Register rs);
298   void Mul(Register rd, Register rs, Register rt);
299   void Div(Register rd, Register rs, Register rt);
300   void Rem(Register rd, Register rs, Register rt);
301 
302   void AddConstant(Register rt, Register rs, int32_t value);
303   void LoadImmediate(Register rt, int32_t value);
304 
305   void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
306   void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
307   void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
308   void LoadDFromOffset(DRegister reg, Register base, int32_t offset);
309   void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset);
310   void StoreFToOffset(FRegister reg, Register base, int32_t offset);
311   void StoreDToOffset(DRegister reg, Register base, int32_t offset);
312 
313 #if 0
314   MipsAssembler* lock();
315 
316   void mfence();
317 
318   MipsAssembler* fs();
319 
320   //
321   // Macros for High-level operations.
322   //
323 
324   void AddImmediate(Register reg, const Immediate& imm);
325 
326   void LoadDoubleConstant(XmmRegister dst, double value);
327 
328   void DoubleNegate(XmmRegister d);
329   void FloatNegate(XmmRegister f);
330 
331   void DoubleAbs(XmmRegister reg);
332 
333   void LockCmpxchgl(const Address& address, Register reg) {
334     lock()->cmpxchgl(address, reg);
335   }
336 
337   //
338   // Misc. functionality
339   //
340   int PreferredLoopAlignment() { return 16; }
341   void Align(int alignment, int offset);
342 
343   // Debugging and bringup support.
344   void Stop(const char* message);
345 #endif
346 
347   // Emit data (e.g. encoded instruction or immediate) to the instruction stream.
348   void Emit(int32_t value);
349   void EmitBranch(Register rt, Register rs, Label* label, bool equal);
350   void EmitJump(Label* label, bool link);
351   void Bind(Label* label, bool is_jump);
352 
353   //
354   // Overridden common assembler high-level functionality
355   //
356 
357   // Emit code that will create an activation on the stack
358   virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
359                           const std::vector<ManagedRegister>& callee_save_regs,
360                           const std::vector<ManagedRegister>& entry_spills);
361 
362   // Emit code that will remove an activation from the stack
363   virtual void RemoveFrame(size_t frame_size,
364                            const std::vector<ManagedRegister>& callee_save_regs);
365 
366   virtual void IncreaseFrameSize(size_t adjust);
367   virtual void DecreaseFrameSize(size_t adjust);
368 
369   // Store routines
370   virtual void Store(FrameOffset offs, ManagedRegister msrc, size_t size);
371   virtual void StoreRef(FrameOffset dest, ManagedRegister msrc);
372   virtual void StoreRawPtr(FrameOffset dest, ManagedRegister msrc);
373 
374   virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
375                                      ManagedRegister mscratch);
376 
377   virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm,
378                                       ManagedRegister mscratch);
379 
380   virtual void StoreStackOffsetToThread(ThreadOffset thr_offs,
381                                         FrameOffset fr_offs,
382                                         ManagedRegister mscratch);
383 
384   virtual void StoreStackPointerToThread(ThreadOffset thr_offs);
385 
386   virtual void StoreSpanning(FrameOffset dest, ManagedRegister msrc,
387                              FrameOffset in_off, ManagedRegister mscratch);
388 
389   // Load routines
390   virtual void Load(ManagedRegister mdest, FrameOffset src, size_t size);
391 
392   virtual void Load(ManagedRegister mdest, ThreadOffset src, size_t size);
393 
394   virtual void LoadRef(ManagedRegister dest, FrameOffset  src);
395 
396   virtual void LoadRef(ManagedRegister mdest, ManagedRegister base,
397                        MemberOffset offs);
398 
399   virtual void LoadRawPtr(ManagedRegister mdest, ManagedRegister base,
400                           Offset offs);
401 
402   virtual void LoadRawPtrFromThread(ManagedRegister mdest,
403                                     ThreadOffset offs);
404 
405   // Copying routines
406   virtual void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size);
407 
408   virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs,
409                                     ManagedRegister mscratch);
410 
411   virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs,
412                                   ManagedRegister mscratch);
413 
414   virtual void CopyRef(FrameOffset dest, FrameOffset src,
415                        ManagedRegister mscratch);
416 
417   virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size);
418 
419   virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
420                     ManagedRegister mscratch, size_t size);
421 
422   virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
423                     ManagedRegister mscratch, size_t size);
424 
425   virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
426                     ManagedRegister mscratch, size_t size);
427 
428   virtual void Copy(ManagedRegister dest, Offset dest_offset,
429                     ManagedRegister src, Offset src_offset,
430                     ManagedRegister mscratch, size_t size);
431 
432   virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
433                     ManagedRegister mscratch, size_t size);
434 
435   virtual void MemoryBarrier(ManagedRegister);
436 
437   // Sign extension
438   virtual void SignExtend(ManagedRegister mreg, size_t size);
439 
440   // Zero extension
441   virtual void ZeroExtend(ManagedRegister mreg, size_t size);
442 
443   // Exploit fast access in managed code to Thread::Current()
444   virtual void GetCurrentThread(ManagedRegister tr);
445   virtual void GetCurrentThread(FrameOffset dest_offset,
446                                 ManagedRegister mscratch);
447 
448   // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the
449   // value is null and null_allowed. in_reg holds a possibly stale reference
450   // that can be used to avoid loading the SIRT entry to see if the value is
451   // NULL.
452   virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset,
453                                ManagedRegister in_reg, bool null_allowed);
454 
455   // Set up out_off to hold a Object** into the SIRT, or to be NULL if the
456   // value is null and null_allowed.
457   virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset,
458                                ManagedRegister mscratch, bool null_allowed);
459 
460   // src holds a SIRT entry (Object**) load this into dst
461   virtual void LoadReferenceFromSirt(ManagedRegister dst,
462                                      ManagedRegister src);
463 
464   // Heap::VerifyObject on src. In some cases (such as a reference to this) we
465   // know that src may not be null.
466   virtual void VerifyObject(ManagedRegister src, bool could_be_null);
467   virtual void VerifyObject(FrameOffset src, bool could_be_null);
468 
469   // Call to address held at [base+offset]
470   virtual void Call(ManagedRegister base, Offset offset,
471                     ManagedRegister mscratch);
472   virtual void Call(FrameOffset base, Offset offset,
473                     ManagedRegister mscratch);
474   virtual void Call(ThreadOffset offset, ManagedRegister mscratch);
475 
476   // Generate code to check if Thread::Current()->exception_ is non-null
477   // and branch to a ExceptionSlowPath if it is.
478   virtual void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust);
479 
480  private:
481   void EmitR(int opcode, Register rs, Register rt, Register rd, int shamt, int funct);
482   void EmitI(int opcode, Register rs, Register rt, uint16_t imm);
483   void EmitJ(int opcode, int address);
484   void EmitFR(int opcode, int fmt, FRegister ft, FRegister fs, FRegister fd, int funct);
485   void EmitFI(int opcode, int fmt, FRegister rt, uint16_t imm);
486 
487   int32_t EncodeBranchOffset(int offset, int32_t inst, bool is_jump);
488   int DecodeBranchOffset(int32_t inst, bool is_jump);
489 
490   DISALLOW_COPY_AND_ASSIGN(MipsAssembler);
491 };
492 
493 // Slowpath entered when Thread::Current()->_exception is non-null
494 class MipsExceptionSlowPath : public SlowPath {
495  public:
MipsExceptionSlowPath(MipsManagedRegister scratch,size_t stack_adjust)496   explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
497       : scratch_(scratch), stack_adjust_(stack_adjust) {}
498   virtual void Emit(Assembler *sp_asm);
499  private:
500   const MipsManagedRegister scratch_;
501   const size_t stack_adjust_;
502 };
503 
504 }  // namespace mips
505 }  // namespace art
506 
507 #endif  // ART_COMPILER_UTILS_MIPS_ASSEMBLER_MIPS_H_
508