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