assembler_thumb2.cc revision 96f89a290eb67d7bf4b1636798fa28df14309cc7
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#include "assembler_thumb2.h" 18 19#include "base/logging.h" 20#include "entrypoints/quick/quick_entrypoints.h" 21#include "offsets.h" 22#include "thread.h" 23#include "utils.h" 24 25namespace art { 26namespace arm { 27 28void Thumb2Assembler::and_(Register rd, Register rn, const ShifterOperand& so, 29 Condition cond) { 30 EmitDataProcessing(cond, AND, 0, rn, rd, so); 31} 32 33 34void Thumb2Assembler::eor(Register rd, Register rn, const ShifterOperand& so, 35 Condition cond) { 36 EmitDataProcessing(cond, EOR, 0, rn, rd, so); 37} 38 39 40void Thumb2Assembler::sub(Register rd, Register rn, const ShifterOperand& so, 41 Condition cond) { 42 EmitDataProcessing(cond, SUB, 0, rn, rd, so); 43} 44 45 46void Thumb2Assembler::rsb(Register rd, Register rn, const ShifterOperand& so, 47 Condition cond) { 48 EmitDataProcessing(cond, RSB, 0, rn, rd, so); 49} 50 51 52void Thumb2Assembler::rsbs(Register rd, Register rn, const ShifterOperand& so, 53 Condition cond) { 54 EmitDataProcessing(cond, RSB, 1, rn, rd, so); 55} 56 57 58void Thumb2Assembler::add(Register rd, Register rn, const ShifterOperand& so, 59 Condition cond) { 60 EmitDataProcessing(cond, ADD, 0, rn, rd, so); 61} 62 63 64void Thumb2Assembler::adds(Register rd, Register rn, const ShifterOperand& so, 65 Condition cond) { 66 EmitDataProcessing(cond, ADD, 1, rn, rd, so); 67} 68 69 70void Thumb2Assembler::subs(Register rd, Register rn, const ShifterOperand& so, 71 Condition cond) { 72 EmitDataProcessing(cond, SUB, 1, rn, rd, so); 73} 74 75 76void Thumb2Assembler::adc(Register rd, Register rn, const ShifterOperand& so, 77 Condition cond) { 78 EmitDataProcessing(cond, ADC, 0, rn, rd, so); 79} 80 81 82void Thumb2Assembler::sbc(Register rd, Register rn, const ShifterOperand& so, 83 Condition cond) { 84 EmitDataProcessing(cond, SBC, 0, rn, rd, so); 85} 86 87 88void Thumb2Assembler::rsc(Register rd, Register rn, const ShifterOperand& so, 89 Condition cond) { 90 EmitDataProcessing(cond, RSC, 0, rn, rd, so); 91} 92 93 94void Thumb2Assembler::tst(Register rn, const ShifterOperand& so, Condition cond) { 95 CHECK_NE(rn, PC); // Reserve tst pc instruction for exception handler marker. 96 EmitDataProcessing(cond, TST, 1, rn, R0, so); 97} 98 99 100void Thumb2Assembler::teq(Register rn, const ShifterOperand& so, Condition cond) { 101 CHECK_NE(rn, PC); // Reserve teq pc instruction for exception handler marker. 102 EmitDataProcessing(cond, TEQ, 1, rn, R0, so); 103} 104 105 106void Thumb2Assembler::cmp(Register rn, const ShifterOperand& so, Condition cond) { 107 EmitDataProcessing(cond, CMP, 1, rn, R0, so); 108} 109 110 111void Thumb2Assembler::cmn(Register rn, const ShifterOperand& so, Condition cond) { 112 EmitDataProcessing(cond, CMN, 1, rn, R0, so); 113} 114 115 116void Thumb2Assembler::orr(Register rd, Register rn, 117 const ShifterOperand& so, Condition cond) { 118 EmitDataProcessing(cond, ORR, 0, rn, rd, so); 119} 120 121 122void Thumb2Assembler::orrs(Register rd, Register rn, 123 const ShifterOperand& so, Condition cond) { 124 EmitDataProcessing(cond, ORR, 1, rn, rd, so); 125} 126 127 128void Thumb2Assembler::mov(Register rd, const ShifterOperand& so, Condition cond) { 129 EmitDataProcessing(cond, MOV, 0, R0, rd, so); 130} 131 132 133void Thumb2Assembler::movs(Register rd, const ShifterOperand& so, Condition cond) { 134 EmitDataProcessing(cond, MOV, 1, R0, rd, so); 135} 136 137 138void Thumb2Assembler::bic(Register rd, Register rn, const ShifterOperand& so, 139 Condition cond) { 140 EmitDataProcessing(cond, BIC, 0, rn, rd, so); 141} 142 143 144void Thumb2Assembler::mvn(Register rd, const ShifterOperand& so, Condition cond) { 145 EmitDataProcessing(cond, MVN, 0, R0, rd, so); 146} 147 148 149void Thumb2Assembler::mvns(Register rd, const ShifterOperand& so, Condition cond) { 150 EmitDataProcessing(cond, MVN, 1, R0, rd, so); 151} 152 153 154void Thumb2Assembler::mul(Register rd, Register rn, Register rm, Condition cond) { 155 if (rd == rm && !IsHighRegister(rd) && !IsHighRegister(rn) && !force_32bit_) { 156 // 16 bit. 157 int16_t encoding = B14 | B9 | B8 | B6 | 158 rn << 3 | rd; 159 Emit16(encoding); 160 } else { 161 // 32 bit. 162 uint32_t op1 = 0b000; 163 uint32_t op2 = 0b00; 164 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | 165 op1 << 20 | 166 B15 | B14 | B13 | B12 | 167 op2 << 4 | 168 static_cast<uint32_t>(rd) << 8 | 169 static_cast<uint32_t>(rn) << 16 | 170 static_cast<uint32_t>(rm); 171 172 Emit32(encoding); 173 } 174} 175 176 177void Thumb2Assembler::mla(Register rd, Register rn, Register rm, Register ra, 178 Condition cond) { 179 uint32_t op1 = 0b000; 180 uint32_t op2 = 0b00; 181 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | 182 op1 << 20 | 183 op2 << 4 | 184 static_cast<uint32_t>(rd) << 8 | 185 static_cast<uint32_t>(ra) << 12 | 186 static_cast<uint32_t>(rn) << 16 | 187 static_cast<uint32_t>(rm); 188 189 Emit32(encoding); 190} 191 192 193void Thumb2Assembler::mls(Register rd, Register rn, Register rm, Register ra, 194 Condition cond) { 195 uint32_t op1 = 0b000; 196 uint32_t op2 = 0b01; 197 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | 198 op1 << 20 | 199 op2 << 4 | 200 static_cast<uint32_t>(rd) << 8 | 201 static_cast<uint32_t>(ra) << 12 | 202 static_cast<uint32_t>(rn) << 16 | 203 static_cast<uint32_t>(rm); 204 205 Emit32(encoding); 206} 207 208 209void Thumb2Assembler::umull(Register rd_lo, Register rd_hi, Register rn, 210 Register rm, Condition cond) { 211 uint32_t op1 = 0b010; 212 uint32_t op2 = 0b0000; 213 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | B23 | 214 op1 << 20 | 215 op2 << 4 | 216 static_cast<uint32_t>(rd_lo) << 12 | 217 static_cast<uint32_t>(rd_hi) << 8 | 218 static_cast<uint32_t>(rn) << 16 | 219 static_cast<uint32_t>(rm); 220 221 Emit32(encoding); 222} 223 224 225void Thumb2Assembler::sdiv(Register rd, Register rn, Register rm, Condition cond) { 226 uint32_t op1 = 0b001; 227 uint32_t op2 = 0b1111; 228 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | B23 | B20 | 229 op1 << 20 | 230 op2 << 4 | 231 0xf << 12 | 232 static_cast<uint32_t>(rd) << 8 | 233 static_cast<uint32_t>(rn) << 16 | 234 static_cast<uint32_t>(rm); 235 236 Emit32(encoding); 237} 238 239 240void Thumb2Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) { 241 uint32_t op1 = 0b001; 242 uint32_t op2 = 0b1111; 243 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | B24 | B23 | B21 | B20 | 244 op1 << 20 | 245 op2 << 4 | 246 0xf << 12 | 247 static_cast<uint32_t>(rd) << 8 | 248 static_cast<uint32_t>(rn) << 16 | 249 static_cast<uint32_t>(rm); 250 251 Emit32(encoding); 252} 253 254 255void Thumb2Assembler::ldr(Register rd, const Address& ad, Condition cond) { 256 EmitLoadStore(cond, true, false, false, false, rd, ad); 257} 258 259 260void Thumb2Assembler::str(Register rd, const Address& ad, Condition cond) { 261 EmitLoadStore(cond, false, false, false, false, rd, ad); 262} 263 264 265void Thumb2Assembler::ldrb(Register rd, const Address& ad, Condition cond) { 266 EmitLoadStore(cond, true, true, false, false, rd, ad); 267} 268 269 270void Thumb2Assembler::strb(Register rd, const Address& ad, Condition cond) { 271 EmitLoadStore(cond, false, true, false, false, rd, ad); 272} 273 274 275void Thumb2Assembler::ldrh(Register rd, const Address& ad, Condition cond) { 276 EmitLoadStore(cond, true, false, true, false, rd, ad); 277} 278 279 280void Thumb2Assembler::strh(Register rd, const Address& ad, Condition cond) { 281 EmitLoadStore(cond, false, false, true, false, rd, ad); 282} 283 284 285void Thumb2Assembler::ldrsb(Register rd, const Address& ad, Condition cond) { 286 EmitLoadStore(cond, true, true, false, true, rd, ad); 287} 288 289 290void Thumb2Assembler::ldrsh(Register rd, const Address& ad, Condition cond) { 291 EmitLoadStore(cond, true, false, true, true, rd, ad); 292} 293 294 295void Thumb2Assembler::ldrd(Register rd, const Address& ad, Condition cond) { 296 CHECK_EQ(rd % 2, 0); 297 // This is different from other loads. The encoding is like ARM. 298 int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 | 299 static_cast<int32_t>(rd) << 12 | 300 (static_cast<int32_t>(rd) + 1) << 8 | 301 ad.encodingThumbLdrdStrd(); 302 Emit32(encoding); 303} 304 305 306void Thumb2Assembler::strd(Register rd, const Address& ad, Condition cond) { 307 CHECK_EQ(rd % 2, 0); 308 // This is different from other loads. The encoding is like ARM. 309 int32_t encoding = B31 | B30 | B29 | B27 | B22 | 310 static_cast<int32_t>(rd) << 12 | 311 (static_cast<int32_t>(rd) + 1) << 8 | 312 ad.encodingThumbLdrdStrd(); 313 Emit32(encoding); 314} 315 316 317void Thumb2Assembler::ldm(BlockAddressMode am, 318 Register base, 319 RegList regs, 320 Condition cond) { 321 if (__builtin_popcount(regs) == 1) { 322 // Thumb doesn't support one reg in the list. 323 // Find the register number. 324 int reg = 0; 325 while (reg < 16) { 326 if ((regs & (1 << reg)) != 0) { 327 break; 328 } 329 ++reg; 330 } 331 CHECK_LT(reg, 16); 332 CHECK(am == DB_W); // Only writeback is supported. 333 ldr(static_cast<Register>(reg), Address(base, kRegisterSize, Address::PostIndex), cond); 334 } else { 335 EmitMultiMemOp(cond, am, true, base, regs); 336 } 337} 338 339 340void Thumb2Assembler::stm(BlockAddressMode am, 341 Register base, 342 RegList regs, 343 Condition cond) { 344 if (__builtin_popcount(regs) == 1) { 345 // Thumb doesn't support one reg in the list. 346 // Find the register number. 347 int reg = 0; 348 while (reg < 16) { 349 if ((regs & (1 << reg)) != 0) { 350 break; 351 } 352 ++reg; 353 } 354 CHECK_LT(reg, 16); 355 CHECK(am == IA || am == IA_W); 356 Address::Mode strmode = am == IA ? Address::PreIndex : Address::Offset; 357 str(static_cast<Register>(reg), Address(base, -kRegisterSize, strmode), cond); 358 } else { 359 EmitMultiMemOp(cond, am, false, base, regs); 360 } 361} 362 363 364bool Thumb2Assembler::vmovs(SRegister sd, float s_imm, Condition cond) { 365 uint32_t imm32 = bit_cast<uint32_t, float>(s_imm); 366 if (((imm32 & ((1 << 19) - 1)) == 0) && 367 ((((imm32 >> 25) & ((1 << 6) - 1)) == (1 << 5)) || 368 (((imm32 >> 25) & ((1 << 6) - 1)) == ((1 << 5) -1)))) { 369 uint8_t imm8 = ((imm32 >> 31) << 7) | (((imm32 >> 29) & 1) << 6) | 370 ((imm32 >> 19) & ((1 << 6) -1)); 371 EmitVFPsss(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | (imm8 & 0xf), 372 sd, S0, S0); 373 return true; 374 } 375 return false; 376} 377 378 379bool Thumb2Assembler::vmovd(DRegister dd, double d_imm, Condition cond) { 380 uint64_t imm64 = bit_cast<uint64_t, double>(d_imm); 381 if (((imm64 & ((1LL << 48) - 1)) == 0) && 382 ((((imm64 >> 54) & ((1 << 9) - 1)) == (1 << 8)) || 383 (((imm64 >> 54) & ((1 << 9) - 1)) == ((1 << 8) -1)))) { 384 uint8_t imm8 = ((imm64 >> 63) << 7) | (((imm64 >> 61) & 1) << 6) | 385 ((imm64 >> 48) & ((1 << 6) -1)); 386 EmitVFPddd(cond, B23 | B21 | B20 | ((imm8 >> 4)*B16) | B8 | (imm8 & 0xf), 387 dd, D0, D0); 388 return true; 389 } 390 return false; 391} 392 393 394void Thumb2Assembler::vmovs(SRegister sd, SRegister sm, Condition cond) { 395 EmitVFPsss(cond, B23 | B21 | B20 | B6, sd, S0, sm); 396} 397 398 399void Thumb2Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) { 400 EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm); 401} 402 403 404void Thumb2Assembler::vadds(SRegister sd, SRegister sn, SRegister sm, 405 Condition cond) { 406 EmitVFPsss(cond, B21 | B20, sd, sn, sm); 407} 408 409 410void Thumb2Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm, 411 Condition cond) { 412 EmitVFPddd(cond, B21 | B20, dd, dn, dm); 413} 414 415 416void Thumb2Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm, 417 Condition cond) { 418 EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm); 419} 420 421 422void Thumb2Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm, 423 Condition cond) { 424 EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm); 425} 426 427 428void Thumb2Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm, 429 Condition cond) { 430 EmitVFPsss(cond, B21, sd, sn, sm); 431} 432 433 434void Thumb2Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm, 435 Condition cond) { 436 EmitVFPddd(cond, B21, dd, dn, dm); 437} 438 439 440void Thumb2Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm, 441 Condition cond) { 442 EmitVFPsss(cond, 0, sd, sn, sm); 443} 444 445 446void Thumb2Assembler::vmlad(DRegister dd, DRegister dn, DRegister dm, 447 Condition cond) { 448 EmitVFPddd(cond, 0, dd, dn, dm); 449} 450 451 452void Thumb2Assembler::vmlss(SRegister sd, SRegister sn, SRegister sm, 453 Condition cond) { 454 EmitVFPsss(cond, B6, sd, sn, sm); 455} 456 457 458void Thumb2Assembler::vmlsd(DRegister dd, DRegister dn, DRegister dm, 459 Condition cond) { 460 EmitVFPddd(cond, B6, dd, dn, dm); 461} 462 463 464void Thumb2Assembler::vdivs(SRegister sd, SRegister sn, SRegister sm, 465 Condition cond) { 466 EmitVFPsss(cond, B23, sd, sn, sm); 467} 468 469 470void Thumb2Assembler::vdivd(DRegister dd, DRegister dn, DRegister dm, 471 Condition cond) { 472 EmitVFPddd(cond, B23, dd, dn, dm); 473} 474 475 476void Thumb2Assembler::vabss(SRegister sd, SRegister sm, Condition cond) { 477 EmitVFPsss(cond, B23 | B21 | B20 | B7 | B6, sd, S0, sm); 478} 479 480 481void Thumb2Assembler::vabsd(DRegister dd, DRegister dm, Condition cond) { 482 EmitVFPddd(cond, B23 | B21 | B20 | B7 | B6, dd, D0, dm); 483} 484 485 486void Thumb2Assembler::vnegs(SRegister sd, SRegister sm, Condition cond) { 487 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B6, sd, S0, sm); 488} 489 490 491void Thumb2Assembler::vnegd(DRegister dd, DRegister dm, Condition cond) { 492 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B6, dd, D0, dm); 493} 494 495 496void Thumb2Assembler::vsqrts(SRegister sd, SRegister sm, Condition cond) { 497 EmitVFPsss(cond, B23 | B21 | B20 | B16 | B7 | B6, sd, S0, sm); 498} 499 500void Thumb2Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) { 501 EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm); 502} 503 504 505void Thumb2Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) { 506 EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm); 507} 508 509 510void Thumb2Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) { 511 EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm); 512} 513 514 515void Thumb2Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) { 516 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6, sd, S0, sm); 517} 518 519 520void Thumb2Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) { 521 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm); 522} 523 524 525void Thumb2Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) { 526 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm); 527} 528 529 530void Thumb2Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) { 531 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm); 532} 533 534 535void Thumb2Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) { 536 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm); 537} 538 539 540void Thumb2Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) { 541 EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm); 542} 543 544 545void Thumb2Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) { 546 EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm); 547} 548 549 550void Thumb2Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) { 551 EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm); 552} 553 554 555void Thumb2Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) { 556 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm); 557} 558 559 560void Thumb2Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) { 561 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm); 562} 563 564 565void Thumb2Assembler::vcmpsz(SRegister sd, Condition cond) { 566 EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0); 567} 568 569 570void Thumb2Assembler::vcmpdz(DRegister dd, Condition cond) { 571 EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0); 572} 573 574void Thumb2Assembler::b(Label* label, Condition cond) { 575 EmitBranch(cond, label, false, false); 576} 577 578 579void Thumb2Assembler::bl(Label* label, Condition cond) { 580 CheckCondition(cond); 581 EmitBranch(cond, label, true, false); 582} 583 584 585void Thumb2Assembler::blx(Label* label) { 586 EmitBranch(AL, label, true, true); 587} 588 589 590void Thumb2Assembler::MarkExceptionHandler(Label* label) { 591 EmitDataProcessing(AL, TST, 1, PC, R0, ShifterOperand(0)); 592 Label l; 593 b(&l); 594 EmitBranch(AL, label, false, false); 595 Bind(&l); 596} 597 598 599void Thumb2Assembler::Emit32(int32_t value) { 600 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 601 buffer_.Emit<int16_t>(value >> 16); 602 buffer_.Emit<int16_t>(value & 0xffff); 603} 604 605 606void Thumb2Assembler::Emit16(int16_t value) { 607 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 608 buffer_.Emit<int16_t>(value); 609} 610 611 612bool Thumb2Assembler::Is32BitDataProcessing(Condition cond, 613 Opcode opcode, 614 int set_cc, 615 Register rn, 616 Register rd, 617 const ShifterOperand& so) { 618 if (force_32bit_) { 619 return true; 620 } 621 622 bool can_contain_high_register = (opcode == MOV) 623 || ((opcode == ADD || opcode == SUB) && (rn == rd)); 624 625 if (IsHighRegister(rd) || IsHighRegister(rn)) { 626 if (can_contain_high_register) { 627 // There are high register instructions available for this opcode. 628 // However, there is no RRX available. 629 if (so.IsShift() && so.GetShift() == RRX) { 630 return true; 631 } 632 633 // Check special case for SP relative ADD and SUB immediate. 634 if ((opcode == ADD || opcode == SUB) && so.IsImmediate()) { 635 // If rn is SP and rd is a high register we need to use a 32 bit encoding. 636 if (rn == SP && rd != SP && IsHighRegister(rd)) { 637 return true; 638 } 639 640 uint32_t imm = so.GetImmediate(); 641 // If the immediates are out of range use 32 bit. 642 if (rd == SP && rn == SP) { 643 if (imm > (1 << 9)) { // 9 bit immediate. 644 return true; 645 } 646 } else if (opcode == ADD && rd != SP && rn == SP) { // 10 bit immediate. 647 if (imm > (1 << 10)) { 648 return true; 649 } 650 } else if (opcode == SUB && rd != SP && rn == SP) { 651 // SUB rd, SP, #imm is always 32 bit. 652 return true; 653 } 654 } 655 } 656 657 // The ADD,SUB and MOV instructions that work with high registers don't have 658 // immediate variants. 659 if (so.IsImmediate()) { 660 return true; 661 } 662 } 663 664 if (so.IsRegister() && IsHighRegister(so.GetRegister()) && !can_contain_high_register) { 665 return true; 666 } 667 668 // Check for MOV with an ROR. 669 if (opcode == MOV && so.IsRegister() && so.IsShift() && so.GetShift() == ROR) { 670 if (so.GetImmediate() != 0) { 671 return true; 672 } 673 } 674 675 bool rn_is_valid = true; 676 677 // Check for single operand instructions and ADD/SUB. 678 switch (opcode) { 679 case CMP: 680 case MOV: 681 case TST: 682 case MVN: 683 rn_is_valid = false; // There is no Rn for these instructions. 684 break; 685 case TEQ: 686 return true; 687 break; 688 case ADD: 689 case SUB: 690 break; 691 default: 692 if (so.IsRegister() && rd != rn) { 693 return true; 694 } 695 } 696 697 if (so.IsImmediate()) { 698 if (rn_is_valid && rn != rd) { 699 // The only thumb1 instruction with a register and an immediate are ADD and SUB. The 700 // immediate must be 3 bits. 701 if (opcode != ADD && opcode != SUB) { 702 return true; 703 } else { 704 // Check that the immediate is 3 bits for ADD and SUB. 705 if (so.GetImmediate() >= 8) { 706 return true; 707 } 708 } 709 } else { 710 // ADD, SUB, CMP and MOV may be thumb1 only if the immediate is 8 bits. 711 if (!(opcode == ADD || opcode == SUB || opcode == MOV || opcode == CMP)) { 712 return true; 713 } else { 714 if (so.GetImmediate() > 255) { 715 return true; 716 } 717 } 718 } 719 } 720 721 // The instruction can be encoded in 16 bits. 722 return false; 723} 724 725 726void Thumb2Assembler::Emit32BitDataProcessing(Condition cond, 727 Opcode opcode, 728 int set_cc, 729 Register rn, 730 Register rd, 731 const ShifterOperand& so) { 732 uint8_t thumb_opcode = 0b11111111; 733 switch (opcode) { 734 case AND: thumb_opcode = 0b0000; break; 735 case EOR: thumb_opcode = 0b0100; break; 736 case SUB: thumb_opcode = 0b1101; break; 737 case RSB: thumb_opcode = 0b1110; break; 738 case ADD: thumb_opcode = 0b1000; break; 739 case ADC: thumb_opcode = 0b1010; break; 740 case SBC: thumb_opcode = 0b1011; break; 741 case RSC: break; 742 case TST: thumb_opcode = 0b0000; set_cc = true; rd = PC; break; 743 case TEQ: thumb_opcode = 0b0100; set_cc = true; rd = PC; break; 744 case CMP: thumb_opcode = 0b1101; set_cc = true; rd = PC; break; 745 case CMN: thumb_opcode = 0b1000; set_cc = true; rd = PC; break; 746 case ORR: thumb_opcode = 0b0010; break; 747 case MOV: thumb_opcode = 0b0010; rn = PC; break; 748 case BIC: thumb_opcode = 0b0001; break; 749 case MVN: thumb_opcode = 0b0011; rn = PC; break; 750 default: 751 break; 752 } 753 754 if (thumb_opcode == 0b11111111) { 755 LOG(FATAL) << "Invalid thumb2 opcode " << opcode; 756 } 757 758 int32_t encoding = 0; 759 if (so.IsImmediate()) { 760 // Check special cases. 761 if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) { 762 if (opcode == SUB) { 763 thumb_opcode = 0b0101; 764 } else { 765 thumb_opcode = 0; 766 } 767 uint32_t imm = so.GetImmediate(); 768 769 uint32_t i = (imm >> 11) & 1; 770 uint32_t imm3 = (imm >> 8) & 0b111; 771 uint32_t imm8 = imm & 0xff; 772 773 encoding = B31 | B30 | B29 | B28 | B25 | 774 thumb_opcode << 21 | 775 rn << 16 | 776 rd << 8 | 777 i << 26 | 778 imm3 << 12 | 779 imm8; 780 } else { 781 // Modified immediate. 782 uint32_t imm = ModifiedImmediate(so.encodingThumb()); 783 if (imm == kInvalidModifiedImmediate) { 784 LOG(FATAL) << "Immediate value cannot fit in thumb2 modified immediate"; 785 } 786 encoding = B31 | B30 | B29 | B28 | 787 thumb_opcode << 21 | 788 set_cc << 20 | 789 rn << 16 | 790 rd << 8 | 791 imm; 792 } 793 } else if (so.IsRegister()) { 794 // Register (possibly shifted) 795 encoding = B31 | B30 | B29 | B27 | B25 | 796 thumb_opcode << 21 | 797 set_cc << 20 | 798 rn << 16 | 799 rd << 8 | 800 so.encodingThumb(); 801 } 802 Emit32(encoding); 803} 804 805 806void Thumb2Assembler::Emit16BitDataProcessing(Condition cond, 807 Opcode opcode, 808 int set_cc, 809 Register rn, 810 Register rd, 811 const ShifterOperand& so) { 812 if (opcode == ADD || opcode == SUB) { 813 Emit16BitAddSub(cond, opcode, set_cc, rn, rd, so); 814 return; 815 } 816 uint8_t thumb_opcode = 0b11111111; 817 // Thumb1. 818 uint8_t dp_opcode = 0b01; 819 uint8_t opcode_shift = 6; 820 uint8_t rd_shift = 0; 821 uint8_t rn_shift = 3; 822 uint8_t immediate_shift = 0; 823 bool use_immediate = false; 824 uint8_t immediate = 0; 825 826 if (opcode == MOV && so.IsRegister() && so.IsShift()) { 827 // Convert shifted mov operand2 into 16 bit opcodes. 828 dp_opcode = 0; 829 opcode_shift = 11; 830 831 use_immediate = true; 832 immediate = so.GetImmediate(); 833 immediate_shift = 6; 834 835 rn = so.GetRegister(); 836 837 switch (so.GetShift()) { 838 case LSL: thumb_opcode = 0b00; break; 839 case LSR: thumb_opcode = 0b01; break; 840 case ASR: thumb_opcode = 0b10; break; 841 case ROR: 842 // ROR doesn't allow immediates. 843 thumb_opcode = 0b111; 844 dp_opcode = 0b01; 845 opcode_shift = 6; 846 use_immediate = false; 847 break; 848 case RRX: break; 849 default: 850 break; 851 } 852 } else { 853 if (so.IsImmediate()) { 854 use_immediate = true; 855 immediate = so.GetImmediate(); 856 } 857 858 switch (opcode) { 859 case AND: thumb_opcode = 0b0000; break; 860 case EOR: thumb_opcode = 0b0001; break; 861 case SUB: break; 862 case RSB: thumb_opcode = 0b1001; break; 863 case ADD: break; 864 case ADC: thumb_opcode = 0b0101; break; 865 case SBC: thumb_opcode = 0b0110; break; 866 case RSC: break; 867 case TST: thumb_opcode = 0b1000; rn = so.GetRegister(); break; 868 case TEQ: break; 869 case CMP: 870 if (use_immediate) { 871 // T2 encoding. 872 dp_opcode = 0; 873 opcode_shift = 11; 874 thumb_opcode = 0b101; 875 rd_shift = 8; 876 rn_shift = 8; 877 } else { 878 thumb_opcode = 0b1010; 879 rd = rn; 880 rn = so.GetRegister(); 881 } 882 883 break; 884 case CMN: { 885 thumb_opcode = 0b1011; 886 rd = rn; 887 rn = so.GetRegister(); 888 break; 889 } 890 case ORR: thumb_opcode = 0b1100; break; 891 case MOV: 892 dp_opcode = 0; 893 if (use_immediate) { 894 // T2 encoding. 895 opcode_shift = 11; 896 thumb_opcode = 0b100; 897 rd_shift = 8; 898 rn_shift = 8; 899 } else { 900 rn = so.GetRegister(); 901 if (IsHighRegister(rn) || IsHighRegister(rd)) { 902 // Special mov for high registers. 903 dp_opcode = 0b01; 904 opcode_shift = 7; 905 // Put the top bit of rd into the bottom bit of the opcode. 906 thumb_opcode = 0b0001100 | static_cast<uint32_t>(rd) >> 3; 907 rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111); 908 } else { 909 thumb_opcode = 0; 910 } 911 } 912 break; 913 case BIC: thumb_opcode = 0b1110; break; 914 case MVN: thumb_opcode = 0b1111; rn = so.GetRegister(); break; 915 default: 916 break; 917 } 918 } 919 920 if (thumb_opcode == 0b11111111) { 921 LOG(FATAL) << "Invalid thumb1 opcode " << opcode; 922 } 923 924 int16_t encoding = dp_opcode << 14 | 925 (thumb_opcode << opcode_shift) | 926 rd << rd_shift | 927 rn << rn_shift | 928 (use_immediate ? (immediate << immediate_shift) : 0); 929 930 Emit16(encoding); 931} 932 933 934// ADD and SUB are complex enough to warrant their own emitter. 935void Thumb2Assembler::Emit16BitAddSub(Condition cond, 936 Opcode opcode, 937 int set_cc, 938 Register rn, 939 Register rd, 940 const ShifterOperand& so) { 941 uint8_t dp_opcode = 0; 942 uint8_t opcode_shift = 6; 943 uint8_t rd_shift = 0; 944 uint8_t rn_shift = 3; 945 uint8_t immediate_shift = 0; 946 bool use_immediate = false; 947 uint8_t immediate = 0; 948 uint8_t thumb_opcode;; 949 950 if (so.IsImmediate()) { 951 use_immediate = true; 952 immediate = so.GetImmediate(); 953 } 954 955 switch (opcode) { 956 case ADD: 957 if (so.IsRegister()) { 958 Register rm = so.GetRegister(); 959 if (rn == rd) { 960 // Can use T2 encoding (allows 4 bit registers) 961 dp_opcode = 0b01; 962 opcode_shift = 10; 963 thumb_opcode = 0b0001; 964 // Make Rn also contain the top bit of rd. 965 rn = static_cast<Register>(static_cast<uint32_t>(rm) | 966 (static_cast<uint32_t>(rd) & 0b1000) << 1); 967 rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111); 968 } else { 969 // T1. 970 opcode_shift = 9; 971 thumb_opcode = 0b01100; 972 immediate = static_cast<uint32_t>(so.GetRegister()); 973 use_immediate = true; 974 immediate_shift = 6; 975 } 976 } else { 977 // Immediate. 978 if (rd == SP && rn == SP) { 979 // ADD sp, sp, #imm 980 dp_opcode = 0b10; 981 thumb_opcode = 0b11; 982 opcode_shift = 12; 983 CHECK_LT(immediate, (1 << 9)); 984 CHECK_EQ((immediate & 0b11), 0); 985 986 // Remove rd and rn from instruction by orring it with immed and clearing bits. 987 rn = R0; 988 rd = R0; 989 rd_shift = 0; 990 rn_shift = 0; 991 immediate >>= 2; 992 } else if (rd != SP && rn == SP) { 993 // ADD rd, SP, #imm 994 dp_opcode = 0b10; 995 thumb_opcode = 0b101; 996 opcode_shift = 11; 997 CHECK_LT(immediate, (1 << 10)); 998 CHECK_EQ((immediate & 0b11), 0); 999 1000 // Remove rn from instruction. 1001 rn = R0; 1002 rn_shift = 0; 1003 rd_shift = 8; 1004 immediate >>= 2; 1005 } else if (rn != rd) { 1006 // Must use T1. 1007 opcode_shift = 9; 1008 thumb_opcode = 0b01110; 1009 immediate_shift = 6; 1010 } else { 1011 // T2 encoding. 1012 opcode_shift = 11; 1013 thumb_opcode = 0b110; 1014 rd_shift = 8; 1015 rn_shift = 8; 1016 } 1017 } 1018 break; 1019 1020 case SUB: 1021 if (so.IsRegister()) { 1022 // T1. 1023 opcode_shift = 9; 1024 thumb_opcode = 0b01101; 1025 immediate = static_cast<uint32_t>(so.GetRegister()); 1026 use_immediate = true; 1027 immediate_shift = 6; 1028 } else { 1029 if (rd == SP && rn == SP) { 1030 // SUB sp, sp, #imm 1031 dp_opcode = 0b10; 1032 thumb_opcode = 0b1100001; 1033 opcode_shift = 7; 1034 CHECK_LT(immediate, (1 << 9)); 1035 CHECK_EQ((immediate & 0b11), 0); 1036 1037 // Remove rd and rn from instruction by orring it with immed and clearing bits. 1038 rn = R0; 1039 rd = R0; 1040 rd_shift = 0; 1041 rn_shift = 0; 1042 immediate >>= 2; 1043 } else if (rn != rd) { 1044 // Must use T1. 1045 opcode_shift = 9; 1046 thumb_opcode = 0b01111; 1047 immediate_shift = 6; 1048 } else { 1049 // T2 encoding. 1050 opcode_shift = 11; 1051 thumb_opcode = 0b111; 1052 rd_shift = 8; 1053 rn_shift = 8; 1054 } 1055 } 1056 break; 1057 default: 1058 LOG(FATAL) << "This opcode is not an ADD or SUB: " << opcode; 1059 return; 1060 } 1061 1062 int16_t encoding = dp_opcode << 14 | 1063 (thumb_opcode << opcode_shift) | 1064 rd << rd_shift | 1065 rn << rn_shift | 1066 (use_immediate ? (immediate << immediate_shift) : 0); 1067 1068 Emit16(encoding); 1069} 1070 1071 1072void Thumb2Assembler::EmitDataProcessing(Condition cond, 1073 Opcode opcode, 1074 int set_cc, 1075 Register rn, 1076 Register rd, 1077 const ShifterOperand& so) { 1078 CHECK_NE(rd, kNoRegister); 1079 CheckCondition(cond); 1080 1081 if (Is32BitDataProcessing(cond, opcode, set_cc, rn, rd, so)) { 1082 Emit32BitDataProcessing(cond, opcode, set_cc, rn, rd, so); 1083 } else { 1084 Emit16BitDataProcessing(cond, opcode, set_cc, rn, rd, so); 1085 } 1086} 1087 1088void Thumb2Assembler::EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc) { 1089 CHECK_LT(amount, (1 << 5)); 1090 if (IsHighRegister(rd) || IsHighRegister(rm) || shift == ROR || shift == RRX) { 1091 uint16_t opcode = 0; 1092 switch (shift) { 1093 case LSL: opcode = 0b00; break; 1094 case LSR: opcode = 0b01; break; 1095 case ASR: opcode = 0b10; break; 1096 case ROR: opcode = 0b11; break; 1097 case RRX: opcode = 0b11; amount = 0; break; 1098 default: 1099 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1100 } 1101 // 32 bit. 1102 int32_t encoding = B31 | B30 | B29 | B27 | B25 | B22 | 1103 0xf << 16 | (setcc ? B20 : 0); 1104 uint32_t imm3 = amount >> 2; 1105 uint32_t imm2 = amount & 0b11; 1106 encoding |= imm3 << 12 | imm2 << 6 | static_cast<int16_t>(rm) | 1107 static_cast<int16_t>(rd) << 8 | opcode << 4; 1108 Emit32(encoding); 1109 } else { 1110 // 16 bit shift 1111 uint16_t opcode = 0; 1112 switch (shift) { 1113 case LSL: opcode = 0b00; break; 1114 case LSR: opcode = 0b01; break; 1115 case ASR: opcode = 0b10; break; 1116 default: 1117 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1118 } 1119 int16_t encoding = opcode << 11 | amount << 6 | static_cast<int16_t>(rm) << 3 | 1120 static_cast<int16_t>(rd); 1121 Emit16(encoding); 1122 } 1123} 1124 1125void Thumb2Assembler::EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc) { 1126 CHECK_NE(shift, RRX); 1127 bool must_be_32bit = false; 1128 if (IsHighRegister(rd) || IsHighRegister(rm) || IsHighRegister(rn) || rd != rn) { 1129 must_be_32bit = true; 1130 } 1131 1132 if (must_be_32bit) { 1133 uint16_t opcode = 0; 1134 switch (shift) { 1135 case LSL: opcode = 0b00; break; 1136 case LSR: opcode = 0b01; break; 1137 case ASR: opcode = 0b10; break; 1138 case ROR: opcode = 0b11; break; 1139 default: 1140 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1141 } 1142 // 32 bit. 1143 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | 1144 0xf << 12 | (setcc ? B20 : 0); 1145 encoding |= static_cast<int16_t>(rn) << 16 | static_cast<int16_t>(rm) | 1146 static_cast<int16_t>(rd) << 8 | opcode << 21; 1147 Emit32(encoding); 1148 } else { 1149 uint16_t opcode = 0; 1150 switch (shift) { 1151 case LSL: opcode = 0b0010; break; 1152 case LSR: opcode = 0b0011; break; 1153 case ASR: opcode = 0b0100; break; 1154 default: 1155 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1156 } 1157 int16_t encoding = B14 | opcode << 6 | static_cast<int16_t>(rm) << 3 | 1158 static_cast<int16_t>(rd); 1159 Emit16(encoding); 1160 } 1161} 1162 1163 1164 1165void Thumb2Assembler::Branch::Emit(AssemblerBuffer* buffer) const { 1166 bool link = type_ == kUnconditionalLinkX || type_ == kUnconditionalLink; 1167 bool x = type_ == kUnconditionalX || type_ == kUnconditionalLinkX; 1168 int32_t offset = target_ - location_; 1169 1170 if (size_ == k32Bit) { 1171 int32_t encoding = B31 | B30 | B29 | B28 | B15; 1172 if (link) { 1173 // BL or BLX immediate. 1174 encoding |= B14; 1175 if (!x) { 1176 encoding |= B12; 1177 } else { 1178 // Bottom bit of offset must be 0. 1179 CHECK_EQ((offset & 1), 0); 1180 } 1181 } else { 1182 if (x) { 1183 LOG(FATAL) << "Invalid use of BX"; 1184 } else { 1185 if (cond_ == AL) { 1186 // Can use the T4 encoding allowing a 24 bit offset. 1187 if (!x) { 1188 encoding |= B12; 1189 } 1190 } else { 1191 // Must be T3 encoding with a 20 bit offset. 1192 encoding |= cond_ << 22; 1193 } 1194 } 1195 } 1196 encoding = Thumb2Assembler::EncodeBranchOffset(offset, encoding); 1197 buffer->Store<int16_t>(location_, static_cast<int16_t>(encoding >> 16)); 1198 buffer->Store<int16_t>(location_+2, static_cast<int16_t>(encoding & 0xffff)); 1199 } else { 1200 if (IsCompareAndBranch()) { 1201 offset -= 4; 1202 uint16_t i = (offset >> 6) & 1; 1203 uint16_t imm5 = (offset >> 1) & 0b11111; 1204 int16_t encoding = B15 | B13 | B12 | 1205 (type_ == kCompareAndBranchNonZero ? B11 : 0) | 1206 static_cast<uint32_t>(rn_) | 1207 B8 | 1208 i << 9 | 1209 imm5 << 3; 1210 buffer->Store<int16_t>(location_, encoding); 1211 } else { 1212 offset -= 4; // Account for PC offset. 1213 int16_t encoding; 1214 // 16 bit. 1215 if (cond_ == AL) { 1216 encoding = B15 | B14 | B13 | 1217 ((offset >> 1) & 0x7ff); 1218 } else { 1219 encoding = B15 | B14 | B12 | 1220 cond_ << 8 | ((offset >> 1) & 0xff); 1221 } 1222 buffer->Store<int16_t>(location_, encoding); 1223 } 1224 } 1225} 1226 1227 1228uint16_t Thumb2Assembler::EmitCompareAndBranch(Register rn, uint16_t prev, bool n) { 1229 uint32_t location = buffer_.Size(); 1230 1231 // This is always unresolved as it must be a forward branch. 1232 Emit16(prev); // Previous link. 1233 return AddBranch(n ? Branch::kCompareAndBranchNonZero : Branch::kCompareAndBranchZero, 1234 location, rn); 1235} 1236 1237 1238// NOTE: this only support immediate offsets, not [rx,ry]. 1239// TODO: support [rx,ry] instructions. 1240void Thumb2Assembler::EmitLoadStore(Condition cond, 1241 bool load, 1242 bool byte, 1243 bool half, 1244 bool is_signed, 1245 Register rd, 1246 const Address& ad) { 1247 CHECK_NE(rd, kNoRegister); 1248 CheckCondition(cond); 1249 bool must_be_32bit = force_32bit_; 1250 if (IsHighRegister(rd)) { 1251 must_be_32bit = true; 1252 } 1253 1254 Register rn = ad.GetRegister(); 1255 if (IsHighRegister(rn) && rn != SP && rn != PC) { 1256 must_be_32bit = true; 1257 } 1258 1259 if (is_signed || ad.GetOffset() < 0 || ad.GetMode() != Address::Offset) { 1260 must_be_32bit = true; 1261 } 1262 1263 if (ad.IsImmediate()) { 1264 // Immediate offset 1265 int32_t offset = ad.GetOffset(); 1266 1267 // The 16 bit SP relative instruction can only have a 10 bit offset. 1268 if (rn == SP && offset >= (1 << 10)) { 1269 must_be_32bit = true; 1270 } 1271 1272 if (byte) { 1273 // 5 bit offset, no shift. 1274 if (offset >= (1 << 5)) { 1275 must_be_32bit = true; 1276 } 1277 } else if (half) { 1278 // 6 bit offset, shifted by 1. 1279 if (offset >= (1 << 6)) { 1280 must_be_32bit = true; 1281 } 1282 } else { 1283 // 7 bit offset, shifted by 2. 1284 if (offset >= (1 << 7)) { 1285 must_be_32bit = true; 1286 } 1287 } 1288 1289 if (must_be_32bit) { 1290 int32_t encoding = B31 | B30 | B29 | B28 | B27 | 1291 (load ? B20 : 0) | 1292 (is_signed ? B24 : 0) | 1293 static_cast<uint32_t>(rd) << 12 | 1294 ad.encodingThumb(true) | 1295 (byte ? 0 : half ? B21 : B22); 1296 Emit32(encoding); 1297 } else { 1298 // 16 bit thumb1. 1299 uint8_t opA = 0; 1300 bool sp_relative = false; 1301 1302 if (byte) { 1303 opA = 0b0111; 1304 } else if (half) { 1305 opA = 0b1000; 1306 } else { 1307 if (rn == SP) { 1308 opA = 0b1001; 1309 sp_relative = true; 1310 } else { 1311 opA = 0b0110; 1312 } 1313 } 1314 int16_t encoding = opA << 12 | 1315 (load ? B11 : 0); 1316 1317 CHECK_GE(offset, 0); 1318 if (sp_relative) { 1319 // SP relative, 10 bit offset. 1320 CHECK_LT(offset, (1 << 10)); 1321 CHECK_EQ((offset & 0b11), 0); 1322 encoding |= rd << 8 | offset >> 2; 1323 } else { 1324 // No SP relative. The offset is shifted right depending on 1325 // the size of the load/store. 1326 encoding |= static_cast<uint32_t>(rd); 1327 1328 if (byte) { 1329 // 5 bit offset, no shift. 1330 CHECK_LT(offset, (1 << 5)); 1331 } else if (half) { 1332 // 6 bit offset, shifted by 1. 1333 CHECK_LT(offset, (1 << 6)); 1334 CHECK_EQ((offset & 0b1), 0); 1335 offset >>= 1; 1336 } else { 1337 // 7 bit offset, shifted by 2. 1338 CHECK_LT(offset, (1 << 7)); 1339 CHECK_EQ((offset & 0b11), 0); 1340 offset >>= 2; 1341 } 1342 encoding |= rn << 3 | offset << 6; 1343 } 1344 1345 Emit16(encoding); 1346 } 1347 } else { 1348 // Register shift. 1349 if (ad.GetRegister() == PC) { 1350 // PC relative literal encoding. 1351 int32_t offset = ad.GetOffset(); 1352 if (must_be_32bit || offset < 0 || offset >= (1 << 10) || !load) { 1353 int32_t up = B23; 1354 if (offset < 0) { 1355 offset = -offset; 1356 up = 0; 1357 } 1358 CHECK_LT(offset, (1 << 12)); 1359 int32_t encoding = 0x1f << 27 | 0xf << 16 | B22 | (load ? B20 : 0) | 1360 offset | up | 1361 static_cast<uint32_t>(rd) << 12; 1362 Emit32(encoding); 1363 } else { 1364 // 16 bit literal load. 1365 CHECK_GE(offset, 0); 1366 CHECK_LT(offset, (1 << 10)); 1367 int32_t encoding = B14 | (load ? B11 : 0) | static_cast<uint32_t>(rd) << 8 | offset >> 2; 1368 Emit16(encoding); 1369 } 1370 } else { 1371 if (ad.GetShiftCount() != 0) { 1372 // If there is a shift count this must be 32 bit. 1373 must_be_32bit = true; 1374 } else if (IsHighRegister(ad.GetRegisterOffset())) { 1375 must_be_32bit = true; 1376 } 1377 1378 if (must_be_32bit) { 1379 int32_t encoding = 0x1f << 27 | B22 | (load ? B20 : 0) | static_cast<uint32_t>(rd) << 12 | 1380 ad.encodingThumb(true); 1381 Emit32(encoding); 1382 } else { 1383 // 16 bit register offset. 1384 int32_t encoding = B14 | B12 | (load ? B11 : 0) | static_cast<uint32_t>(rd) | 1385 ad.encodingThumb(false); 1386 Emit16(encoding); 1387 } 1388 } 1389 } 1390} 1391 1392 1393void Thumb2Assembler::EmitMultiMemOp(Condition cond, 1394 BlockAddressMode am, 1395 bool load, 1396 Register base, 1397 RegList regs) { 1398 CHECK_NE(base, kNoRegister); 1399 CheckCondition(cond); 1400 bool must_be_32bit = force_32bit_; 1401 1402 if ((regs & 0xff00) != 0) { 1403 must_be_32bit = true; 1404 } 1405 1406 uint32_t w_bit = am == IA_W || am == DB_W || am == DA_W || am == IB_W; 1407 // 16 bit always uses writeback. 1408 if (!w_bit) { 1409 must_be_32bit = true; 1410 } 1411 1412 if (must_be_32bit) { 1413 uint32_t op = 0; 1414 switch (am) { 1415 case IA: 1416 case IA_W: 1417 op = 0b01; 1418 break; 1419 case DB: 1420 case DB_W: 1421 op = 0b10; 1422 break; 1423 case DA: 1424 case IB: 1425 case DA_W: 1426 case IB_W: 1427 LOG(FATAL) << "LDM/STM mode not supported on thumb: " << am; 1428 } 1429 if (load) { 1430 // Cannot have SP in the list. 1431 CHECK_EQ((regs & (1 << SP)), 0); 1432 } else { 1433 // Cannot have PC or SP in the list. 1434 CHECK_EQ((regs & (1 << PC | 1 << SP)), 0); 1435 } 1436 int32_t encoding = B31 | B30 | B29 | B27 | 1437 (op << 23) | 1438 (load ? B20 : 0) | 1439 base << 16 | 1440 regs | 1441 (w_bit << 21); 1442 Emit32(encoding); 1443 } else { 1444 int16_t encoding = B15 | B14 | 1445 (load ? B11 : 0) | 1446 base << 8 | 1447 regs; 1448 Emit16(encoding); 1449 } 1450} 1451 1452 1453void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x) { 1454 uint32_t pc = buffer_.Size(); 1455 Branch::Type branch_type; 1456 if (cond == AL) { 1457 if (link) { 1458 if (x) { 1459 branch_type = Branch::kUnconditionalLinkX; // BLX. 1460 } else { 1461 branch_type = Branch::kUnconditionalLink; // BX. 1462 } 1463 } else { 1464 branch_type = Branch::kUnconditional; // B. 1465 } 1466 } else { 1467 branch_type = Branch::kConditional; // B<cond>. 1468 } 1469 1470 if (label->IsBound()) { 1471 Branch::Size size = AddBranch(branch_type, pc, label->Position(), cond); // Resolved branch. 1472 1473 // The branch is to a bound label which means that it's a backwards branch. We know the 1474 // current size of it so we can emit the appropriate space. Note that if it's a 16 bit 1475 // branch the size may change if it so happens that other branches change size that change 1476 // the distance to the target and that distance puts this branch over the limit for 16 bits. 1477 if (size == Branch::k16Bit) { 1478 DCHECK(!force_32bit_branches_); 1479 Emit16(0); // Space for a 16 bit branch. 1480 } else { 1481 Emit32(0); // Space for a 32 bit branch. 1482 } 1483 } else { 1484 // Branch is to an unbound label. Emit space for it. 1485 uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch. 1486 if (force_32bit_branches_ || force_32bit_) { 1487 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1488 Emit16(0); // another 16 bits. 1489 } else { 1490 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1491 } 1492 label->LinkTo(branch_id); // Link to the branch ID. 1493 } 1494} 1495 1496 1497void Thumb2Assembler::clz(Register rd, Register rm, Condition cond) { 1498 CHECK_NE(rd, kNoRegister); 1499 CHECK_NE(rm, kNoRegister); 1500 CheckCondition(cond); 1501 CHECK_NE(rd, PC); 1502 CHECK_NE(rm, PC); 1503 int32_t encoding = B31 | B30 | B29 | B28 | B27 | 1504 B25 | B23 | B21 | B20 | 1505 static_cast<uint32_t>(rm) << 16 | 1506 0xf << 12 | 1507 static_cast<uint32_t>(rd) << 8 | 1508 B7 | 1509 static_cast<uint32_t>(rm); 1510 Emit32(encoding); 1511} 1512 1513 1514void Thumb2Assembler::movw(Register rd, uint16_t imm16, Condition cond) { 1515 CheckCondition(cond); 1516 bool must_be_32bit = force_32bit_; 1517 if (IsHighRegister(rd)|| imm16 >= 256u) { 1518 must_be_32bit = true; 1519 } 1520 1521 if (must_be_32bit) { 1522 // Use encoding T3. 1523 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1524 uint32_t i = (imm16 >> 11) & 0b1; 1525 uint32_t imm3 = (imm16 >> 8) & 0b111; 1526 uint32_t imm8 = imm16 & 0xff; 1527 int32_t encoding = B31 | B30 | B29 | B28 | 1528 B25 | B22 | 1529 static_cast<uint32_t>(rd) << 8 | 1530 i << 26 | 1531 imm4 << 16 | 1532 imm3 << 12 | 1533 imm8; 1534 Emit32(encoding); 1535 } else { 1536 int16_t encoding = B13 | static_cast<uint16_t>(rd) << 8 | 1537 imm16; 1538 Emit16(encoding); 1539 } 1540} 1541 1542 1543void Thumb2Assembler::movt(Register rd, uint16_t imm16, Condition cond) { 1544 CheckCondition(cond); 1545 // Always 32 bits. 1546 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1547 uint32_t i = (imm16 >> 11) & 0b1; 1548 uint32_t imm3 = (imm16 >> 8) & 0b111; 1549 uint32_t imm8 = imm16 & 0xff; 1550 int32_t encoding = B31 | B30 | B29 | B28 | 1551 B25 | B23 | B22 | 1552 static_cast<uint32_t>(rd) << 8 | 1553 i << 26 | 1554 imm4 << 16 | 1555 imm3 << 12 | 1556 imm8; 1557 Emit32(encoding); 1558} 1559 1560 1561void Thumb2Assembler::ldrex(Register rt, Register rn, uint16_t imm, Condition cond) { 1562 CHECK_NE(rn, kNoRegister); 1563 CHECK_NE(rt, kNoRegister); 1564 CheckCondition(cond); 1565 CHECK_NE(rn, kNoRegister); 1566 CHECK_NE(rt, kNoRegister); 1567 CheckCondition(cond); 1568 CHECK_LT(imm, (1u << 10)); 1569 1570 int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 | 1571 static_cast<uint32_t>(rn) << 16 | 1572 static_cast<uint32_t>(rt) << 12 | 1573 0xf << 8 | 1574 imm >> 2; 1575 Emit32(encoding); 1576} 1577 1578 1579void Thumb2Assembler::ldrex(Register rt, Register rn, Condition cond) { 1580 ldrex(rt, rn, 0, cond); 1581} 1582 1583 1584void Thumb2Assembler::strex(Register rd, 1585 Register rt, 1586 Register rn, 1587 uint16_t imm, 1588 Condition cond) { 1589 CHECK_NE(rn, kNoRegister); 1590 CHECK_NE(rd, kNoRegister); 1591 CHECK_NE(rt, kNoRegister); 1592 CheckCondition(cond); 1593 CHECK_LT(imm, (1u << 10)); 1594 1595 int32_t encoding = B31 | B30 | B29 | B27 | B22 | 1596 static_cast<uint32_t>(rn) << 16 | 1597 static_cast<uint32_t>(rt) << 12 | 1598 static_cast<uint32_t>(rd) << 8 | 1599 imm >> 2; 1600 Emit32(encoding); 1601} 1602 1603 1604void Thumb2Assembler::strex(Register rd, 1605 Register rt, 1606 Register rn, 1607 Condition cond) { 1608 strex(rd, rt, rn, 0, cond); 1609} 1610 1611 1612void Thumb2Assembler::clrex(Condition cond) { 1613 CheckCondition(cond); 1614 int32_t encoding = B31 | B30 | B29 | B27 | B28 | B25 | B24 | B23 | 1615 B21 | B20 | 1616 0xf << 16 | 1617 B15 | 1618 0xf << 8 | 1619 B5 | 1620 0xf; 1621 Emit32(encoding); 1622} 1623 1624 1625void Thumb2Assembler::nop(Condition cond) { 1626 CheckCondition(cond); 1627 int16_t encoding = B15 | B13 | B12 | 1628 B11 | B10 | B9 | B8; 1629 Emit16(encoding); 1630} 1631 1632 1633void Thumb2Assembler::vmovsr(SRegister sn, Register rt, Condition cond) { 1634 CHECK_NE(sn, kNoSRegister); 1635 CHECK_NE(rt, kNoRegister); 1636 CHECK_NE(rt, SP); 1637 CHECK_NE(rt, PC); 1638 CheckCondition(cond); 1639 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1640 B27 | B26 | B25 | 1641 ((static_cast<int32_t>(sn) >> 1)*B16) | 1642 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1643 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1644 Emit32(encoding); 1645} 1646 1647 1648void Thumb2Assembler::vmovrs(Register rt, SRegister sn, Condition cond) { 1649 CHECK_NE(sn, kNoSRegister); 1650 CHECK_NE(rt, kNoRegister); 1651 CHECK_NE(rt, SP); 1652 CHECK_NE(rt, PC); 1653 CheckCondition(cond); 1654 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1655 B27 | B26 | B25 | B20 | 1656 ((static_cast<int32_t>(sn) >> 1)*B16) | 1657 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1658 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1659 Emit32(encoding); 1660} 1661 1662 1663void Thumb2Assembler::vmovsrr(SRegister sm, Register rt, Register rt2, 1664 Condition cond) { 1665 CHECK_NE(sm, kNoSRegister); 1666 CHECK_NE(sm, S31); 1667 CHECK_NE(rt, kNoRegister); 1668 CHECK_NE(rt, SP); 1669 CHECK_NE(rt, PC); 1670 CHECK_NE(rt2, kNoRegister); 1671 CHECK_NE(rt2, SP); 1672 CHECK_NE(rt2, PC); 1673 CheckCondition(cond); 1674 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1675 B27 | B26 | B22 | 1676 (static_cast<int32_t>(rt2)*B16) | 1677 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1678 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1679 (static_cast<int32_t>(sm) >> 1); 1680 Emit32(encoding); 1681} 1682 1683 1684void Thumb2Assembler::vmovrrs(Register rt, Register rt2, SRegister sm, 1685 Condition cond) { 1686 CHECK_NE(sm, kNoSRegister); 1687 CHECK_NE(sm, S31); 1688 CHECK_NE(rt, kNoRegister); 1689 CHECK_NE(rt, SP); 1690 CHECK_NE(rt, PC); 1691 CHECK_NE(rt2, kNoRegister); 1692 CHECK_NE(rt2, SP); 1693 CHECK_NE(rt2, PC); 1694 CHECK_NE(rt, rt2); 1695 CheckCondition(cond); 1696 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1697 B27 | B26 | B22 | B20 | 1698 (static_cast<int32_t>(rt2)*B16) | 1699 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1700 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1701 (static_cast<int32_t>(sm) >> 1); 1702 Emit32(encoding); 1703} 1704 1705 1706void Thumb2Assembler::vmovdrr(DRegister dm, Register rt, Register rt2, 1707 Condition cond) { 1708 CHECK_NE(dm, kNoDRegister); 1709 CHECK_NE(rt, kNoRegister); 1710 CHECK_NE(rt, SP); 1711 CHECK_NE(rt, PC); 1712 CHECK_NE(rt2, kNoRegister); 1713 CHECK_NE(rt2, SP); 1714 CHECK_NE(rt2, PC); 1715 CheckCondition(cond); 1716 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1717 B27 | B26 | B22 | 1718 (static_cast<int32_t>(rt2)*B16) | 1719 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1720 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1721 (static_cast<int32_t>(dm) & 0xf); 1722 Emit32(encoding); 1723} 1724 1725 1726void Thumb2Assembler::vmovrrd(Register rt, Register rt2, DRegister dm, 1727 Condition cond) { 1728 CHECK_NE(dm, kNoDRegister); 1729 CHECK_NE(rt, kNoRegister); 1730 CHECK_NE(rt, SP); 1731 CHECK_NE(rt, PC); 1732 CHECK_NE(rt2, kNoRegister); 1733 CHECK_NE(rt2, SP); 1734 CHECK_NE(rt2, PC); 1735 CHECK_NE(rt, rt2); 1736 CheckCondition(cond); 1737 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1738 B27 | B26 | B22 | B20 | 1739 (static_cast<int32_t>(rt2)*B16) | 1740 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1741 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1742 (static_cast<int32_t>(dm) & 0xf); 1743 Emit32(encoding); 1744} 1745 1746 1747void Thumb2Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) { 1748 const Address& addr = static_cast<const Address&>(ad); 1749 CHECK_NE(sd, kNoSRegister); 1750 CheckCondition(cond); 1751 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1752 B27 | B26 | B24 | B20 | 1753 ((static_cast<int32_t>(sd) & 1)*B22) | 1754 ((static_cast<int32_t>(sd) >> 1)*B12) | 1755 B11 | B9 | addr.vencoding(); 1756 Emit32(encoding); 1757} 1758 1759 1760void Thumb2Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) { 1761 const Address& addr = static_cast<const Address&>(ad); 1762 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1763 CHECK_NE(sd, kNoSRegister); 1764 CheckCondition(cond); 1765 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1766 B27 | B26 | B24 | 1767 ((static_cast<int32_t>(sd) & 1)*B22) | 1768 ((static_cast<int32_t>(sd) >> 1)*B12) | 1769 B11 | B9 | addr.vencoding(); 1770 Emit32(encoding); 1771} 1772 1773 1774void Thumb2Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) { 1775 const Address& addr = static_cast<const Address&>(ad); 1776 CHECK_NE(dd, kNoDRegister); 1777 CheckCondition(cond); 1778 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1779 B27 | B26 | B24 | B20 | 1780 ((static_cast<int32_t>(dd) >> 4)*B22) | 1781 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1782 B11 | B9 | B8 | addr.vencoding(); 1783 Emit32(encoding); 1784} 1785 1786 1787void Thumb2Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) { 1788 const Address& addr = static_cast<const Address&>(ad); 1789 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1790 CHECK_NE(dd, kNoDRegister); 1791 CheckCondition(cond); 1792 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1793 B27 | B26 | B24 | 1794 ((static_cast<int32_t>(dd) >> 4)*B22) | 1795 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1796 B11 | B9 | B8 | addr.vencoding(); 1797 Emit32(encoding); 1798} 1799 1800 1801void Thumb2Assembler::vpushs(SRegister reg, int nregs, Condition cond) { 1802 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond); 1803} 1804 1805 1806void Thumb2Assembler::vpushd(DRegister reg, int nregs, Condition cond) { 1807 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond); 1808} 1809 1810 1811void Thumb2Assembler::vpops(SRegister reg, int nregs, Condition cond) { 1812 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond); 1813} 1814 1815 1816void Thumb2Assembler::vpopd(DRegister reg, int nregs, Condition cond) { 1817 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond); 1818} 1819 1820 1821void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) { 1822 CheckCondition(cond); 1823 1824 uint32_t D; 1825 uint32_t Vd; 1826 if (dbl) { 1827 // Encoded as D:Vd. 1828 D = (reg >> 4) & 1; 1829 Vd = reg & 0b1111; 1830 } else { 1831 // Encoded as Vd:D. 1832 D = reg & 1; 1833 Vd = (reg >> 1) & 0b1111; 1834 } 1835 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 | 1836 B11 | B9 | 1837 (dbl ? B8 : 0) | 1838 (push ? B24 : (B23 | B20)) | 1839 0b1110 << 28 | 1840 nregs << (dbl ? 1 : 0) | 1841 D << 22 | 1842 Vd << 12; 1843 Emit32(encoding); 1844} 1845 1846 1847void Thumb2Assembler::EmitVFPsss(Condition cond, int32_t opcode, 1848 SRegister sd, SRegister sn, SRegister sm) { 1849 CHECK_NE(sd, kNoSRegister); 1850 CHECK_NE(sn, kNoSRegister); 1851 CHECK_NE(sm, kNoSRegister); 1852 CheckCondition(cond); 1853 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1854 B27 | B26 | B25 | B11 | B9 | opcode | 1855 ((static_cast<int32_t>(sd) & 1)*B22) | 1856 ((static_cast<int32_t>(sn) >> 1)*B16) | 1857 ((static_cast<int32_t>(sd) >> 1)*B12) | 1858 ((static_cast<int32_t>(sn) & 1)*B7) | 1859 ((static_cast<int32_t>(sm) & 1)*B5) | 1860 (static_cast<int32_t>(sm) >> 1); 1861 Emit32(encoding); 1862} 1863 1864 1865void Thumb2Assembler::EmitVFPddd(Condition cond, int32_t opcode, 1866 DRegister dd, DRegister dn, DRegister dm) { 1867 CHECK_NE(dd, kNoDRegister); 1868 CHECK_NE(dn, kNoDRegister); 1869 CHECK_NE(dm, kNoDRegister); 1870 CheckCondition(cond); 1871 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1872 B27 | B26 | B25 | B11 | B9 | B8 | opcode | 1873 ((static_cast<int32_t>(dd) >> 4)*B22) | 1874 ((static_cast<int32_t>(dn) & 0xf)*B16) | 1875 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1876 ((static_cast<int32_t>(dn) >> 4)*B7) | 1877 ((static_cast<int32_t>(dm) >> 4)*B5) | 1878 (static_cast<int32_t>(dm) & 0xf); 1879 Emit32(encoding); 1880} 1881 1882 1883void Thumb2Assembler::EmitVFPsd(Condition cond, int32_t opcode, 1884 SRegister sd, DRegister dm) { 1885 CHECK_NE(sd, kNoSRegister); 1886 CHECK_NE(dm, kNoDRegister); 1887 CheckCondition(cond); 1888 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1889 B27 | B26 | B25 | B11 | B9 | opcode | 1890 ((static_cast<int32_t>(sd) & 1)*B22) | 1891 ((static_cast<int32_t>(sd) >> 1)*B12) | 1892 ((static_cast<int32_t>(dm) >> 4)*B5) | 1893 (static_cast<int32_t>(dm) & 0xf); 1894 Emit32(encoding); 1895} 1896 1897 1898void Thumb2Assembler::EmitVFPds(Condition cond, int32_t opcode, 1899 DRegister dd, SRegister sm) { 1900 CHECK_NE(dd, kNoDRegister); 1901 CHECK_NE(sm, kNoSRegister); 1902 CheckCondition(cond); 1903 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1904 B27 | B26 | B25 | B11 | B9 | opcode | 1905 ((static_cast<int32_t>(dd) >> 4)*B22) | 1906 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1907 ((static_cast<int32_t>(sm) & 1)*B5) | 1908 (static_cast<int32_t>(sm) >> 1); 1909 Emit32(encoding); 1910} 1911 1912 1913void Thumb2Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR. 1914 CheckCondition(cond); 1915 UNIMPLEMENTED(FATAL) << "Unimplemented thumb instruction"; 1916} 1917 1918 1919void Thumb2Assembler::svc(uint32_t imm8) { 1920 CHECK(IsUint(8, imm8)) << imm8; 1921 int16_t encoding = B15 | B14 | B12 | 1922 B11 | B10 | B9 | B8 | 1923 imm8; 1924 Emit16(encoding); 1925} 1926 1927 1928void Thumb2Assembler::bkpt(uint16_t imm8) { 1929 CHECK(IsUint(8, imm8)) << imm8; 1930 int16_t encoding = B15 | B13 | B12 | 1931 B11 | B10 | B9 | 1932 imm8; 1933 Emit16(encoding); 1934} 1935 1936// Convert the given IT state to a mask bit given bit 0 of the first 1937// condition and a shift position. 1938static uint8_t ToItMask(ItState s, uint8_t firstcond0, uint8_t shift) { 1939 switch (s) { 1940 case kItOmitted: return 1 << shift; 1941 case kItThen: return firstcond0 << shift; 1942 case kItElse: return !firstcond0 << shift; 1943 } 1944 return 0; 1945} 1946 1947 1948// Set the IT condition in the given position for the given state. This is used 1949// to check that conditional instructions match the preceding IT statement. 1950void Thumb2Assembler::SetItCondition(ItState s, Condition cond, uint8_t index) { 1951 switch (s) { 1952 case kItOmitted: it_conditions_[index] = AL; break; 1953 case kItThen: it_conditions_[index] = cond; break; 1954 case kItElse: 1955 it_conditions_[index] = static_cast<Condition>(static_cast<uint8_t>(cond) ^ 1); 1956 break; 1957 } 1958} 1959 1960 1961void Thumb2Assembler::it(Condition firstcond, ItState i1, ItState i2, ItState i3) { 1962 CheckCondition(AL); // Not allowed in IT block. 1963 uint8_t firstcond0 = static_cast<uint8_t>(firstcond) & 1; 1964 1965 // All conditions to AL. 1966 for (uint8_t i = 0; i < 4; ++i) { 1967 it_conditions_[i] = AL; 1968 } 1969 1970 SetItCondition(kItThen, firstcond, 0); 1971 uint8_t mask = ToItMask(i1, firstcond0, 3); 1972 SetItCondition(i1, firstcond, 1); 1973 1974 if (i1 != kItOmitted) { 1975 mask |= ToItMask(i2, firstcond0, 2); 1976 SetItCondition(i2, firstcond, 2); 1977 if (i2 != kItOmitted) { 1978 mask |= ToItMask(i3, firstcond0, 1); 1979 SetItCondition(i3, firstcond, 3); 1980 if (i3 != kItOmitted) { 1981 mask |= 0b0001; 1982 } 1983 } 1984 } 1985 1986 // Start at first condition. 1987 it_cond_index_ = 0; 1988 next_condition_ = it_conditions_[0]; 1989 uint16_t encoding = B15 | B13 | B12 | 1990 B11 | B10 | B9 | B8 | 1991 firstcond << 4 | 1992 mask; 1993 Emit16(encoding); 1994} 1995 1996 1997void Thumb2Assembler::cbz(Register rn, Label* label) { 1998 CheckCondition(AL); 1999 if (label->IsBound()) { 2000 LOG(FATAL) << "cbz can only be used to branch forwards"; 2001 } else { 2002 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), false); 2003 label->LinkTo(branchid); 2004 } 2005} 2006 2007 2008void Thumb2Assembler::cbnz(Register rn, Label* label) { 2009 CheckCondition(AL); 2010 if (label->IsBound()) { 2011 LOG(FATAL) << "cbnz can only be used to branch forwards"; 2012 } else { 2013 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), true); 2014 label->LinkTo(branchid); 2015 } 2016} 2017 2018 2019void Thumb2Assembler::blx(Register rm, Condition cond) { 2020 CHECK_NE(rm, kNoRegister); 2021 CheckCondition(cond); 2022 int16_t encoding = B14 | B10 | B9 | B8 | B7 | static_cast<int16_t>(rm) << 3; 2023 Emit16(encoding); 2024} 2025 2026 2027void Thumb2Assembler::bx(Register rm, Condition cond) { 2028 CHECK_NE(rm, kNoRegister); 2029 CheckCondition(cond); 2030 int16_t encoding = B14 | B10 | B9 | B8 | static_cast<int16_t>(rm) << 3; 2031 Emit16(encoding); 2032} 2033 2034 2035void Thumb2Assembler::Push(Register rd, Condition cond) { 2036 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond); 2037} 2038 2039 2040void Thumb2Assembler::Pop(Register rd, Condition cond) { 2041 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond); 2042} 2043 2044 2045void Thumb2Assembler::PushList(RegList regs, Condition cond) { 2046 stm(DB_W, SP, regs, cond); 2047} 2048 2049 2050void Thumb2Assembler::PopList(RegList regs, Condition cond) { 2051 ldm(IA_W, SP, regs, cond); 2052} 2053 2054 2055void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) { 2056 if (cond != AL || rd != rm) { 2057 mov(rd, ShifterOperand(rm), cond); 2058 } 2059} 2060 2061 2062// A branch has changed size. Make a hole for it. 2063void Thumb2Assembler::MakeHoleForBranch(uint32_t location, uint32_t delta) { 2064 // Move the contents of the buffer using: Move(newposition, oldposition) 2065 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2066 buffer_.Move(location + delta, location); 2067} 2068 2069 2070void Thumb2Assembler::Bind(Label* label) { 2071 CHECK(!label->IsBound()); 2072 uint32_t bound_pc = buffer_.Size(); 2073 std::vector<Branch*> changed_branches; 2074 2075 while (label->IsLinked()) { 2076 uint16_t position = label->Position(); // Branch id for linked branch. 2077 Branch* branch = GetBranch(position); // Get the branch at this id. 2078 bool changed = branch->Resolve(bound_pc); // Branch can be resolved now. 2079 uint32_t branch_location = branch->GetLocation(); 2080 uint16_t next = buffer_.Load<uint16_t>(branch_location); // Get next in chain. 2081 if (changed) { 2082 DCHECK(!force_32bit_branches_); 2083 MakeHoleForBranch(branch->GetLocation(), 2); 2084 if (branch->IsCompareAndBranch()) { 2085 // A cbz/cbnz instruction has changed size. There is no valid encoding for 2086 // a 32 bit cbz/cbnz so we need to change this to an instruction pair: 2087 // cmp rn, #0 2088 // b<eq|ne> target 2089 bool n = branch->GetType() == Branch::kCompareAndBranchNonZero; 2090 Condition cond = n ? NE : EQ; 2091 branch->Move(2); // Move the branch forward by 2 bytes. 2092 branch->ResetTypeAndCondition(Branch::kConditional, cond); 2093 branch->ResetSize(Branch::k16Bit); 2094 2095 // Now add a compare instruction in the place the branch was. 2096 int16_t cmp = B13 | B11 | static_cast<int16_t>(branch->GetRegister()) << 8; 2097 buffer_.Store<int16_t>(branch_location, cmp); 2098 2099 // Since have moved made a hole in the code we need to reload the 2100 // current pc. 2101 bound_pc = buffer_.Size(); 2102 2103 // Now resolve the newly added branch. 2104 changed = branch->Resolve(bound_pc); 2105 if (changed) { 2106 MakeHoleForBranch(branch->GetLocation(), 2); 2107 changed_branches.push_back(branch); 2108 } 2109 } else { 2110 changed_branches.push_back(branch); 2111 } 2112 } 2113 label->position_ = next; // Move to next. 2114 } 2115 label->BindTo(bound_pc); 2116 2117 // Now relocate any changed branches. Do this until there are no more changes. 2118 std::vector<Branch*> branches_to_process = changed_branches; 2119 while (branches_to_process.size() != 0) { 2120 changed_branches.clear(); 2121 for (auto& changed_branch : branches_to_process) { 2122 for (auto& branch : branches_) { 2123 bool changed = branch->Relocate(changed_branch->GetLocation(), 2); 2124 if (changed) { 2125 changed_branches.push_back(branch); 2126 } 2127 } 2128 branches_to_process = changed_branches; 2129 } 2130 } 2131} 2132 2133 2134void Thumb2Assembler::EmitBranches() { 2135 for (auto& branch : branches_) { 2136 branch->Emit(&buffer_); 2137 } 2138} 2139 2140 2141void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, 2142 bool setcc, Condition cond) { 2143 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted. 2144 CheckCondition(cond); 2145 EmitShift(rd, rm, LSL, shift_imm, setcc); 2146} 2147 2148 2149void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, 2150 bool setcc, Condition cond) { 2151 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted. 2152 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2153 CheckCondition(cond); 2154 EmitShift(rd, rm, LSR, shift_imm, setcc); 2155} 2156 2157 2158void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, 2159 bool setcc, Condition cond) { 2160 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted. 2161 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2162 CheckCondition(cond); 2163 EmitShift(rd, rm, ASR, shift_imm, setcc); 2164} 2165 2166 2167void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm, 2168 bool setcc, Condition cond) { 2169 CHECK_NE(shift_imm, 0u); // Use Rrx instruction. 2170 CheckCondition(cond); 2171 EmitShift(rd, rm, ROR, shift_imm, setcc); 2172} 2173 2174 2175void Thumb2Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) { 2176 CheckCondition(cond); 2177 EmitShift(rd, rm, RRX, rm, setcc); 2178} 2179 2180 2181void Thumb2Assembler::Lsl(Register rd, Register rm, Register rn, 2182 bool setcc, Condition cond) { 2183 CheckCondition(cond); 2184 EmitShift(rd, rm, LSL, rn, setcc); 2185} 2186 2187 2188void Thumb2Assembler::Lsr(Register rd, Register rm, Register rn, 2189 bool setcc, Condition cond) { 2190 CheckCondition(cond); 2191 EmitShift(rd, rm, LSR, rn, setcc); 2192} 2193 2194 2195void Thumb2Assembler::Asr(Register rd, Register rm, Register rn, 2196 bool setcc, Condition cond) { 2197 CheckCondition(cond); 2198 EmitShift(rd, rm, ASR, rn, setcc); 2199} 2200 2201 2202void Thumb2Assembler::Ror(Register rd, Register rm, Register rn, 2203 bool setcc, Condition cond) { 2204 CheckCondition(cond); 2205 EmitShift(rd, rm, ROR, rn, setcc); 2206} 2207 2208 2209int32_t Thumb2Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { 2210 // The offset is off by 4 due to the way the ARM CPUs read PC. 2211 offset -= 4; 2212 offset >>= 1; 2213 2214 uint32_t value = 0; 2215 // There are two different encodings depending on the value of bit 12. In one case 2216 // intermediate values are calculated using the sign bit. 2217 if ((inst & B12) == B12) { 2218 // 25 bits of offset. 2219 uint32_t signbit = (offset >> 31) & 0x1; 2220 uint32_t i1 = (offset >> 22) & 0x1; 2221 uint32_t i2 = (offset >> 21) & 0x1; 2222 uint32_t imm10 = (offset >> 11) & 0x03ff; 2223 uint32_t imm11 = offset & 0x07ff; 2224 uint32_t j1 = (i1 ^ signbit) ? 0 : 1; 2225 uint32_t j2 = (i2 ^ signbit) ? 0 : 1; 2226 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm10 << 16) | 2227 imm11; 2228 // Remove the offset from the current encoding. 2229 inst &= ~(0x3ff << 16 | 0x7ff); 2230 } else { 2231 uint32_t signbit = (offset >> 31) & 0x1; 2232 uint32_t imm6 = (offset >> 11) & 0x03f; 2233 uint32_t imm11 = offset & 0x07ff; 2234 uint32_t j1 = (offset >> 19) & 1; 2235 uint32_t j2 = (offset >> 17) & 1; 2236 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm6 << 16) | 2237 imm11; 2238 // Remove the offset from the current encoding. 2239 inst &= ~(0x3f << 16 | 0x7ff); 2240 } 2241 // Mask out offset bits in current instruction. 2242 inst &= ~(B26 | B13 | B11); 2243 inst |= value; 2244 return inst; 2245} 2246 2247 2248int Thumb2Assembler::DecodeBranchOffset(int32_t instr) { 2249 int32_t imm32; 2250 if ((instr & B12) == B12) { 2251 uint32_t S = (instr >> 26) & 1; 2252 uint32_t J2 = (instr >> 11) & 1; 2253 uint32_t J1 = (instr >> 13) & 1; 2254 uint32_t imm10 = (instr >> 16) & 0x3FF; 2255 uint32_t imm11 = instr & 0x7FF; 2256 2257 uint32_t I1 = ~(J1 ^ S) & 1; 2258 uint32_t I2 = ~(J2 ^ S) & 1; 2259 imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2260 imm32 = (imm32 << 8) >> 8; // sign extend 24 bit immediate. 2261 } else { 2262 uint32_t S = (instr >> 26) & 1; 2263 uint32_t J2 = (instr >> 11) & 1; 2264 uint32_t J1 = (instr >> 13) & 1; 2265 uint32_t imm6 = (instr >> 16) & 0x3F; 2266 uint32_t imm11 = instr & 0x7FF; 2267 2268 imm32 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2269 imm32 = (imm32 << 11) >> 11; // sign extend 21 bit immediate. 2270 } 2271 imm32 += 4; 2272 return imm32; 2273} 2274 2275 2276void Thumb2Assembler::AddConstant(Register rd, int32_t value, Condition cond) { 2277 AddConstant(rd, rd, value, cond); 2278} 2279 2280 2281void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value, 2282 Condition cond) { 2283 if (value == 0) { 2284 if (rd != rn) { 2285 mov(rd, ShifterOperand(rn), cond); 2286 } 2287 return; 2288 } 2289 // We prefer to select the shorter code sequence rather than selecting add for 2290 // positive values and sub for negatives ones, which would slightly improve 2291 // the readability of generated code for some constants. 2292 ShifterOperand shifter_op; 2293 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2294 add(rd, rn, shifter_op, cond); 2295 } else if (ShifterOperand::CanHoldThumb(rd, rn, SUB, -value, &shifter_op)) { 2296 sub(rd, rn, shifter_op, cond); 2297 } else { 2298 CHECK(rn != IP); 2299 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2300 mvn(IP, shifter_op, cond); 2301 add(rd, rn, ShifterOperand(IP), cond); 2302 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2303 mvn(IP, shifter_op, cond); 2304 sub(rd, rn, ShifterOperand(IP), cond); 2305 } else { 2306 movw(IP, Low16Bits(value), cond); 2307 uint16_t value_high = High16Bits(value); 2308 if (value_high != 0) { 2309 movt(IP, value_high, cond); 2310 } 2311 add(rd, rn, ShifterOperand(IP), cond); 2312 } 2313 } 2314} 2315 2316 2317void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value, 2318 Condition cond) { 2319 ShifterOperand shifter_op; 2320 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2321 adds(rd, rn, shifter_op, cond); 2322 } else if (ShifterOperand::CanHoldThumb(rd, rn, ADD, -value, &shifter_op)) { 2323 subs(rd, rn, shifter_op, cond); 2324 } else { 2325 CHECK(rn != IP); 2326 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2327 mvn(IP, shifter_op, cond); 2328 adds(rd, rn, ShifterOperand(IP), cond); 2329 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2330 mvn(IP, shifter_op, cond); 2331 subs(rd, rn, ShifterOperand(IP), cond); 2332 } else { 2333 movw(IP, Low16Bits(value), cond); 2334 uint16_t value_high = High16Bits(value); 2335 if (value_high != 0) { 2336 movt(IP, value_high, cond); 2337 } 2338 adds(rd, rn, ShifterOperand(IP), cond); 2339 } 2340 } 2341} 2342 2343 2344void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { 2345 ShifterOperand shifter_op; 2346 if (ShifterOperand::CanHoldThumb(rd, R0, MOV, value, &shifter_op)) { 2347 mov(rd, shifter_op, cond); 2348 } else if (ShifterOperand::CanHoldThumb(rd, R0, MVN, ~value, &shifter_op)) { 2349 mvn(rd, shifter_op, cond); 2350 } else { 2351 movw(rd, Low16Bits(value), cond); 2352 uint16_t value_high = High16Bits(value); 2353 if (value_high != 0) { 2354 movt(rd, value_high, cond); 2355 } 2356 } 2357} 2358 2359// Implementation note: this method must emit at most one instruction when 2360// Address::CanHoldLoadOffsetThumb. 2361void Thumb2Assembler::LoadFromOffset(LoadOperandType type, 2362 Register reg, 2363 Register base, 2364 int32_t offset, 2365 Condition cond) { 2366 if (!Address::CanHoldLoadOffsetThumb(type, offset)) { 2367 CHECK(base != IP); 2368 LoadImmediate(IP, offset, cond); 2369 add(IP, IP, ShifterOperand(base), cond); 2370 base = IP; 2371 offset = 0; 2372 } 2373 CHECK(Address::CanHoldLoadOffsetThumb(type, offset)); 2374 switch (type) { 2375 case kLoadSignedByte: 2376 ldrsb(reg, Address(base, offset), cond); 2377 break; 2378 case kLoadUnsignedByte: 2379 ldrb(reg, Address(base, offset), cond); 2380 break; 2381 case kLoadSignedHalfword: 2382 ldrsh(reg, Address(base, offset), cond); 2383 break; 2384 case kLoadUnsignedHalfword: 2385 ldrh(reg, Address(base, offset), cond); 2386 break; 2387 case kLoadWord: 2388 ldr(reg, Address(base, offset), cond); 2389 break; 2390 case kLoadWordPair: 2391 ldrd(reg, Address(base, offset), cond); 2392 break; 2393 default: 2394 LOG(FATAL) << "UNREACHABLE"; 2395 } 2396} 2397 2398 2399// Implementation note: this method must emit at most one instruction when 2400// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2401void Thumb2Assembler::LoadSFromOffset(SRegister reg, 2402 Register base, 2403 int32_t offset, 2404 Condition cond) { 2405 if (!Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)) { 2406 CHECK_NE(base, IP); 2407 LoadImmediate(IP, offset, cond); 2408 add(IP, IP, ShifterOperand(base), cond); 2409 base = IP; 2410 offset = 0; 2411 } 2412 CHECK(Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)); 2413 vldrs(reg, Address(base, offset), cond); 2414} 2415 2416 2417// Implementation note: this method must emit at most one instruction when 2418// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2419void Thumb2Assembler::LoadDFromOffset(DRegister reg, 2420 Register base, 2421 int32_t offset, 2422 Condition cond) { 2423 if (!Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)) { 2424 CHECK_NE(base, IP); 2425 LoadImmediate(IP, offset, cond); 2426 add(IP, IP, ShifterOperand(base), cond); 2427 base = IP; 2428 offset = 0; 2429 } 2430 CHECK(Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)); 2431 vldrd(reg, Address(base, offset), cond); 2432} 2433 2434 2435// Implementation note: this method must emit at most one instruction when 2436// Address::CanHoldStoreOffsetThumb. 2437void Thumb2Assembler::StoreToOffset(StoreOperandType type, 2438 Register reg, 2439 Register base, 2440 int32_t offset, 2441 Condition cond) { 2442 if (!Address::CanHoldStoreOffsetThumb(type, offset)) { 2443 CHECK(reg != IP); 2444 CHECK(base != IP); 2445 LoadImmediate(IP, offset, cond); 2446 add(IP, IP, ShifterOperand(base), cond); 2447 base = IP; 2448 offset = 0; 2449 } 2450 CHECK(Address::CanHoldStoreOffsetThumb(type, offset)); 2451 switch (type) { 2452 case kStoreByte: 2453 strb(reg, Address(base, offset), cond); 2454 break; 2455 case kStoreHalfword: 2456 strh(reg, Address(base, offset), cond); 2457 break; 2458 case kStoreWord: 2459 str(reg, Address(base, offset), cond); 2460 break; 2461 case kStoreWordPair: 2462 strd(reg, Address(base, offset), cond); 2463 break; 2464 default: 2465 LOG(FATAL) << "UNREACHABLE"; 2466 } 2467} 2468 2469 2470// Implementation note: this method must emit at most one instruction when 2471// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreToOffset. 2472void Thumb2Assembler::StoreSToOffset(SRegister reg, 2473 Register base, 2474 int32_t offset, 2475 Condition cond) { 2476 if (!Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)) { 2477 CHECK_NE(base, IP); 2478 LoadImmediate(IP, offset, cond); 2479 add(IP, IP, ShifterOperand(base), cond); 2480 base = IP; 2481 offset = 0; 2482 } 2483 CHECK(Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)); 2484 vstrs(reg, Address(base, offset), cond); 2485} 2486 2487 2488// Implementation note: this method must emit at most one instruction when 2489// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreSToOffset. 2490void Thumb2Assembler::StoreDToOffset(DRegister reg, 2491 Register base, 2492 int32_t offset, 2493 Condition cond) { 2494 if (!Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)) { 2495 CHECK_NE(base, IP); 2496 LoadImmediate(IP, offset, cond); 2497 add(IP, IP, ShifterOperand(base), cond); 2498 base = IP; 2499 offset = 0; 2500 } 2501 CHECK(Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)); 2502 vstrd(reg, Address(base, offset), cond); 2503} 2504 2505 2506void Thumb2Assembler::MemoryBarrier(ManagedRegister mscratch) { 2507 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12); 2508#if ANDROID_SMP != 0 2509 int32_t encoding = 0xf3bf8f5f; // dmb in T1 encoding. 2510 Emit32(encoding); 2511#endif 2512} 2513 2514 2515void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) { 2516 cbz(r, label); 2517} 2518 2519 2520void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) { 2521 cbnz(r, label); 2522} 2523} // namespace arm 2524} // namespace art 2525