1 /* 2 * Copyright (C) 2014 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_MIPS64_ASSEMBLER_MIPS64_H_ 18 #define ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_ 19 20 #include <vector> 21 22 #include "base/macros.h" 23 #include "constants_mips64.h" 24 #include "globals.h" 25 #include "managed_register_mips64.h" 26 #include "utils/assembler.h" 27 #include "offsets.h" 28 29 namespace art { 30 namespace mips64 { 31 32 enum LoadOperandType { 33 kLoadSignedByte, 34 kLoadUnsignedByte, 35 kLoadSignedHalfword, 36 kLoadUnsignedHalfword, 37 kLoadWord, 38 kLoadUnsignedWord, 39 kLoadDoubleword 40 }; 41 42 enum StoreOperandType { 43 kStoreByte, 44 kStoreHalfword, 45 kStoreWord, 46 kStoreDoubleword 47 }; 48 49 class Mips64Assembler FINAL : public Assembler { 50 public: Mips64Assembler()51 Mips64Assembler() {} ~Mips64Assembler()52 virtual ~Mips64Assembler() {} 53 54 // Emit Machine Instructions. 55 void Add(GpuRegister rd, GpuRegister rs, GpuRegister rt); 56 void Addi(GpuRegister rt, GpuRegister rs, uint16_t imm16); 57 void Addu(GpuRegister rd, GpuRegister rs, GpuRegister rt); 58 void Addiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 59 void Daddu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 60 void Daddiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 61 void Sub(GpuRegister rd, GpuRegister rs, GpuRegister rt); 62 void Subu(GpuRegister rd, GpuRegister rs, GpuRegister rt); 63 void Dsubu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 64 65 void MultR2(GpuRegister rs, GpuRegister rt); // R2 66 void MultuR2(GpuRegister rs, GpuRegister rt); // R2 67 void DivR2(GpuRegister rs, GpuRegister rt); // R2 68 void DivuR2(GpuRegister rs, GpuRegister rt); // R2 69 void MulR2(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R2 70 void DivR2(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R2 71 void ModR2(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R2 72 void DivuR2(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R2 73 void ModuR2(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R2 74 void MulR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R6 75 void DivR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R6 76 void ModR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R6 77 void DivuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R6 78 void ModuR6(GpuRegister rd, GpuRegister rs, GpuRegister rt); // R6 79 void Dmul(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 R6 80 void Ddiv(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 R6 81 void Dmod(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 R6 82 void Ddivu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 R6 83 void Dmodu(GpuRegister rd, GpuRegister rs, GpuRegister rt); // MIPS64 R6 84 85 void And(GpuRegister rd, GpuRegister rs, GpuRegister rt); 86 void Andi(GpuRegister rt, GpuRegister rs, uint16_t imm16); 87 void Or(GpuRegister rd, GpuRegister rs, GpuRegister rt); 88 void Ori(GpuRegister rt, GpuRegister rs, uint16_t imm16); 89 void Xor(GpuRegister rd, GpuRegister rs, GpuRegister rt); 90 void Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16); 91 void Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt); 92 93 void Seb(GpuRegister rd, GpuRegister rt); // R2+ 94 void Seh(GpuRegister rd, GpuRegister rt); // R2+ 95 void Dext(GpuRegister rs, GpuRegister rt, int pos, int size_less_one); // MIPS64 96 97 void Sll(GpuRegister rd, GpuRegister rt, int shamt); 98 void Srl(GpuRegister rd, GpuRegister rt, int shamt); 99 void Sra(GpuRegister rd, GpuRegister rt, int shamt); 100 void Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs); 101 void Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs); 102 void Srav(GpuRegister rd, GpuRegister rt, GpuRegister rs); 103 void Dsll(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 104 void Dsrl(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 105 void Dsra(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 106 void Dsll32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 107 void Dsrl32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 108 void Dsra32(GpuRegister rd, GpuRegister rt, int shamt); // MIPS64 109 void Dsllv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64 110 void Dsrlv(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64 111 void Dsrav(GpuRegister rd, GpuRegister rt, GpuRegister rs); // MIPS64 112 113 void Lb(GpuRegister rt, GpuRegister rs, uint16_t imm16); 114 void Lh(GpuRegister rt, GpuRegister rs, uint16_t imm16); 115 void Lw(GpuRegister rt, GpuRegister rs, uint16_t imm16); 116 void Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 117 void Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 118 void Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 119 void Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 120 void Lui(GpuRegister rt, uint16_t imm16); 121 void Dahi(GpuRegister rs, uint16_t imm16); // MIPS64 R6 122 void Dati(GpuRegister rs, uint16_t imm16); // MIPS64 R6 123 void Sync(uint32_t stype); 124 void Mfhi(GpuRegister rd); // R2 125 void Mflo(GpuRegister rd); // R2 126 127 void Sb(GpuRegister rt, GpuRegister rs, uint16_t imm16); 128 void Sh(GpuRegister rt, GpuRegister rs, uint16_t imm16); 129 void Sw(GpuRegister rt, GpuRegister rs, uint16_t imm16); 130 void Sd(GpuRegister rt, GpuRegister rs, uint16_t imm16); // MIPS64 131 132 void Slt(GpuRegister rd, GpuRegister rs, GpuRegister rt); 133 void Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt); 134 void Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16); 135 void Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); 136 137 void Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16); 138 void Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16); 139 void J(uint32_t addr26); 140 void Jal(uint32_t addr26); 141 void Jalr(GpuRegister rd, GpuRegister rs); 142 void Jalr(GpuRegister rs); 143 void Jr(GpuRegister rs); 144 void Auipc(GpuRegister rs, uint16_t imm16); // R6 145 void Jic(GpuRegister rt, uint16_t imm16); // R6 146 void Jialc(GpuRegister rt, uint16_t imm16); // R6 147 void Bltc(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R6 148 void Bltzc(GpuRegister rt, uint16_t imm16); // R6 149 void Bgtzc(GpuRegister rt, uint16_t imm16); // R6 150 void Bgec(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R6 151 void Bgezc(GpuRegister rt, uint16_t imm16); // R6 152 void Blezc(GpuRegister rt, uint16_t imm16); // R6 153 void Bltuc(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R6 154 void Bgeuc(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R6 155 void Beqc(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R6 156 void Bnec(GpuRegister rs, GpuRegister rt, uint16_t imm16); // R6 157 void Beqzc(GpuRegister rs, uint32_t imm21); // R6 158 void Bnezc(GpuRegister rs, uint32_t imm21); // R6 159 160 void AddS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 161 void SubS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 162 void MulS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 163 void DivS(FpuRegister fd, FpuRegister fs, FpuRegister ft); 164 void AddD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 165 void SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 166 void MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 167 void DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft); 168 void MovS(FpuRegister fd, FpuRegister fs); 169 void MovD(FpuRegister fd, FpuRegister fs); 170 void NegS(FpuRegister fd, FpuRegister fs); 171 void NegD(FpuRegister fd, FpuRegister fs); 172 173 void Cvtsw(FpuRegister fd, FpuRegister fs); 174 void Cvtdw(FpuRegister fd, FpuRegister fs); 175 void Cvtsd(FpuRegister fd, FpuRegister fs); 176 void Cvtds(FpuRegister fd, FpuRegister fs); 177 178 void Mfc1(GpuRegister rt, FpuRegister fs); 179 void Mtc1(GpuRegister rt, FpuRegister fs); 180 void Dmfc1(GpuRegister rt, FpuRegister fs); // MIPS64 181 void Dmtc1(GpuRegister rt, FpuRegister fs); // MIPS64 182 void Lwc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 183 void Ldc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 184 void Swc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 185 void Sdc1(FpuRegister ft, GpuRegister rs, uint16_t imm16); 186 187 void Break(); 188 void Nop(); 189 void Move(GpuRegister rd, GpuRegister rs); 190 void Clear(GpuRegister rd); 191 void Not(GpuRegister rd, GpuRegister rs); 192 193 // Higher level composite instructions 194 void LoadConst32(GpuRegister rd, int32_t value); 195 void LoadConst64(GpuRegister rd, int64_t value); // MIPS64 196 197 void Addiu32(GpuRegister rt, GpuRegister rs, int32_t value, GpuRegister rtmp = AT); 198 void Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp = AT); // MIPS64 199 200 void Bind(Label* label); // R6 201 void B(Label* label); // R6 202 void Jalr(Label* label, GpuRegister indirect_reg = RA); // R6 203 // TODO: implement common for R6 and non-R6 interface for conditional branches? 204 void Bltc(GpuRegister rs, GpuRegister rt, Label* label); // R6 205 void Bltzc(GpuRegister rt, Label* label); // R6 206 void Bgtzc(GpuRegister rt, Label* label); // R6 207 void Bgec(GpuRegister rs, GpuRegister rt, Label* label); // R6 208 void Bgezc(GpuRegister rt, Label* label); // R6 209 void Blezc(GpuRegister rt, Label* label); // R6 210 void Bltuc(GpuRegister rs, GpuRegister rt, Label* label); // R6 211 void Bgeuc(GpuRegister rs, GpuRegister rt, Label* label); // R6 212 void Beqc(GpuRegister rs, GpuRegister rt, Label* label); // R6 213 void Bnec(GpuRegister rs, GpuRegister rt, Label* label); // R6 214 void Beqzc(GpuRegister rs, Label* label); // R6 215 void Bnezc(GpuRegister rs, Label* label); // R6 216 217 void EmitLoad(ManagedRegister m_dst, GpuRegister src_register, int32_t src_offset, size_t size); 218 void LoadFromOffset(LoadOperandType type, GpuRegister reg, GpuRegister base, int32_t offset); 219 void LoadFpuFromOffset(LoadOperandType type, FpuRegister reg, GpuRegister base, int32_t offset); 220 void StoreToOffset(StoreOperandType type, GpuRegister reg, GpuRegister base, int32_t offset); 221 void StoreFpuToOffset(StoreOperandType type, FpuRegister reg, GpuRegister base, int32_t offset); 222 223 // Emit data (e.g. encoded instruction or immediate) to the instruction stream. 224 void Emit(uint32_t value); 225 226 // 227 // Overridden common assembler high-level functionality 228 // 229 230 // Emit code that will create an activation on the stack 231 void BuildFrame(size_t frame_size, ManagedRegister method_reg, 232 const std::vector<ManagedRegister>& callee_save_regs, 233 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 234 235 // Emit code that will remove an activation from the stack 236 void RemoveFrame(size_t frame_size, 237 const std::vector<ManagedRegister>& callee_save_regs) OVERRIDE; 238 239 void IncreaseFrameSize(size_t adjust) OVERRIDE; 240 void DecreaseFrameSize(size_t adjust) OVERRIDE; 241 242 // Store routines 243 void Store(FrameOffset offs, ManagedRegister msrc, size_t size) OVERRIDE; 244 void StoreRef(FrameOffset dest, ManagedRegister msrc) OVERRIDE; 245 void StoreRawPtr(FrameOffset dest, ManagedRegister msrc) OVERRIDE; 246 247 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister mscratch) OVERRIDE; 248 249 void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, 250 ManagedRegister mscratch) OVERRIDE; 251 252 void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, 253 ManagedRegister mscratch) OVERRIDE; 254 255 void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE; 256 257 void StoreSpanning(FrameOffset dest, ManagedRegister msrc, FrameOffset in_off, 258 ManagedRegister mscratch) OVERRIDE; 259 260 // Load routines 261 void Load(ManagedRegister mdest, FrameOffset src, size_t size) OVERRIDE; 262 263 void LoadFromThread64(ManagedRegister mdest, ThreadOffset<8> src, size_t size) OVERRIDE; 264 265 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 266 267 void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs, 268 bool poison_reference) OVERRIDE; 269 270 void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE; 271 272 void LoadRawPtrFromThread64(ManagedRegister mdest, ThreadOffset<8> offs) OVERRIDE; 273 274 // Copying routines 275 void Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) OVERRIDE; 276 277 void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs, 278 ManagedRegister mscratch) OVERRIDE; 279 280 void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, 281 ManagedRegister mscratch) OVERRIDE; 282 283 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) OVERRIDE; 284 285 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch, size_t size) OVERRIDE; 286 287 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister mscratch, 288 size_t size) OVERRIDE; 289 290 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 291 ManagedRegister mscratch, size_t size) OVERRIDE; 292 293 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister mscratch, 294 size_t size) OVERRIDE; 295 296 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, 297 ManagedRegister mscratch, size_t size) OVERRIDE; 298 299 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 300 ManagedRegister mscratch, size_t size) OVERRIDE; 301 302 void MemoryBarrier(ManagedRegister) OVERRIDE; 303 304 // Sign extension 305 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; 306 307 // Zero extension 308 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE; 309 310 // Exploit fast access in managed code to Thread::Current() 311 void GetCurrentThread(ManagedRegister tr) OVERRIDE; 312 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister mscratch) OVERRIDE; 313 314 // Set up out_reg to hold a Object** into the handle scope, or to be null if the 315 // value is null and null_allowed. in_reg holds a possibly stale reference 316 // that can be used to avoid loading the handle scope entry to see if the value is 317 // null. 318 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, 319 ManagedRegister in_reg, bool null_allowed) OVERRIDE; 320 321 // Set up out_off to hold a Object** into the handle scope, or to be null if the 322 // value is null and null_allowed. 323 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister 324 mscratch, bool null_allowed) OVERRIDE; 325 326 // src holds a handle scope entry (Object**) load this into dst 327 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE; 328 329 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 330 // know that src may not be null. 331 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE; 332 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE; 333 334 // Call to address held at [base+offset] 335 void Call(ManagedRegister base, Offset offset, ManagedRegister mscratch) OVERRIDE; 336 void Call(FrameOffset base, Offset offset, ManagedRegister mscratch) OVERRIDE; 337 void CallFromThread64(ThreadOffset<8> offset, ManagedRegister mscratch) OVERRIDE; 338 339 // Generate code to check if Thread::Current()->exception_ is non-null 340 // and branch to a ExceptionSlowPath if it is. 341 void ExceptionPoll(ManagedRegister mscratch, size_t stack_adjust) OVERRIDE; 342 343 private: 344 void EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd, int shamt, int funct); 345 void EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm); 346 void EmitI21(int opcode, GpuRegister rs, uint32_t imm21); 347 void EmitJ(int opcode, uint32_t addr26); 348 void EmitFR(int opcode, int fmt, FpuRegister ft, FpuRegister fs, FpuRegister fd, int funct); 349 void EmitFI(int opcode, int fmt, FpuRegister rt, uint16_t imm); 350 351 DISALLOW_COPY_AND_ASSIGN(Mips64Assembler); 352 }; 353 354 // Slowpath entered when Thread::Current()->_exception is non-null 355 class Mips64ExceptionSlowPath FINAL : public SlowPath { 356 public: Mips64ExceptionSlowPath(Mips64ManagedRegister scratch,size_t stack_adjust)357 explicit Mips64ExceptionSlowPath(Mips64ManagedRegister scratch, size_t stack_adjust) 358 : scratch_(scratch), stack_adjust_(stack_adjust) {} 359 virtual void Emit(Assembler *sp_asm) OVERRIDE; 360 private: 361 const Mips64ManagedRegister scratch_; 362 const size_t stack_adjust_; 363 }; 364 365 } // namespace mips64 366 } // namespace art 367 368 #endif // ART_COMPILER_UTILS_MIPS64_ASSEMBLER_MIPS64_H_ 369