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