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_ARM_ASSEMBLER_ARM_H_ 18 #define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_ 19 20 #include <vector> 21 22 #include "base/logging.h" 23 #include "constants_arm.h" 24 #include "utils/arm/managed_register_arm.h" 25 #include "utils/assembler.h" 26 #include "offsets.h" 27 #include "utils.h" 28 29 namespace art { 30 namespace arm { 31 32 // Encodes Addressing Mode 1 - Data-processing operands defined in Section 5.1. 33 class ShifterOperand { 34 public: 35 // Data-processing operands - Uninitialized 36 ShifterOperand() { 37 type_ = -1; 38 } 39 40 // Data-processing operands - Immediate 41 explicit ShifterOperand(uint32_t immediate) { 42 CHECK(immediate < (1 << kImmed8Bits)); 43 type_ = 1; 44 encoding_ = immediate; 45 } 46 47 // Data-processing operands - Rotated immediate 48 ShifterOperand(uint32_t rotate, uint32_t immed8) { 49 CHECK((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits))); 50 type_ = 1; 51 encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift); 52 } 53 54 // Data-processing operands - Register 55 explicit ShifterOperand(Register rm) { 56 type_ = 0; 57 encoding_ = static_cast<uint32_t>(rm); 58 } 59 60 // Data-processing operands - Logical shift/rotate by immediate 61 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm) { 62 CHECK(shift_imm < (1 << kShiftImmBits)); 63 type_ = 0; 64 encoding_ = shift_imm << kShiftImmShift | 65 static_cast<uint32_t>(shift) << kShiftShift | 66 static_cast<uint32_t>(rm); 67 } 68 69 // Data-processing operands - Logical shift/rotate by register 70 ShifterOperand(Register rm, Shift shift, Register rs) { 71 type_ = 0; 72 encoding_ = static_cast<uint32_t>(rs) << kShiftRegisterShift | 73 static_cast<uint32_t>(shift) << kShiftShift | (1 << 4) | 74 static_cast<uint32_t>(rm); 75 } 76 77 static bool CanHold(uint32_t immediate, ShifterOperand* shifter_op) { 78 // Avoid the more expensive test for frequent small immediate values. 79 if (immediate < (1 << kImmed8Bits)) { 80 shifter_op->type_ = 1; 81 shifter_op->encoding_ = (0 << kRotateShift) | (immediate << kImmed8Shift); 82 return true; 83 } 84 // Note that immediate must be unsigned for the test to work correctly. 85 for (int rot = 0; rot < 16; rot++) { 86 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot)); 87 if (imm8 < (1 << kImmed8Bits)) { 88 shifter_op->type_ = 1; 89 shifter_op->encoding_ = (rot << kRotateShift) | (imm8 << kImmed8Shift); 90 return true; 91 } 92 } 93 return false; 94 } 95 96 private: 97 bool is_valid() const { return (type_ == 0) || (type_ == 1); } 98 99 uint32_t type() const { 100 CHECK(is_valid()); 101 return type_; 102 } 103 104 uint32_t encoding() const { 105 CHECK(is_valid()); 106 return encoding_; 107 } 108 109 uint32_t type_; // Encodes the type field (bits 27-25) in the instruction. 110 uint32_t encoding_; 111 112 friend class ArmAssembler; 113 #ifdef SOURCE_ASSEMBLER_SUPPORT 114 friend class BinaryAssembler; 115 #endif 116 }; 117 118 119 enum LoadOperandType { 120 kLoadSignedByte, 121 kLoadUnsignedByte, 122 kLoadSignedHalfword, 123 kLoadUnsignedHalfword, 124 kLoadWord, 125 kLoadWordPair, 126 kLoadSWord, 127 kLoadDWord 128 }; 129 130 131 enum StoreOperandType { 132 kStoreByte, 133 kStoreHalfword, 134 kStoreWord, 135 kStoreWordPair, 136 kStoreSWord, 137 kStoreDWord 138 }; 139 140 141 // Load/store multiple addressing mode. 142 enum BlockAddressMode { 143 // bit encoding P U W 144 DA = (0|0|0) << 21, // decrement after 145 IA = (0|4|0) << 21, // increment after 146 DB = (8|0|0) << 21, // decrement before 147 IB = (8|4|0) << 21, // increment before 148 DA_W = (0|0|1) << 21, // decrement after with writeback to base 149 IA_W = (0|4|1) << 21, // increment after with writeback to base 150 DB_W = (8|0|1) << 21, // decrement before with writeback to base 151 IB_W = (8|4|1) << 21 // increment before with writeback to base 152 }; 153 154 155 class Address { 156 public: 157 // Memory operand addressing mode 158 enum Mode { 159 // bit encoding P U W 160 Offset = (8|4|0) << 21, // offset (w/o writeback to base) 161 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback 162 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback 163 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base) 164 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback 165 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback 166 }; 167 168 explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) { 169 CHECK(IsAbsoluteUint(12, offset)); 170 if (offset < 0) { 171 encoding_ = (am ^ (1 << kUShift)) | -offset; // Flip U to adjust sign. 172 } else { 173 encoding_ = am | offset; 174 } 175 encoding_ |= static_cast<uint32_t>(rn) << kRnShift; 176 } 177 178 static bool CanHoldLoadOffset(LoadOperandType type, int offset); 179 static bool CanHoldStoreOffset(StoreOperandType type, int offset); 180 181 private: 182 uint32_t encoding() const { return encoding_; } 183 184 // Encoding for addressing mode 3. 185 uint32_t encoding3() const { 186 const uint32_t offset_mask = (1 << 12) - 1; 187 uint32_t offset = encoding_ & offset_mask; 188 CHECK_LT(offset, 256u); 189 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf); 190 } 191 192 // Encoding for vfp load/store addressing. 193 uint32_t vencoding() const { 194 const uint32_t offset_mask = (1 << 12) - 1; 195 uint32_t offset = encoding_ & offset_mask; 196 CHECK(IsAbsoluteUint(10, offset)); // In the range -1020 to +1020. 197 CHECK_ALIGNED(offset, 2); // Multiple of 4. 198 int mode = encoding_ & ((8|4|1) << 21); 199 CHECK((mode == Offset) || (mode == NegOffset)); 200 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2); 201 if (mode == Offset) { 202 vencoding |= 1 << 23; 203 } 204 return vencoding; 205 } 206 207 uint32_t encoding_; 208 209 friend class ArmAssembler; 210 }; 211 212 213 class ArmAssembler : public Assembler { 214 public: 215 ArmAssembler() {} 216 virtual ~ArmAssembler() {} 217 218 // Data-processing instructions. 219 void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 220 221 void eor(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 222 223 void sub(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 224 void subs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 225 226 void rsb(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 227 void rsbs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 228 229 void add(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 230 231 void adds(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 232 233 void adc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 234 235 void sbc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 236 237 void rsc(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 238 239 void tst(Register rn, ShifterOperand so, Condition cond = AL); 240 241 void teq(Register rn, ShifterOperand so, Condition cond = AL); 242 243 void cmp(Register rn, ShifterOperand so, Condition cond = AL); 244 245 void cmn(Register rn, ShifterOperand so, Condition cond = AL); 246 247 void orr(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 248 void orrs(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 249 250 void mov(Register rd, ShifterOperand so, Condition cond = AL); 251 void movs(Register rd, ShifterOperand so, Condition cond = AL); 252 253 void bic(Register rd, Register rn, ShifterOperand so, Condition cond = AL); 254 255 void mvn(Register rd, ShifterOperand so, Condition cond = AL); 256 void mvns(Register rd, ShifterOperand so, Condition cond = AL); 257 258 // Miscellaneous data-processing instructions. 259 void clz(Register rd, Register rm, Condition cond = AL); 260 void movw(Register rd, uint16_t imm16, Condition cond = AL); 261 void movt(Register rd, uint16_t imm16, Condition cond = AL); 262 263 // Multiply instructions. 264 void mul(Register rd, Register rn, Register rm, Condition cond = AL); 265 void mla(Register rd, Register rn, Register rm, Register ra, 266 Condition cond = AL); 267 void mls(Register rd, Register rn, Register rm, Register ra, 268 Condition cond = AL); 269 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, 270 Condition cond = AL); 271 272 // Load/store instructions. 273 void ldr(Register rd, Address ad, Condition cond = AL); 274 void str(Register rd, Address ad, Condition cond = AL); 275 276 void ldrb(Register rd, Address ad, Condition cond = AL); 277 void strb(Register rd, Address ad, Condition cond = AL); 278 279 void ldrh(Register rd, Address ad, Condition cond = AL); 280 void strh(Register rd, Address ad, Condition cond = AL); 281 282 void ldrsb(Register rd, Address ad, Condition cond = AL); 283 void ldrsh(Register rd, Address ad, Condition cond = AL); 284 285 void ldrd(Register rd, Address ad, Condition cond = AL); 286 void strd(Register rd, Address ad, Condition cond = AL); 287 288 void ldm(BlockAddressMode am, Register base, 289 RegList regs, Condition cond = AL); 290 void stm(BlockAddressMode am, Register base, 291 RegList regs, Condition cond = AL); 292 293 void ldrex(Register rd, Register rn, Condition cond = AL); 294 void strex(Register rd, Register rt, Register rn, Condition cond = AL); 295 296 // Miscellaneous instructions. 297 void clrex(); 298 void nop(Condition cond = AL); 299 300 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. 301 void bkpt(uint16_t imm16); 302 void svc(uint32_t imm24); 303 304 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). 305 void vmovsr(SRegister sn, Register rt, Condition cond = AL); 306 void vmovrs(Register rt, SRegister sn, Condition cond = AL); 307 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL); 308 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL); 309 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL); 310 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL); 311 void vmovs(SRegister sd, SRegister sm, Condition cond = AL); 312 void vmovd(DRegister dd, DRegister dm, Condition cond = AL); 313 314 // Returns false if the immediate cannot be encoded. 315 bool vmovs(SRegister sd, float s_imm, Condition cond = AL); 316 bool vmovd(DRegister dd, double d_imm, Condition cond = AL); 317 318 void vldrs(SRegister sd, Address ad, Condition cond = AL); 319 void vstrs(SRegister sd, Address ad, Condition cond = AL); 320 void vldrd(DRegister dd, Address ad, Condition cond = AL); 321 void vstrd(DRegister dd, Address ad, Condition cond = AL); 322 323 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); 324 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); 325 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); 326 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); 327 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); 328 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); 329 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); 330 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); 331 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); 332 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); 333 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); 334 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); 335 336 void vabss(SRegister sd, SRegister sm, Condition cond = AL); 337 void vabsd(DRegister dd, DRegister dm, Condition cond = AL); 338 void vnegs(SRegister sd, SRegister sm, Condition cond = AL); 339 void vnegd(DRegister dd, DRegister dm, Condition cond = AL); 340 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL); 341 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL); 342 343 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL); 344 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL); 345 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL); 346 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL); 347 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL); 348 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL); 349 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL); 350 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL); 351 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL); 352 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL); 353 354 void vcmps(SRegister sd, SRegister sm, Condition cond = AL); 355 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL); 356 void vcmpsz(SRegister sd, Condition cond = AL); 357 void vcmpdz(DRegister dd, Condition cond = AL); 358 void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR 359 360 // Branch instructions. 361 void b(Label* label, Condition cond = AL); 362 void bl(Label* label, Condition cond = AL); 363 void blx(Register rm, Condition cond = AL); 364 void bx(Register rm, Condition cond = AL); 365 366 // Macros. 367 // Add signed constant value to rd. May clobber IP. 368 void AddConstant(Register rd, int32_t value, Condition cond = AL); 369 void AddConstant(Register rd, Register rn, int32_t value, 370 Condition cond = AL); 371 void AddConstantSetFlags(Register rd, Register rn, int32_t value, 372 Condition cond = AL); 373 void AddConstantWithCarry(Register rd, Register rn, int32_t value, 374 Condition cond = AL); 375 376 // Load and Store. May clobber IP. 377 void LoadImmediate(Register rd, int32_t value, Condition cond = AL); 378 void LoadSImmediate(SRegister sd, float value, Condition cond = AL); 379 void LoadDImmediate(DRegister dd, double value, 380 Register scratch, Condition cond = AL); 381 void MarkExceptionHandler(Label* label); 382 void LoadFromOffset(LoadOperandType type, 383 Register reg, 384 Register base, 385 int32_t offset, 386 Condition cond = AL); 387 void StoreToOffset(StoreOperandType type, 388 Register reg, 389 Register base, 390 int32_t offset, 391 Condition cond = AL); 392 void LoadSFromOffset(SRegister reg, 393 Register base, 394 int32_t offset, 395 Condition cond = AL); 396 void StoreSToOffset(SRegister reg, 397 Register base, 398 int32_t offset, 399 Condition cond = AL); 400 void LoadDFromOffset(DRegister reg, 401 Register base, 402 int32_t offset, 403 Condition cond = AL); 404 void StoreDToOffset(DRegister reg, 405 Register base, 406 int32_t offset, 407 Condition cond = AL); 408 409 void Push(Register rd, Condition cond = AL); 410 void Pop(Register rd, Condition cond = AL); 411 412 void PushList(RegList regs, Condition cond = AL); 413 void PopList(RegList regs, Condition cond = AL); 414 415 void Mov(Register rd, Register rm, Condition cond = AL); 416 417 // Convenience shift instructions. Use mov instruction with shifter operand 418 // for variants setting the status flags or using a register shift count. 419 void Lsl(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); 420 void Lsr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); 421 void Asr(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); 422 void Ror(Register rd, Register rm, uint32_t shift_imm, Condition cond = AL); 423 void Rrx(Register rd, Register rm, Condition cond = AL); 424 425 // Encode a signed constant in tst instructions, only affecting the flags. 426 void EncodeUint32InTstInstructions(uint32_t data); 427 // ... and decode from a pc pointing to the start of encoding instructions. 428 static uint32_t DecodeUint32FromTstInstructions(uword pc); 429 static bool IsInstructionForExceptionHandling(uword pc); 430 431 // Emit data (e.g. encoded instruction or immediate) to the 432 // instruction stream. 433 void Emit(int32_t value); 434 void Bind(Label* label); 435 436 // 437 // Overridden common assembler high-level functionality 438 // 439 440 // Emit code that will create an activation on the stack 441 virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg, 442 const std::vector<ManagedRegister>& callee_save_regs, 443 const std::vector<ManagedRegister>& entry_spills); 444 445 // Emit code that will remove an activation from the stack 446 virtual void RemoveFrame(size_t frame_size, 447 const std::vector<ManagedRegister>& callee_save_regs); 448 449 virtual void IncreaseFrameSize(size_t adjust); 450 virtual void DecreaseFrameSize(size_t adjust); 451 452 // Store routines 453 virtual void Store(FrameOffset offs, ManagedRegister src, size_t size); 454 virtual void StoreRef(FrameOffset dest, ManagedRegister src); 455 virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src); 456 457 virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, 458 ManagedRegister scratch); 459 460 virtual void StoreImmediateToThread(ThreadOffset dest, uint32_t imm, 461 ManagedRegister scratch); 462 463 virtual void StoreStackOffsetToThread(ThreadOffset thr_offs, 464 FrameOffset fr_offs, 465 ManagedRegister scratch); 466 467 virtual void StoreStackPointerToThread(ThreadOffset thr_offs); 468 469 virtual void StoreSpanning(FrameOffset dest, ManagedRegister src, 470 FrameOffset in_off, ManagedRegister scratch); 471 472 // Load routines 473 virtual void Load(ManagedRegister dest, FrameOffset src, size_t size); 474 475 virtual void Load(ManagedRegister dest, ThreadOffset src, size_t size); 476 477 virtual void LoadRef(ManagedRegister dest, FrameOffset src); 478 479 virtual void LoadRef(ManagedRegister dest, ManagedRegister base, 480 MemberOffset offs); 481 482 virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base, 483 Offset offs); 484 485 virtual void LoadRawPtrFromThread(ManagedRegister dest, 486 ThreadOffset offs); 487 488 // Copying routines 489 virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size); 490 491 virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset thr_offs, 492 ManagedRegister scratch); 493 494 virtual void CopyRawPtrToThread(ThreadOffset thr_offs, FrameOffset fr_offs, 495 ManagedRegister scratch); 496 497 virtual void CopyRef(FrameOffset dest, FrameOffset src, 498 ManagedRegister scratch); 499 500 virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size); 501 502 virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, 503 ManagedRegister scratch, size_t size); 504 505 virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, 506 ManagedRegister scratch, size_t size); 507 508 virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, 509 ManagedRegister scratch, size_t size); 510 511 virtual void Copy(ManagedRegister dest, Offset dest_offset, 512 ManagedRegister src, Offset src_offset, 513 ManagedRegister scratch, size_t size); 514 515 virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 516 ManagedRegister scratch, size_t size); 517 518 virtual void MemoryBarrier(ManagedRegister scratch); 519 520 // Sign extension 521 virtual void SignExtend(ManagedRegister mreg, size_t size); 522 523 // Zero extension 524 virtual void ZeroExtend(ManagedRegister mreg, size_t size); 525 526 // Exploit fast access in managed code to Thread::Current() 527 virtual void GetCurrentThread(ManagedRegister tr); 528 virtual void GetCurrentThread(FrameOffset dest_offset, 529 ManagedRegister scratch); 530 531 // Set up out_reg to hold a Object** into the SIRT, or to be NULL if the 532 // value is null and null_allowed. in_reg holds a possibly stale reference 533 // that can be used to avoid loading the SIRT entry to see if the value is 534 // NULL. 535 virtual void CreateSirtEntry(ManagedRegister out_reg, FrameOffset sirt_offset, 536 ManagedRegister in_reg, bool null_allowed); 537 538 // Set up out_off to hold a Object** into the SIRT, or to be NULL if the 539 // value is null and null_allowed. 540 virtual void CreateSirtEntry(FrameOffset out_off, FrameOffset sirt_offset, 541 ManagedRegister scratch, bool null_allowed); 542 543 // src holds a SIRT entry (Object**) load this into dst 544 virtual void LoadReferenceFromSirt(ManagedRegister dst, 545 ManagedRegister src); 546 547 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 548 // know that src may not be null. 549 virtual void VerifyObject(ManagedRegister src, bool could_be_null); 550 virtual void VerifyObject(FrameOffset src, bool could_be_null); 551 552 // Call to address held at [base+offset] 553 virtual void Call(ManagedRegister base, Offset offset, 554 ManagedRegister scratch); 555 virtual void Call(FrameOffset base, Offset offset, 556 ManagedRegister scratch); 557 virtual void Call(ThreadOffset offset, ManagedRegister scratch); 558 559 // Generate code to check if Thread::Current()->exception_ is non-null 560 // and branch to a ExceptionSlowPath if it is. 561 virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust); 562 563 private: 564 void EmitType01(Condition cond, 565 int type, 566 Opcode opcode, 567 int set_cc, 568 Register rn, 569 Register rd, 570 ShifterOperand so); 571 572 void EmitType5(Condition cond, int offset, bool link); 573 574 void EmitMemOp(Condition cond, 575 bool load, 576 bool byte, 577 Register rd, 578 Address ad); 579 580 void EmitMemOpAddressMode3(Condition cond, 581 int32_t mode, 582 Register rd, 583 Address ad); 584 585 void EmitMultiMemOp(Condition cond, 586 BlockAddressMode am, 587 bool load, 588 Register base, 589 RegList regs); 590 591 void EmitShiftImmediate(Condition cond, 592 Shift opcode, 593 Register rd, 594 Register rm, 595 ShifterOperand so); 596 597 void EmitShiftRegister(Condition cond, 598 Shift opcode, 599 Register rd, 600 Register rm, 601 ShifterOperand so); 602 603 void EmitMulOp(Condition cond, 604 int32_t opcode, 605 Register rd, 606 Register rn, 607 Register rm, 608 Register rs); 609 610 void EmitVFPsss(Condition cond, 611 int32_t opcode, 612 SRegister sd, 613 SRegister sn, 614 SRegister sm); 615 616 void EmitVFPddd(Condition cond, 617 int32_t opcode, 618 DRegister dd, 619 DRegister dn, 620 DRegister dm); 621 622 void EmitVFPsd(Condition cond, 623 int32_t opcode, 624 SRegister sd, 625 DRegister dm); 626 627 void EmitVFPds(Condition cond, 628 int32_t opcode, 629 DRegister dd, 630 SRegister sm); 631 632 void EmitBranch(Condition cond, Label* label, bool link); 633 static int32_t EncodeBranchOffset(int offset, int32_t inst); 634 static int DecodeBranchOffset(int32_t inst); 635 int32_t EncodeTstOffset(int offset, int32_t inst); 636 int DecodeTstOffset(int32_t inst); 637 638 // Returns whether or not the given register is used for passing parameters. 639 static int RegisterCompare(const Register* reg1, const Register* reg2) { 640 return *reg1 - *reg2; 641 } 642 }; 643 644 // Slowpath entered when Thread::Current()->_exception is non-null 645 class ArmExceptionSlowPath : public SlowPath { 646 public: 647 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust) 648 : scratch_(scratch), stack_adjust_(stack_adjust) { 649 } 650 virtual void Emit(Assembler *sp_asm); 651 private: 652 const ArmManagedRegister scratch_; 653 const size_t stack_adjust_; 654 }; 655 656 } // namespace arm 657 } // namespace art 658 659 #endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_ 660