1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_ 18 #define ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_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/arm/assembler_arm.h" 26 #include "offsets.h" 27 28 namespace art { 29 namespace arm { 30 31 class Thumb2Assembler FINAL : public ArmAssembler { 32 public: 33 explicit Thumb2Assembler(bool force_32bit_branches = false) force_32bit_branches_(force_32bit_branches)34 : force_32bit_branches_(force_32bit_branches), 35 force_32bit_(false), 36 it_cond_index_(kNoItCondition), 37 next_condition_(AL) { 38 } 39 ~Thumb2Assembler()40 virtual ~Thumb2Assembler() { 41 for (auto& branch : branches_) { 42 delete branch; 43 } 44 } 45 IsThumb()46 bool IsThumb() const OVERRIDE { 47 return true; 48 } 49 IsForced32Bit()50 bool IsForced32Bit() const { 51 return force_32bit_; 52 } 53 IsForced32BitBranches()54 bool IsForced32BitBranches() const { 55 return force_32bit_branches_; 56 } 57 FinalizeInstructions(const MemoryRegion & region)58 void FinalizeInstructions(const MemoryRegion& region) OVERRIDE { 59 EmitBranches(); 60 Assembler::FinalizeInstructions(region); 61 } 62 63 // Data-processing instructions. 64 void and_(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 65 66 void eor(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 67 68 void sub(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 69 void subs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 70 71 void rsb(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 72 void rsbs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 73 74 void add(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 75 76 void adds(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 77 78 void adc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 79 80 void sbc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 81 82 void rsc(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 83 84 void tst(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 85 86 void teq(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 87 88 void cmp(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 89 90 void cmn(Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 91 92 void orr(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 93 void orrs(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 94 95 void mov(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 96 void movs(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 97 98 void bic(Register rd, Register rn, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 99 100 void mvn(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 101 void mvns(Register rd, const ShifterOperand& so, Condition cond = AL) OVERRIDE; 102 103 // Miscellaneous data-processing instructions. 104 void clz(Register rd, Register rm, Condition cond = AL) OVERRIDE; 105 void movw(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE; 106 void movt(Register rd, uint16_t imm16, Condition cond = AL) OVERRIDE; 107 108 // Multiply instructions. 109 void mul(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE; 110 void mla(Register rd, Register rn, Register rm, Register ra, 111 Condition cond = AL) OVERRIDE; 112 void mls(Register rd, Register rn, Register rm, Register ra, 113 Condition cond = AL) OVERRIDE; 114 void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, 115 Condition cond = AL) OVERRIDE; 116 117 void sdiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE; 118 void udiv(Register rd, Register rn, Register rm, Condition cond = AL) OVERRIDE; 119 120 // Bit field extract instructions. 121 void sbfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE; 122 void ubfx(Register rd, Register rn, uint32_t lsb, uint32_t width, Condition cond = AL) OVERRIDE; 123 124 // Load/store instructions. 125 void ldr(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 126 void str(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 127 128 void ldrb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 129 void strb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 130 131 void ldrh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 132 void strh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 133 134 void ldrsb(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 135 void ldrsh(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 136 137 // Load/store register dual instructions using registers `rd` and `rd` + 1. 138 void ldrd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 139 void strd(Register rd, const Address& ad, Condition cond = AL) OVERRIDE; 140 141 // Load/store register dual instructions using registers `rd` and `rd2`. 142 // Note that contrary to the ARM A1 encoding, the Thumb-2 T1 encoding 143 // does not require `rd` to be even, nor `rd2' to be equal to `rd` + 1. 144 void ldrd(Register rd, Register rd2, const Address& ad, Condition cond); 145 void strd(Register rd, Register rd2, const Address& ad, Condition cond); 146 147 148 void ldm(BlockAddressMode am, Register base, 149 RegList regs, Condition cond = AL) OVERRIDE; 150 void stm(BlockAddressMode am, Register base, 151 RegList regs, Condition cond = AL) OVERRIDE; 152 153 void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE; 154 void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE; 155 156 void ldrex(Register rd, Register rn, uint16_t imm, Condition cond = AL); 157 void strex(Register rd, Register rt, Register rn, uint16_t imm, Condition cond = AL); 158 159 void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; 160 void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; 161 162 // Miscellaneous instructions. 163 void clrex(Condition cond = AL) OVERRIDE; 164 void nop(Condition cond = AL) OVERRIDE; 165 166 void bkpt(uint16_t imm16) OVERRIDE; 167 void svc(uint32_t imm24) OVERRIDE; 168 169 // If-then 170 void it(Condition firstcond, ItState i1 = kItOmitted, 171 ItState i2 = kItOmitted, ItState i3 = kItOmitted) OVERRIDE; 172 173 void cbz(Register rn, Label* target) OVERRIDE; 174 void cbnz(Register rn, Label* target) OVERRIDE; 175 176 // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles). 177 void vmovsr(SRegister sn, Register rt, Condition cond = AL) OVERRIDE; 178 void vmovrs(Register rt, SRegister sn, Condition cond = AL) OVERRIDE; 179 void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL) OVERRIDE; 180 void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL) OVERRIDE; 181 void vmovdrr(DRegister dm, Register rt, Register rt2, Condition cond = AL) OVERRIDE; 182 void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL) OVERRIDE; 183 void vmovs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 184 void vmovd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 185 186 // Returns false if the immediate cannot be encoded. 187 bool vmovs(SRegister sd, float s_imm, Condition cond = AL) OVERRIDE; 188 bool vmovd(DRegister dd, double d_imm, Condition cond = AL) OVERRIDE; 189 190 void vldrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE; 191 void vstrs(SRegister sd, const Address& ad, Condition cond = AL) OVERRIDE; 192 void vldrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE; 193 void vstrd(DRegister dd, const Address& ad, Condition cond = AL) OVERRIDE; 194 195 void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 196 void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 197 void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 198 void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 199 void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 200 void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 201 void vmlas(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 202 void vmlad(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 203 void vmlss(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 204 void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 205 void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL) OVERRIDE; 206 void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL) OVERRIDE; 207 208 void vabss(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 209 void vabsd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 210 void vnegs(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 211 void vnegd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 212 void vsqrts(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 213 void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 214 215 void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE; 216 void vcvtds(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE; 217 void vcvtis(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 218 void vcvtid(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE; 219 void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 220 void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE; 221 void vcvtus(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 222 void vcvtud(SRegister sd, DRegister dm, Condition cond = AL) OVERRIDE; 223 void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 224 void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL) OVERRIDE; 225 226 void vcmps(SRegister sd, SRegister sm, Condition cond = AL) OVERRIDE; 227 void vcmpd(DRegister dd, DRegister dm, Condition cond = AL) OVERRIDE; 228 void vcmpsz(SRegister sd, Condition cond = AL) OVERRIDE; 229 void vcmpdz(DRegister dd, Condition cond = AL) OVERRIDE; 230 void vmstat(Condition cond = AL) OVERRIDE; // VMRS APSR_nzcv, FPSCR 231 232 void vpushs(SRegister reg, int nregs, Condition cond = AL) OVERRIDE; 233 void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; 234 void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE; 235 void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; 236 237 // Branch instructions. 238 void b(Label* label, Condition cond = AL); 239 void bl(Label* label, Condition cond = AL); 240 void blx(Label* label); 241 void blx(Register rm, Condition cond = AL) OVERRIDE; 242 void bx(Register rm, Condition cond = AL) OVERRIDE; 243 244 void Lsl(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 245 Condition cond = AL) OVERRIDE; 246 void Lsr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 247 Condition cond = AL) OVERRIDE; 248 void Asr(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 249 Condition cond = AL) OVERRIDE; 250 void Ror(Register rd, Register rm, uint32_t shift_imm, bool setcc = false, 251 Condition cond = AL) OVERRIDE; 252 void Rrx(Register rd, Register rm, bool setcc = false, 253 Condition cond = AL) OVERRIDE; 254 255 void Lsl(Register rd, Register rm, Register rn, bool setcc = false, 256 Condition cond = AL) OVERRIDE; 257 void Lsr(Register rd, Register rm, Register rn, bool setcc = false, 258 Condition cond = AL) OVERRIDE; 259 void Asr(Register rd, Register rm, Register rn, bool setcc = false, 260 Condition cond = AL) OVERRIDE; 261 void Ror(Register rd, Register rm, Register rn, bool setcc = false, 262 Condition cond = AL) OVERRIDE; 263 264 void Push(Register rd, Condition cond = AL) OVERRIDE; 265 void Pop(Register rd, Condition cond = AL) OVERRIDE; 266 267 void PushList(RegList regs, Condition cond = AL) OVERRIDE; 268 void PopList(RegList regs, Condition cond = AL) OVERRIDE; 269 270 void Mov(Register rd, Register rm, Condition cond = AL) OVERRIDE; 271 272 void CompareAndBranchIfZero(Register r, Label* label) OVERRIDE; 273 void CompareAndBranchIfNonZero(Register r, Label* label) OVERRIDE; 274 275 // Memory barriers. 276 void dmb(DmbOptions flavor) OVERRIDE; 277 278 // Macros. 279 // Add signed constant value to rd. May clobber IP. 280 void AddConstant(Register rd, int32_t value, Condition cond = AL) OVERRIDE; 281 void AddConstant(Register rd, Register rn, int32_t value, 282 Condition cond = AL) OVERRIDE; 283 void AddConstantSetFlags(Register rd, Register rn, int32_t value, 284 Condition cond = AL) OVERRIDE; 285 286 // Load and Store. May clobber IP. 287 void LoadImmediate(Register rd, int32_t value, Condition cond = AL) OVERRIDE; 288 void MarkExceptionHandler(Label* label) OVERRIDE; 289 void LoadFromOffset(LoadOperandType type, 290 Register reg, 291 Register base, 292 int32_t offset, 293 Condition cond = AL) OVERRIDE; 294 void StoreToOffset(StoreOperandType type, 295 Register reg, 296 Register base, 297 int32_t offset, 298 Condition cond = AL) OVERRIDE; 299 void LoadSFromOffset(SRegister reg, 300 Register base, 301 int32_t offset, 302 Condition cond = AL) OVERRIDE; 303 void StoreSToOffset(SRegister reg, 304 Register base, 305 int32_t offset, 306 Condition cond = AL) OVERRIDE; 307 void LoadDFromOffset(DRegister reg, 308 Register base, 309 int32_t offset, 310 Condition cond = AL) OVERRIDE; 311 void StoreDToOffset(DRegister reg, 312 Register base, 313 int32_t offset, 314 Condition cond = AL) OVERRIDE; 315 316 bool ShifterOperandCanHold(Register rd, 317 Register rn, 318 Opcode opcode, 319 uint32_t immediate, 320 ShifterOperand* shifter_op) OVERRIDE; 321 322 323 static bool IsInstructionForExceptionHandling(uintptr_t pc); 324 325 // Emit data (e.g. encoded instruction or immediate) to the. 326 // instruction stream. 327 void Emit32(int32_t value); // Emit a 32 bit instruction in thumb format. 328 void Emit16(int16_t value); // Emit a 16 bit instruction in little endian format. 329 void Bind(Label* label) OVERRIDE; 330 331 void MemoryBarrier(ManagedRegister scratch) OVERRIDE; 332 333 // Force the assembler to generate 32 bit instructions. Force32Bit()334 void Force32Bit() { 335 force_32bit_ = true; 336 } 337 338 private: 339 // Emit a single 32 or 16 bit data processing instruction. 340 void EmitDataProcessing(Condition cond, 341 Opcode opcode, 342 bool set_cc, 343 Register rn, 344 Register rd, 345 const ShifterOperand& so); 346 347 // Must the instruction be 32 bits or can it possibly be encoded 348 // in 16 bits? 349 bool Is32BitDataProcessing(Condition cond, 350 Opcode opcode, 351 bool set_cc, 352 Register rn, 353 Register rd, 354 const ShifterOperand& so); 355 356 // Emit a 32 bit data processing instruction. 357 void Emit32BitDataProcessing(Condition cond, 358 Opcode opcode, 359 bool set_cc, 360 Register rn, 361 Register rd, 362 const ShifterOperand& so); 363 364 // Emit a 16 bit data processing instruction. 365 void Emit16BitDataProcessing(Condition cond, 366 Opcode opcode, 367 bool set_cc, 368 Register rn, 369 Register rd, 370 const ShifterOperand& so); 371 372 void Emit16BitAddSub(Condition cond, 373 Opcode opcode, 374 bool set_cc, 375 Register rn, 376 Register rd, 377 const ShifterOperand& so); 378 379 uint16_t EmitCompareAndBranch(Register rn, uint16_t prev, bool n); 380 381 void EmitLoadStore(Condition cond, 382 bool load, 383 bool byte, 384 bool half, 385 bool is_signed, 386 Register rd, 387 const Address& ad); 388 389 void EmitMemOpAddressMode3(Condition cond, 390 int32_t mode, 391 Register rd, 392 const Address& ad); 393 394 void EmitMultiMemOp(Condition cond, 395 BlockAddressMode am, 396 bool load, 397 Register base, 398 RegList regs); 399 400 void EmitMulOp(Condition cond, 401 int32_t opcode, 402 Register rd, 403 Register rn, 404 Register rm, 405 Register rs); 406 407 void EmitVFPsss(Condition cond, 408 int32_t opcode, 409 SRegister sd, 410 SRegister sn, 411 SRegister sm); 412 413 void EmitVFPddd(Condition cond, 414 int32_t opcode, 415 DRegister dd, 416 DRegister dn, 417 DRegister dm); 418 419 void EmitVFPsd(Condition cond, 420 int32_t opcode, 421 SRegister sd, 422 DRegister dm); 423 424 void EmitVFPds(Condition cond, 425 int32_t opcode, 426 DRegister dd, 427 SRegister sm); 428 429 void EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond); 430 431 void EmitBranch(Condition cond, Label* label, bool link, bool x); 432 static int32_t EncodeBranchOffset(int32_t offset, int32_t inst); 433 static int DecodeBranchOffset(int32_t inst); 434 int32_t EncodeTstOffset(int offset, int32_t inst); 435 int DecodeTstOffset(int32_t inst); 436 void EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc = false); 437 void EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc = false); 438 439 bool force_32bit_branches_; // Force the assembler to use 32 bit branch instructions. 440 bool force_32bit_; // Force the assembler to use 32 bit thumb2 instructions. 441 442 // IfThen conditions. Used to check that conditional instructions match the preceding IT. 443 Condition it_conditions_[4]; 444 uint8_t it_cond_index_; 445 Condition next_condition_; 446 447 void SetItCondition(ItState s, Condition cond, uint8_t index); 448 CheckCondition(Condition cond)449 void CheckCondition(Condition cond) { 450 CHECK_EQ(cond, next_condition_); 451 452 // Move to the next condition if there is one. 453 if (it_cond_index_ < 3) { 454 ++it_cond_index_; 455 next_condition_ = it_conditions_[it_cond_index_]; 456 } else { 457 next_condition_ = AL; 458 } 459 } 460 CheckConditionLastIt(Condition cond)461 void CheckConditionLastIt(Condition cond) { 462 if (it_cond_index_ < 3) { 463 // Check that the next condition is AL. This means that the 464 // current condition is the last in the IT block. 465 CHECK_EQ(it_conditions_[it_cond_index_ + 1], AL); 466 } 467 CheckCondition(cond); 468 } 469 470 // Branches. 471 // 472 // The thumb2 architecture allows branches to be either 16 or 32 bit instructions. This 473 // depends on both the type of branch and the offset to which it is branching. When 474 // generating code for branches we don't know the size before hand (if the branch is 475 // going forward, because we haven't seen the target address yet), so we need to assume 476 // that it is going to be one of 16 or 32 bits. When we know the target (the label is 'bound') 477 // we can determine the actual size of the branch. However, if we had guessed wrong before 478 // we knew the target there will be no room in the instruction sequence for the new 479 // instruction (assume that we never decrease the size of a branch). 480 // 481 // To handle this, we keep a record of every branch in the program. The actual instruction 482 // encoding for these is delayed until we know the final size of every branch. When we 483 // bind a label to a branch (we then know the target address) we determine if the branch 484 // has changed size. If it has we need to move all the instructions in the buffer after 485 // the branch point forward by the change in size of the branch. This will create a gap 486 // in the code big enough for the new branch encoding. However, since we have moved 487 // a chunk of code we need to relocate the branches in that code to their new address. 488 // 489 // Creating a hole in the code for the new branch encoding might cause another branch that was 490 // 16 bits to become 32 bits, so we need to find this in another pass. 491 // 492 // We also need to deal with a cbz/cbnz instruction that becomes too big for its offset 493 // range. We do this by converting it to two instructions: 494 // cmp Rn, #0 495 // b<cond> target 496 // But we also need to handle the case where the conditional branch is out of range and 497 // becomes a 32 bit conditional branch. 498 // 499 // All branches have a 'branch id' which is a 16 bit unsigned number used to identify 500 // the branch. Unresolved labels use the branch id to link to the next unresolved branch. 501 502 class Branch { 503 public: 504 // Branch type. 505 enum Type { 506 kUnconditional, // B. 507 kConditional, // B<cond>. 508 kCompareAndBranchZero, // cbz. 509 kCompareAndBranchNonZero, // cbnz. 510 kUnconditionalLink, // BL. 511 kUnconditionalLinkX, // BLX. 512 kUnconditionalX // BX. 513 }; 514 515 // Calculated size of branch instruction based on type and offset. 516 enum Size { 517 k16Bit, 518 k32Bit 519 }; 520 521 // Unresolved branch possibly with a condition. 522 Branch(const Thumb2Assembler* assembler, Type type, uint32_t location, Condition cond = AL) : assembler_(assembler)523 assembler_(assembler), type_(type), location_(location), 524 target_(kUnresolved), 525 cond_(cond), rn_(R0) { 526 CHECK(!IsCompareAndBranch()); 527 size_ = CalculateSize(); 528 } 529 530 // Unresolved compare-and-branch instruction with a register. Branch(const Thumb2Assembler * assembler,Type type,uint32_t location,Register rn)531 Branch(const Thumb2Assembler* assembler, Type type, uint32_t location, Register rn) : 532 assembler_(assembler), type_(type), location_(location), 533 target_(kUnresolved), cond_(AL), rn_(rn) { 534 CHECK(IsCompareAndBranch()); 535 size_ = CalculateSize(); 536 } 537 538 // Resolved branch (can't be compare-and-branch) with a target and possibly a condition. 539 Branch(const Thumb2Assembler* assembler, Type type, uint32_t location, uint32_t target, 540 Condition cond = AL) : assembler_(assembler)541 assembler_(assembler), type_(type), location_(location), 542 target_(target), cond_(cond), rn_(R0) { 543 CHECK(!IsCompareAndBranch()); 544 // Resolved branch. 545 size_ = CalculateSize(); 546 } 547 IsCompareAndBranch()548 bool IsCompareAndBranch() const { 549 return type_ == kCompareAndBranchNonZero || type_ == kCompareAndBranchZero; 550 } 551 552 // Resolve a branch when the target is known. If this causes the 553 // size of the branch to change return true. Otherwise return false. Resolve(uint32_t target)554 bool Resolve(uint32_t target) { 555 target_ = target; 556 Size newsize = CalculateSize(); 557 if (size_ != newsize) { 558 size_ = newsize; 559 return true; 560 } 561 return false; 562 } 563 564 // Move a cbz/cbnz branch. This is always forward. Move(int32_t delta)565 void Move(int32_t delta) { 566 CHECK(IsCompareAndBranch()); 567 CHECK_GT(delta, 0); 568 location_ += delta; 569 target_ += delta; 570 } 571 572 // Relocate a branch by a given delta. This changed the location and 573 // target if they need to be changed. It also recalculates the 574 // size of the branch instruction. It returns true if the branch 575 // has changed size. Relocate(uint32_t oldlocation,int32_t delta)576 bool Relocate(uint32_t oldlocation, int32_t delta) { 577 if (location_ > oldlocation) { 578 location_ += delta; 579 } 580 if (target_ != kUnresolved) { 581 if (target_ > oldlocation) { 582 target_ += delta; 583 } 584 } else { 585 return false; // Don't know the size yet. 586 } 587 588 // Calculate the new size. 589 Size newsize = CalculateSize(); 590 if (size_ != newsize) { 591 size_ = newsize; 592 return true; 593 } 594 return false; 595 } 596 GetSize()597 Size GetSize() const { 598 return size_; 599 } 600 GetType()601 Type GetType() const { 602 return type_; 603 } 604 GetLocation()605 uint32_t GetLocation() const { 606 return location_; 607 } 608 609 // Emit the branch instruction into the assembler buffer. This does the 610 // encoding into the thumb instruction. 611 void Emit(AssemblerBuffer* buffer) const; 612 613 // Reset the type and condition to those given. This used for 614 // cbz/cbnz instructions when they are converted to cmp/b<cond> ResetTypeAndCondition(Type type,Condition cond)615 void ResetTypeAndCondition(Type type, Condition cond) { 616 CHECK(IsCompareAndBranch()); 617 CHECK(cond == EQ || cond == NE); 618 type_ = type; 619 cond_ = cond; 620 } 621 GetRegister()622 Register GetRegister() const { 623 return rn_; 624 } 625 ResetSize(Size size)626 void ResetSize(Size size) { 627 size_ = size; 628 } 629 630 private: 631 // Calculate the size of the branch instruction based on its type and offset. CalculateSize()632 Size CalculateSize() const { 633 if (assembler_->IsForced32BitBranches()) { 634 return k32Bit; 635 } 636 if (target_ == kUnresolved) { 637 if (assembler_->IsForced32Bit() && (type_ == kUnconditional || type_ == kConditional)) { 638 return k32Bit; 639 } 640 return k16Bit; 641 } 642 int32_t delta = target_ - location_ - 4; 643 if (delta < 0) { 644 delta = -delta; 645 } 646 switch (type_) { 647 case kUnconditional: 648 if (assembler_->IsForced32Bit() || delta >= (1 << 11)) { 649 return k32Bit; 650 } else { 651 return k16Bit; 652 } 653 case kConditional: 654 if (assembler_->IsForced32Bit() || delta >= (1 << 8)) { 655 return k32Bit; 656 } else { 657 return k16Bit; 658 } 659 case kCompareAndBranchZero: 660 case kCompareAndBranchNonZero: 661 if (delta >= (1 << 7)) { 662 return k32Bit; // Will cause this branch to become invalid. 663 } 664 return k16Bit; 665 666 case kUnconditionalX: 667 case kUnconditionalLinkX: 668 return k16Bit; 669 case kUnconditionalLink: 670 return k32Bit; 671 } 672 LOG(FATAL) << "Cannot reach"; 673 return k16Bit; 674 } 675 676 static constexpr uint32_t kUnresolved = 0xffffffff; // Value for target_ for unresolved. 677 const Thumb2Assembler* assembler_; 678 Type type_; 679 uint32_t location_; // Offset into assembler buffer in bytes. 680 uint32_t target_; // Offset into assembler buffer in bytes. 681 Size size_; 682 Condition cond_; 683 const Register rn_; 684 }; 685 686 std::vector<Branch*> branches_; 687 688 // Add a resolved branch and return its size. 689 Branch::Size AddBranch(Branch::Type type, uint32_t location, uint32_t target, 690 Condition cond = AL) { 691 branches_.push_back(new Branch(this, type, location, target, cond)); 692 return branches_[branches_.size()-1]->GetSize(); 693 } 694 695 // Add a compare and branch (with a register) and return its id. AddBranch(Branch::Type type,uint32_t location,Register rn)696 uint16_t AddBranch(Branch::Type type, uint32_t location, Register rn) { 697 branches_.push_back(new Branch(this, type, location, rn)); 698 return branches_.size() - 1; 699 } 700 701 // Add an unresolved branch and return its id. 702 uint16_t AddBranch(Branch::Type type, uint32_t location, Condition cond = AL) { 703 branches_.push_back(new Branch(this, type, location, cond)); 704 return branches_.size() - 1; 705 } 706 GetBranch(uint16_t branchid)707 Branch* GetBranch(uint16_t branchid) { 708 if (branchid >= branches_.size()) { 709 return nullptr; 710 } 711 return branches_[branchid]; 712 } 713 714 void EmitBranches(); 715 void MakeHoleForBranch(uint32_t location, uint32_t size); 716 }; 717 718 } // namespace arm 719 } // namespace art 720 721 #endif // ART_COMPILER_UTILS_ARM_ASSEMBLER_THUMB2_H_ 722