Home | History | Annotate | Download | only in mips
      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:
    220   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:
    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