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