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 29 namespace art { 30 namespace mips { 31 32 enum LoadOperandType { 33 kLoadSignedByte, 34 kLoadUnsignedByte, 35 kLoadSignedHalfword, 36 kLoadUnsignedHalfword, 37 kLoadWord, 38 kLoadWordPair, 39 kLoadSWord, 40 kLoadDWord 41 }; 42 43 enum StoreOperandType { 44 kStoreByte, 45 kStoreHalfword, 46 kStoreWord, 47 kStoreWordPair, 48 kStoreSWord, 49 kStoreDWord 50 }; 51 52 class MipsAssembler FINAL : public Assembler { 53 public: MipsAssembler()54 MipsAssembler() {} ~MipsAssembler()55 virtual ~MipsAssembler() {} 56 57 // Emit Machine Instructions. 58 void Add(Register rd, Register rs, Register rt); 59 void Addu(Register rd, Register rs, Register rt); 60 void Addi(Register rt, Register rs, uint16_t imm16); 61 void Addiu(Register rt, Register rs, uint16_t imm16); 62 void Sub(Register rd, Register rs, Register rt); 63 void Subu(Register rd, Register rs, Register rt); 64 void Mult(Register rs, Register rt); 65 void Multu(Register rs, Register rt); 66 void Div(Register rs, Register rt); 67 void Divu(Register rs, Register rt); 68 69 void And(Register rd, Register rs, Register rt); 70 void Andi(Register rt, Register rs, uint16_t imm16); 71 void Or(Register rd, Register rs, Register rt); 72 void Ori(Register rt, Register rs, uint16_t imm16); 73 void Xor(Register rd, Register rs, Register rt); 74 void Xori(Register rt, Register rs, uint16_t imm16); 75 void Nor(Register rd, Register rs, Register rt); 76 77 void Sll(Register rd, Register rs, int shamt); 78 void Srl(Register rd, Register rs, int shamt); 79 void Sra(Register rd, Register rs, int shamt); 80 void Sllv(Register rd, Register rs, Register rt); 81 void Srlv(Register rd, Register rs, Register rt); 82 void Srav(Register rd, Register rs, Register rt); 83 84 void Lb(Register rt, Register rs, uint16_t imm16); 85 void Lh(Register rt, Register rs, uint16_t imm16); 86 void Lw(Register rt, Register rs, uint16_t imm16); 87 void Lbu(Register rt, Register rs, uint16_t imm16); 88 void Lhu(Register rt, Register rs, uint16_t imm16); 89 void Lui(Register rt, uint16_t imm16); 90 void Mfhi(Register rd); 91 void Mflo(Register rd); 92 93 void Sb(Register rt, Register rs, uint16_t imm16); 94 void Sh(Register rt, Register rs, uint16_t imm16); 95 void Sw(Register rt, Register rs, uint16_t imm16); 96 97 void Slt(Register rd, Register rs, Register rt); 98 void Sltu(Register rd, Register rs, Register rt); 99 void Slti(Register rt, Register rs, uint16_t imm16); 100 void Sltiu(Register rt, Register rs, uint16_t imm16); 101 102 void Beq(Register rt, Register rs, uint16_t imm16); 103 void Bne(Register rt, Register rs, uint16_t imm16); 104 void J(uint32_t address); 105 void Jal(uint32_t address); 106 void Jr(Register rs); 107 void Jalr(Register rs); 108 109 void AddS(FRegister fd, FRegister fs, FRegister ft); 110 void SubS(FRegister fd, FRegister fs, FRegister ft); 111 void MulS(FRegister fd, FRegister fs, FRegister ft); 112 void DivS(FRegister fd, FRegister fs, FRegister ft); 113 void AddD(DRegister fd, DRegister fs, DRegister ft); 114 void SubD(DRegister fd, DRegister fs, DRegister ft); 115 void MulD(DRegister fd, DRegister fs, DRegister ft); 116 void DivD(DRegister fd, DRegister fs, DRegister ft); 117 void MovS(FRegister fd, FRegister fs); 118 void MovD(DRegister fd, DRegister fs); 119 120 void Mfc1(Register rt, FRegister fs); 121 void Mtc1(FRegister ft, Register rs); 122 void Lwc1(FRegister ft, Register rs, uint16_t imm16); 123 void Ldc1(DRegister ft, Register rs, uint16_t imm16); 124 void Swc1(FRegister ft, Register rs, uint16_t imm16); 125 void Sdc1(DRegister ft, Register rs, uint16_t imm16); 126 127 void Break(); 128 void Nop(); 129 void Move(Register rt, Register rs); 130 void Clear(Register rt); 131 void Not(Register rt, Register rs); 132 void Mul(Register rd, Register rs, Register rt); 133 void Div(Register rd, Register rs, Register rt); 134 void Rem(Register rd, Register rs, Register rt); 135 136 void AddConstant(Register rt, Register rs, int32_t value); 137 void LoadImmediate(Register rt, int32_t value); 138 139 void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size); 140 void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset); 141 void LoadSFromOffset(FRegister reg, Register base, int32_t offset); 142 void LoadDFromOffset(DRegister reg, Register base, int32_t offset); 143 void StoreToOffset(StoreOperandType type, Register reg, Register base, int32_t offset); 144 void StoreFToOffset(FRegister reg, Register base, int32_t offset); 145 void StoreDToOffset(DRegister reg, Register base, int32_t offset); 146 147 // Emit data (e.g. encoded instruction or immediate) to the instruction stream. 148 void Emit(int32_t value); 149 void EmitBranch(Register rt, Register rs, Label* label, bool equal); 150 void EmitJump(Label* label, bool link); 151 void Bind(Label* label, bool is_jump); 152 153 // 154 // Overridden common assembler high-level functionality 155 // 156 157 // Emit code that will create an activation on the stack 158 void BuildFrame(size_t frame_size, ManagedRegister method_reg, 159 const std::vector<ManagedRegister>& callee_save_regs, 160 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 161 162 // Emit code that will remove an activation from the stack 163 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) 164 OVERRIDE; 165 166 void IncreaseFrameSize(size_t adjust) OVERRIDE; 167 void DecreaseFrameSize(size_t adjust) OVERRIDE; 168 169 // Store routines 170 void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE; 171 void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE; 172 void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE; 173 174 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE; 175 176 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister mscratch) 177 OVERRIDE; 178 179 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, 180 ManagedRegister mscratch) OVERRIDE; 181 182 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE; 183 184 void StoreSpanning(FrameOffset dest, ManagedRegister msrc, FrameOffset in_off, 185 ManagedRegister mscratch) OVERRIDE; 186 187 // Load routines 188 void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE; 189 190 void LoadFromThread32(ManagedRegister mdest, ThreadOffset<4> src, size_t size) OVERRIDE; 191 192 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 193 194 void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 195 bool poison_reference) 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, 246 ManagedRegister in_reg, 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, 251 ManagedRegister mscratch, 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