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 class ShifterOperand { 33 public: ShifterOperand()34 ShifterOperand() : type_(kUnknown), rm_(kNoRegister), rs_(kNoRegister), 35 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) { 36 } 37 38 explicit ShifterOperand(uint32_t immed); 39 40 // Data-processing operands - Register ShifterOperand(Register rm)41 explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister), 42 is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) { 43 } 44 ShifterOperand(uint32_t rotate,uint32_t immed8)45 ShifterOperand(uint32_t rotate, uint32_t immed8) : type_(kImmediate), rm_(kNoRegister), 46 rs_(kNoRegister), 47 is_rotate_(true), is_shift_(false), shift_(kNoShift), rotate_(rotate), immed_(immed8) { 48 } 49 type_(kRegister)50 ShifterOperand(Register rm, Shift shift, uint32_t shift_imm = 0) : type_(kRegister), rm_(rm), 51 rs_(kNoRegister), 52 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(shift_imm) { 53 } 54 55 // Data-processing operands - Logical shift/rotate by register ShifterOperand(Register rm,Shift shift,Register rs)56 ShifterOperand(Register rm, Shift shift, Register rs) : type_(kRegister), rm_(rm), 57 rs_(rs), 58 is_rotate_(false), is_shift_(true), shift_(shift), rotate_(0), immed_(0) { 59 } 60 is_valid()61 bool is_valid() const { return (type_ == kImmediate) || (type_ == kRegister); } 62 type()63 uint32_t type() const { 64 CHECK(is_valid()); 65 return type_; 66 } 67 68 uint32_t encodingArm() const; 69 uint32_t encodingThumb() const; 70 IsEmpty()71 bool IsEmpty() const { 72 return type_ == kUnknown; 73 } 74 IsImmediate()75 bool IsImmediate() const { 76 return type_ == kImmediate; 77 } 78 IsRegister()79 bool IsRegister() const { 80 return type_ == kRegister; 81 } 82 IsShift()83 bool IsShift() const { 84 return is_shift_; 85 } 86 GetImmediate()87 uint32_t GetImmediate() const { 88 return immed_; 89 } 90 GetShift()91 Shift GetShift() const { 92 return shift_; 93 } 94 GetRegister()95 Register GetRegister() const { 96 return rm_; 97 } 98 99 enum Type { 100 kUnknown = -1, 101 kRegister, 102 kImmediate 103 }; 104 CanHoldArm(uint32_t immediate,ShifterOperand * shifter_op)105 static bool CanHoldArm(uint32_t immediate, ShifterOperand* shifter_op) { 106 // Avoid the more expensive test for frequent small immediate values. 107 if (immediate < (1 << kImmed8Bits)) { 108 shifter_op->type_ = kImmediate; 109 shifter_op->is_rotate_ = true; 110 shifter_op->rotate_ = 0; 111 shifter_op->immed_ = immediate; 112 return true; 113 } 114 // Note that immediate must be unsigned for the test to work correctly. 115 for (int rot = 0; rot < 16; rot++) { 116 uint32_t imm8 = (immediate << 2*rot) | (immediate >> (32 - 2*rot)); 117 if (imm8 < (1 << kImmed8Bits)) { 118 shifter_op->type_ = kImmediate; 119 shifter_op->is_rotate_ = true; 120 shifter_op->rotate_ = rot; 121 shifter_op->immed_ = imm8; 122 return true; 123 } 124 } 125 return false; 126 } 127 128 static bool CanHoldThumb(Register rd, Register rn, Opcode opcode, 129 uint32_t immediate, ShifterOperand* shifter_op); 130 131 132 private: 133 Type type_; 134 Register rm_; 135 Register rs_; 136 bool is_rotate_; 137 bool is_shift_; 138 Shift shift_; 139 uint32_t rotate_; 140 uint32_t immed_; 141 142 #ifdef SOURCE_ASSEMBLER_SUPPORT 143 friend class BinaryAssembler; 144 #endif 145 }; 146 147 148 enum LoadOperandType { 149 kLoadSignedByte, 150 kLoadUnsignedByte, 151 kLoadSignedHalfword, 152 kLoadUnsignedHalfword, 153 kLoadWord, 154 kLoadWordPair, 155 kLoadSWord, 156 kLoadDWord 157 }; 158 159 160 enum StoreOperandType { 161 kStoreByte, 162 kStoreHalfword, 163 kStoreWord, 164 kStoreWordPair, 165 kStoreSWord, 166 kStoreDWord 167 }; 168 169 170 // Load/store multiple addressing mode. 171 enum BlockAddressMode { 172 // bit encoding P U W 173 DA = (0|0|0) << 21, // decrement after 174 IA = (0|4|0) << 21, // increment after 175 DB = (8|0|0) << 21, // decrement before 176 IB = (8|4|0) << 21, // increment before 177 DA_W = (0|0|1) << 21, // decrement after with writeback to base 178 IA_W = (0|4|1) << 21, // increment after with writeback to base 179 DB_W = (8|0|1) << 21, // decrement before with writeback to base 180 IB_W = (8|4|1) << 21 // increment before with writeback to base 181 }; 182 183 class Address { 184 public: 185 // Memory operand addressing mode (in ARM encoding form. For others we need 186 // to adjust) 187 enum Mode { 188 // bit encoding P U W 189 Offset = (8|4|0) << 21, // offset (w/o writeback to base) 190 PreIndex = (8|4|1) << 21, // pre-indexed addressing with writeback 191 PostIndex = (0|4|0) << 21, // post-indexed addressing with writeback 192 NegOffset = (8|0|0) << 21, // negative offset (w/o writeback to base) 193 NegPreIndex = (8|0|1) << 21, // negative pre-indexed with writeback 194 NegPostIndex = (0|0|0) << 21 // negative post-indexed with writeback 195 }; 196 rn_(rn)197 Address(Register rn, int32_t offset = 0, Mode am = Offset) : rn_(rn), rm_(R0), 198 offset_(offset), 199 am_(am), is_immed_offset_(true), shift_(LSL) { 200 } 201 rn_(rn)202 Address(Register rn, Register rm, Mode am = Offset) : rn_(rn), rm_(rm), offset_(0), 203 am_(am), is_immed_offset_(false), shift_(LSL) { 204 CHECK_NE(rm, PC); 205 } 206 207 Address(Register rn, Register rm, Shift shift, uint32_t count, Mode am = Offset) : rn_(rn)208 rn_(rn), rm_(rm), offset_(count), 209 am_(am), is_immed_offset_(false), shift_(shift) { 210 CHECK_NE(rm, PC); 211 } 212 213 // LDR(literal) - pc relative load. Address(int32_t offset)214 explicit Address(int32_t offset) : 215 rn_(PC), rm_(R0), offset_(offset), 216 am_(Offset), is_immed_offset_(false), shift_(LSL) { 217 } 218 219 static bool CanHoldLoadOffsetArm(LoadOperandType type, int offset); 220 static bool CanHoldStoreOffsetArm(StoreOperandType type, int offset); 221 222 static bool CanHoldLoadOffsetThumb(LoadOperandType type, int offset); 223 static bool CanHoldStoreOffsetThumb(StoreOperandType type, int offset); 224 225 uint32_t encodingArm() const; 226 uint32_t encodingThumb(bool is_32bit) const; 227 228 uint32_t encoding3() const; 229 uint32_t vencoding() const; 230 231 uint32_t encodingThumbLdrdStrd() const; 232 GetRegister()233 Register GetRegister() const { 234 return rn_; 235 } 236 GetRegisterOffset()237 Register GetRegisterOffset() const { 238 return rm_; 239 } 240 GetOffset()241 int32_t GetOffset() const { 242 return offset_; 243 } 244 GetMode()245 Mode GetMode() const { 246 return am_; 247 } 248 IsImmediate()249 bool IsImmediate() const { 250 return is_immed_offset_; 251 } 252 GetShift()253 Shift GetShift() const { 254 return shift_; 255 } 256 GetShiftCount()257 int32_t GetShiftCount() const { 258 CHECK(!is_immed_offset_); 259 return offset_; 260 } 261 262 private: 263 Register rn_; 264 Register rm_; 265 int32_t offset_; // Used as shift amount for register offset. 266 Mode am_; 267 bool is_immed_offset_; 268 Shift shift_; 269 }; 270 271 // Instruction encoding bits. 272 enum { 273 H = 1 << 5, // halfword (or byte) 274 L = 1 << 20, // load (or store) 275 S = 1 << 20, // set condition code (or leave unchanged) 276 W = 1 << 21, // writeback base register (or leave unchanged) 277 A = 1 << 21, // accumulate in multiply instruction (or not) 278 B = 1 << 22, // unsigned byte (or word) 279 N = 1 << 22, // long (or short) 280 U = 1 << 23, // positive (or negative) offset/index 281 P = 1 << 24, // offset/pre-indexed addressing (or post-indexed addressing) 282 I = 1 << 25, // immediate shifter operand (or not) 283 284 B0 = 1, 285 B1 = 1 << 1, 286 B2 = 1 << 2, 287 B3 = 1 << 3, 288 B4 = 1 << 4, 289 B5 = 1 << 5, 290 B6 = 1 << 6, 291 B7 = 1 << 7, 292 B8 = 1 << 8, 293 B9 = 1 << 9, 294 B10 = 1 << 10, 295 B11 = 1 << 11, 296 B12 = 1 << 12, 297 B13 = 1 << 13, 298 B14 = 1 << 14, 299 B15 = 1 << 15, 300 B16 = 1 << 16, 301 B17 = 1 << 17, 302 B18 = 1 << 18, 303 B19 = 1 << 19, 304 B20 = 1 << 20, 305 B21 = 1 << 21, 306 B22 = 1 << 22, 307 B23 = 1 << 23, 308 B24 = 1 << 24, 309 B25 = 1 << 25, 310 B26 = 1 << 26, 311 B27 = 1 << 27, 312 B28 = 1 << 28, 313 B29 = 1 << 29, 314 B30 = 1 << 30, 315 B31 = 1 << 31, 316 317 // Instruction bit masks. 318 RdMask = 15 << 12, // in str instruction 319 CondMask = 15 << 28, 320 CoprocessorMask = 15 << 8, 321 OpCodeMask = 15 << 21, // in data-processing instructions 322 Imm24Mask = (1 << 24) - 1, 323 Off12Mask = (1 << 12) - 1, 324 325 // ldrex/strex register field encodings. 326 kLdExRnShift = 16, 327 kLdExRtShift = 12, 328 kStrExRnShift = 16, 329 kStrExRdShift = 12, 330 kStrExRtShift = 0, 331 }; 332 333 // IfThen state for IT instructions. 334 enum ItState { 335 kItOmitted, 336 kItThen, 337 kItT = kItThen, 338 kItElse, 339 kItE = kItElse 340 }; 341 342 constexpr uint32_t kNoItCondition = 3; 343 constexpr uint32_t kInvalidModifiedImmediate = -1; 344 345 extern const char* kRegisterNames[]; 346 extern const char* kConditionNames[]; 347 extern std::ostream& operator<<(std::ostream& os, const Register& rhs); 348 extern std::ostream& operator<<(std::ostream& os, const SRegister& rhs); 349 extern std::ostream& operator<<(std::ostream& os, const DRegister& rhs); 350 extern std::ostream& operator<<(std::ostream& os, const Condition& rhs); 351 352 // This is an abstract ARM assembler. Subclasses provide assemblers for the individual 353 // instruction sets (ARM32, Thumb2, etc.) 354 // 355 class ArmAssembler : public Assembler { 356 public: ~ArmAssembler()357 virtual ~ArmAssembler() {} 358 359 // Is this assembler for the thumb instruction set? 360 virtual bool IsThumb() const = 0; 361 362 // Data-processing instructions. 363 virtual void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 364 365 virtual void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 366 367 virtual void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 368 virtual void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 369 370 virtual void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 371 virtual void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 372 373 virtual void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 374 375 virtual void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 376 377 virtual void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 378 379 virtual void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 380 381 virtual void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 382 383 virtual void tst(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 384 385 virtual void teq(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 386 387 virtual void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 388 389 virtual void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 390 391 virtual void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 392 virtual void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 393 394 virtual void mov(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; 395 virtual void movs(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; 396 397 virtual void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) = 0; 398 399 virtual void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; 400 virtual void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) = 0; 401 402 // Miscellaneous data-processing instructions. 403 virtual void clz(Register rd, Register rm, Condition cond = AL) = 0; 404 virtual void movw(Register rd, uint16_t imm16, Condition cond = AL) = 0; 405 virtual void movt(Register rd, uint16_t imm16, Condition cond = AL) = 0; 406 407 // Multiply instructions. 408 virtual void mul(Register rd, Register rn, Register rm, Condition cond = AL) = 0; 409 virtual void mla(Register rd, Register rn, Register rm, Register ra, 410 Condition cond = AL) = 0; 411 virtual void mls(Register rd, Register rn, Register rm, Register ra, 412 Condition cond = AL) = 0; 413 virtual void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, 414 Condition cond = AL) = 0; 415 416 virtual void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0; 417 virtual void udiv(Register rd, Register rn, Register rm, Condition cond = AL) = 0; 418 419 // Load/store instructions. 420 virtual void ldr(Register rd, const Address& ad, Condition cond = AL) = 0; 421 virtual void str(Register rd, const Address& ad, Condition cond = AL) = 0; 422 423 virtual void ldrb(Register rd, const Address& ad, Condition cond = AL) = 0; 424 virtual void strb(Register rd, const Address& ad, Condition cond = AL) = 0; 425 426 virtual void ldrh(Register rd, const Address& ad, Condition cond = AL) = 0; 427 virtual void strh(Register rd, const Address& ad, Condition cond = AL) = 0; 428 429 virtual void ldrsb(Register rd, const Address& ad, Condition cond = AL) = 0; 430 virtual void ldrsh(Register rd, const Address& ad, Condition cond = AL) = 0; 431 432 virtual void ldrd(Register rd, const Address& ad, Condition cond = AL) = 0; 433 virtual void strd(Register rd, const Address& ad, Condition cond = AL) = 0; 434 435 virtual void ldm(BlockAddressMode am, Register base, 436 RegList regs, Condition cond = AL) = 0; 437 virtual void stm(BlockAddressMode am, Register base, 438 RegList regs, Condition cond = AL) = 0; 439 440 virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0; 441 virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0; 442 443 // Miscellaneous instructions. 444 virtual void clrex(Condition cond = AL) = 0; 445 virtual void nop(Condition cond = AL) = 0; 446 447 // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. 448 virtual void bkpt(uint16_t imm16) = 0; 449 virtual void svc(uint32_t imm24) = 0; 450 451 virtual void it(Condition firstcond, ItState i1 = kItOmitted, 452 ItState i2 = kItOmitted, ItState i3 = kItOmitted) { 453 // Ignored if not supported. 454 } 455 456 virtual void cbz(Register rn, Label* target) = 0; 457 virtual void cbnz(Register rn, Label* target) = 0; 458 459 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). 460 virtual void vmovsr(SRegister sn, Register rt, Condition cond = AL) = 0; 461 virtual void vmovrs(Register rt, SRegister sn, Condition cond = AL) = 0; 462 virtual void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) = 0; 463 virtual void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) = 0; 464 virtual void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) = 0; 465 virtual void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) = 0; 466 virtual void vmovs(SRegister sd, SRegister sm, Condition cond = AL) = 0; 467 virtual void vmovd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 468 469 // Returns false if the immediate cannot be encoded. 470 virtual bool vmovs(SRegister sd, float s_imm, Condition cond = AL) = 0; 471 virtual bool vmovd(DRegister dd, double d_imm, Condition cond = AL) = 0; 472 473 virtual void vldrs(SRegister sd, const Address& ad, Condition cond = AL) = 0; 474 virtual void vstrs(SRegister sd, const Address& ad, Condition cond = AL) = 0; 475 virtual void vldrd(DRegister dd, const Address& ad, Condition cond = AL) = 0; 476 virtual void vstrd(DRegister dd, const Address& ad, Condition cond = AL) = 0; 477 478 virtual void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 479 virtual void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 480 virtual void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 481 virtual void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 482 virtual void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 483 virtual void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 484 virtual void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 485 virtual void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 486 virtual void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 487 virtual void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 488 virtual void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) = 0; 489 virtual void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) = 0; 490 491 virtual void vabss(SRegister sd, SRegister sm, Condition cond = AL) = 0; 492 virtual void vabsd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 493 virtual void vnegs(SRegister sd, SRegister sm, Condition cond = AL) = 0; 494 virtual void vnegd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 495 virtual void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) = 0; 496 virtual void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 497 498 virtual void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) = 0; 499 virtual void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) = 0; 500 virtual void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) = 0; 501 virtual void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) = 0; 502 virtual void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) = 0; 503 virtual void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) = 0; 504 virtual void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) = 0; 505 virtual void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) = 0; 506 virtual void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) = 0; 507 virtual void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) = 0; 508 509 virtual void vcmps(SRegister sd, SRegister sm, Condition cond = AL) = 0; 510 virtual void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) = 0; 511 virtual void vcmpsz(SRegister sd, Condition cond = AL) = 0; 512 virtual void vcmpdz(DRegister dd, Condition cond = AL) = 0; 513 virtual void vmstat(Condition cond = AL) = 0; // VMRS APSR_nzcv, FPSCR 514 515 virtual void vpushs(SRegister reg, int nregs, Condition cond = AL) = 0; 516 virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0; 517 virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0; 518 virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0; 519 520 // Branch instructions. 521 virtual void b(Label* label, Condition cond = AL) = 0; 522 virtual void bl(Label* label, Condition cond = AL) = 0; 523 virtual void blx(Register rm, Condition cond = AL) = 0; 524 virtual void bx(Register rm, Condition cond = AL) = 0; 525 526 void Pad(uint32_t bytes); 527 528 // Macros. 529 // Most of these are pure virtual as they need to be implemented per instruction set. 530 531 // Add signed constant value to rd. May clobber IP. 532 virtual void AddConstant(Register rd, int32_t value, Condition cond = AL) = 0; 533 virtual void AddConstant(Register rd, Register rn, int32_t value, 534 Condition cond = AL) = 0; 535 virtual void AddConstantSetFlags(Register rd, Register rn, int32_t value, 536 Condition cond = AL) = 0; 537 virtual void AddConstantWithCarry(Register rd, Register rn, int32_t value, 538 Condition cond = AL) = 0; 539 540 // Load and Store. May clobber IP. 541 virtual void LoadImmediate(Register rd, int32_t value, Condition cond = AL) = 0; 542 virtual void LoadSImmediate(SRegister sd, float value, Condition cond = AL) = 0; 543 virtual void LoadDImmediate(DRegister dd, double value, 544 Register scratch, Condition cond = AL) = 0; 545 virtual void MarkExceptionHandler(Label* label) = 0; 546 virtual void LoadFromOffset(LoadOperandType type, 547 Register reg, 548 Register base, 549 int32_t offset, 550 Condition cond = AL) = 0; 551 virtual void StoreToOffset(StoreOperandType type, 552 Register reg, 553 Register base, 554 int32_t offset, 555 Condition cond = AL) = 0; 556 virtual void LoadSFromOffset(SRegister reg, 557 Register base, 558 int32_t offset, 559 Condition cond = AL) = 0; 560 virtual void StoreSToOffset(SRegister reg, 561 Register base, 562 int32_t offset, 563 Condition cond = AL) = 0; 564 virtual void LoadDFromOffset(DRegister reg, 565 Register base, 566 int32_t offset, 567 Condition cond = AL) = 0; 568 virtual void StoreDToOffset(DRegister reg, 569 Register base, 570 int32_t offset, 571 Condition cond = AL) = 0; 572 573 virtual void Push(Register rd, Condition cond = AL) = 0; 574 virtual void Pop(Register rd, Condition cond = AL) = 0; 575 576 virtual void PushList(RegList regs, Condition cond = AL) = 0; 577 virtual void PopList(RegList regs, Condition cond = AL) = 0; 578 579 virtual void Mov(Register rd, Register rm, Condition cond = AL) = 0; 580 581 // Convenience shift instructions. Use mov instruction with shifter operand 582 // for variants setting the status flags or using a register shift count. 583 virtual void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 584 Condition cond = AL) = 0; 585 virtual void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 586 Condition cond = AL) = 0; 587 virtual void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 588 Condition cond = AL) = 0; 589 virtual void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 590 Condition cond = AL) = 0; 591 virtual void Rrx(Register rd, Register rm, bool setcc = false, 592 Condition cond = AL) = 0; 593 594 virtual void Lsl(Register rd, Register rm, Register rn, bool setcc = false, 595 Condition cond = AL) = 0; 596 virtual void Lsr(Register rd, Register rm, Register rn, bool setcc = false, 597 Condition cond = AL) = 0; 598 virtual void Asr(Register rd, Register rm, Register rn, bool setcc = false, 599 Condition cond = AL) = 0; 600 virtual void Ror(Register rd, Register rm, Register rn, bool setcc = false, 601 Condition cond = AL) = 0; 602 603 static bool IsInstructionForExceptionHandling(uword pc); 604 605 virtual void Bind(Label* label) = 0; 606 607 virtual void CompareAndBranchIfZero(Register r, Label* label) = 0; 608 virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0; 609 610 // 611 // Overridden common assembler high-level functionality 612 // 613 614 // Emit code that will create an activation on the stack 615 void BuildFrame(size_t frame_size, ManagedRegister method_reg, 616 const std::vector<ManagedRegister>& callee_save_regs, 617 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE; 618 619 // Emit code that will remove an activation from the stack 620 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs) 621 OVERRIDE; 622 623 void IncreaseFrameSize(size_t adjust) OVERRIDE; 624 void DecreaseFrameSize(size_t adjust) OVERRIDE; 625 626 // Store routines 627 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE; 628 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE; 629 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE; 630 631 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE; 632 633 void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm, ManagedRegister scratch) 634 OVERRIDE; 635 636 void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, 637 ManagedRegister scratch) OVERRIDE; 638 639 void StoreStackPointerToThread32(ThreadOffset<4> thr_offs) OVERRIDE; 640 641 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off, 642 ManagedRegister scratch) OVERRIDE; 643 644 // Load routines 645 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE; 646 647 void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE; 648 649 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE; 650 651 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE; 652 653 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE; 654 655 void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs) OVERRIDE; 656 657 // Copying routines 658 void Move(ManagedRegister dest, ManagedRegister src, size_t size) OVERRIDE; 659 660 void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs, 661 ManagedRegister scratch) OVERRIDE; 662 663 void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs, ManagedRegister scratch) 664 OVERRIDE; 665 666 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE; 667 668 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE; 669 670 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch, 671 size_t size) OVERRIDE; 672 673 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch, 674 size_t size) OVERRIDE; 675 676 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch, 677 size_t size) OVERRIDE; 678 679 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset, 680 ManagedRegister scratch, size_t size) OVERRIDE; 681 682 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset, 683 ManagedRegister scratch, size_t size) OVERRIDE; 684 685 // Sign extension 686 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE; 687 688 // Zero extension 689 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE; 690 691 // Exploit fast access in managed code to Thread::Current() 692 void GetCurrentThread(ManagedRegister tr) OVERRIDE; 693 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE; 694 695 // Set up out_reg to hold a Object** into the handle scope, or to be NULL if the 696 // value is null and null_allowed. in_reg holds a possibly stale reference 697 // that can be used to avoid loading the handle scope entry to see if the value is 698 // NULL. 699 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset, ManagedRegister in_reg, 700 bool null_allowed) OVERRIDE; 701 702 // Set up out_off to hold a Object** into the handle scope, or to be NULL if the 703 // value is null and null_allowed. 704 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset, ManagedRegister scratch, 705 bool null_allowed) OVERRIDE; 706 707 // src holds a handle scope entry (Object**) load this into dst 708 void LoadReferenceFromHandleScope(ManagedRegister dst, ManagedRegister src) OVERRIDE; 709 710 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 711 // know that src may not be null. 712 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE; 713 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE; 714 715 // Call to address held at [base+offset] 716 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE; 717 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE; 718 void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch) OVERRIDE; 719 720 // Generate code to check if Thread::Current()->exception_ is non-null 721 // and branch to a ExceptionSlowPath if it is. 722 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE; 723 724 static uint32_t ModifiedImmediate(uint32_t value); 725 IsLowRegister(Register r)726 static bool IsLowRegister(Register r) { 727 return r < R8; 728 } 729 IsHighRegister(Register r)730 static bool IsHighRegister(Register r) { 731 return r >= R8; 732 } 733 734 protected: 735 // Returns whether or not the given register is used for passing parameters. RegisterCompare(const Register * reg1,const Register * reg2)736 static int RegisterCompare(const Register* reg1, const Register* reg2) { 737 return *reg1 - *reg2; 738 } 739 }; 740 741 // Slowpath entered when Thread::Current()->_exception is non-null 742 class ArmExceptionSlowPath FINAL : public SlowPath { 743 public: ArmExceptionSlowPath(ArmManagedRegister scratch,size_t stack_adjust)744 explicit ArmExceptionSlowPath(ArmManagedRegister scratch, size_t stack_adjust) 745 : scratch_(scratch), stack_adjust_(stack_adjust) { 746 } 747 void Emit(Assembler *sp_asm) OVERRIDE; 748 private: 749 const ArmManagedRegister scratch_; 750 const size_t stack_adjust_; 751 }; 752 753 } // namespace arm 754 } // namespace art 755 756 #endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_H_ 757