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 <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:
     70   MipsLabel() : prev_branch_id_plus_one_(0) {}
     71 
     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:
     85   explicit MipsExceptionSlowPath(MipsManagedRegister scratch, size_t stack_adjust)
     86       : scratch_(scratch), stack_adjust_(stack_adjust) {}
     87 
     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:
     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)
    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 
    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 
    403   void Bind(Label* label) OVERRIDE {
    404     Bind(down_cast<MipsLabel*>(label));
    405   }
    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 
    788   bool IsR6() const {
    789     if (isa_features_ != nullptr) {
    790       return isa_features_->IsR6();
    791     } else {
    792       return false;
    793     }
    794   }
    795 
    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