assembler_thumb2.cc revision 8d486731559ba0c5e12c27b4a507181333702b7e
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 || opcode == ADD || opcode == SUB; 623 624 if (IsHighRegister(rd) || IsHighRegister(rn)) { 625 if (can_contain_high_register) { 626 // There are high register instructions available for this opcode. 627 // However, there is no RRX available. 628 if (so.IsShift() && so.GetShift() == RRX) { 629 return true; 630 } 631 632 // Check special case for SP relative ADD and SUB immediate. 633 if ((opcode == ADD || opcode == SUB) && so.IsImmediate()) { 634 // If rn is SP and rd is a high register we need to use a 32 bit encoding. 635 if (rn == SP && rd != SP && IsHighRegister(rd)) { 636 return true; 637 } 638 639 uint32_t imm = so.GetImmediate(); 640 // If the immediates are out of range use 32 bit. 641 if (rd == SP && rn == SP) { 642 if (imm > (1 << 9)) { // 9 bit immediate. 643 return true; 644 } 645 } else if (opcode == ADD && rd != SP && rn == SP) { // 10 bit immediate. 646 if (imm > (1 << 10)) { 647 return true; 648 } 649 } else if (opcode == SUB && rd != SP && rn == SP) { 650 // SUB rd, SP, #imm is always 32 bit. 651 return true; 652 } 653 } 654 } 655 656 // The ADD,SUB and MOV instructions that work with high registers don't have 657 // immediate variants. 658 if (so.IsImmediate()) { 659 return true; 660 } 661 } 662 663 if (so.IsRegister() && IsHighRegister(so.GetRegister()) && !can_contain_high_register) { 664 return true; 665 } 666 667 // Check for MOV with an ROR. 668 if (opcode == MOV && so.IsRegister() && so.IsShift() && so.GetShift() == ROR) { 669 if (so.GetImmediate() != 0) { 670 return true; 671 } 672 } 673 674 bool rn_is_valid = true; 675 676 // Check for single operand instructions and ADD/SUB. 677 switch (opcode) { 678 case CMP: 679 case MOV: 680 case TST: 681 case MVN: 682 rn_is_valid = false; // There is no Rn for these instructions. 683 break; 684 case TEQ: 685 return true; 686 break; 687 case ADD: 688 case SUB: 689 break; 690 default: 691 if (so.IsRegister() && rd != rn) { 692 return true; 693 } 694 } 695 696 if (so.IsImmediate()) { 697 if (rn_is_valid && rn != rd) { 698 // The only thumb1 instruction with a register and an immediate are ADD and SUB. The 699 // immediate must be 3 bits. 700 if (opcode != ADD && opcode != SUB) { 701 return true; 702 } else { 703 // Check that the immediate is 3 bits for ADD and SUB. 704 if (so.GetImmediate() >= 8) { 705 return true; 706 } 707 } 708 } else { 709 // ADD, SUB, CMP and MOV may be thumb1 only if the immediate is 8 bits. 710 if (!(opcode == ADD || opcode == SUB || opcode == MOV || opcode == CMP)) { 711 return true; 712 } else { 713 if (so.GetImmediate() > 255) { 714 return true; 715 } 716 } 717 } 718 } 719 720 // The instruction can be encoded in 16 bits. 721 return false; 722} 723 724 725void Thumb2Assembler::Emit32BitDataProcessing(Condition cond, 726 Opcode opcode, 727 int set_cc, 728 Register rn, 729 Register rd, 730 const ShifterOperand& so) { 731 uint8_t thumb_opcode = 0b11111111; 732 switch (opcode) { 733 case AND: thumb_opcode = 0b0000; break; 734 case EOR: thumb_opcode = 0b0100; break; 735 case SUB: thumb_opcode = 0b1101; break; 736 case RSB: thumb_opcode = 0b1110; break; 737 case ADD: thumb_opcode = 0b1000; break; 738 case ADC: thumb_opcode = 0b1010; break; 739 case SBC: thumb_opcode = 0b1011; break; 740 case RSC: break; 741 case TST: thumb_opcode = 0b0000; set_cc = true; rd = PC; break; 742 case TEQ: thumb_opcode = 0b0100; set_cc = true; rd = PC; break; 743 case CMP: thumb_opcode = 0b1101; set_cc = true; rd = PC; break; 744 case CMN: thumb_opcode = 0b1000; set_cc = true; rd = PC; break; 745 case ORR: thumb_opcode = 0b0010; break; 746 case MOV: thumb_opcode = 0b0010; rn = PC; break; 747 case BIC: thumb_opcode = 0b0001; break; 748 case MVN: thumb_opcode = 0b0011; rn = PC; break; 749 default: 750 break; 751 } 752 753 if (thumb_opcode == 0b11111111) { 754 LOG(FATAL) << "Invalid thumb2 opcode " << opcode; 755 } 756 757 int32_t encoding = 0; 758 if (so.IsImmediate()) { 759 // Check special cases. 760 if ((opcode == SUB || opcode == ADD) && rn == SP) { 761 // There are special ADD/SUB rd, SP, #imm12 instructions. 762 if (opcode == SUB) { 763 thumb_opcode = 0b0101; 764 } else { 765 thumb_opcode = 0; 766 } 767 uint32_t imm = so.GetImmediate(); 768 CHECK_LT(imm, (1u << 12)); 769 770 uint32_t i = (imm >> 11) & 1; 771 uint32_t imm3 = (imm >> 8) & 0b111; 772 uint32_t imm8 = imm & 0xff; 773 774 encoding = B31 | B30 | B29 | B28 | B25 | 775 B19 | B18 | B16 | 776 thumb_opcode << 21 | 777 rd << 8 | 778 i << 26 | 779 imm3 << 12 | 780 imm8; 781 } else { 782 // Modified immediate. 783 uint32_t imm = ModifiedImmediate(so.encodingThumb()); 784 if (imm == kInvalidModifiedImmediate) { 785 LOG(FATAL) << "Immediate value cannot fit in thumb2 modified immediate"; 786 } 787 encoding = B31 | B30 | B29 | B28 | 788 thumb_opcode << 21 | 789 set_cc << 20 | 790 rn << 16 | 791 rd << 8 | 792 imm; 793 } 794 } else if (so.IsRegister()) { 795 // Register (possibly shifted) 796 encoding = B31 | B30 | B29 | B27 | B25 | 797 thumb_opcode << 21 | 798 set_cc << 20 | 799 rn << 16 | 800 rd << 8 | 801 so.encodingThumb(); 802 } 803 Emit32(encoding); 804} 805 806 807void Thumb2Assembler::Emit16BitDataProcessing(Condition cond, 808 Opcode opcode, 809 int set_cc, 810 Register rn, 811 Register rd, 812 const ShifterOperand& so) { 813 if (opcode == ADD || opcode == SUB) { 814 Emit16BitAddSub(cond, opcode, set_cc, rn, rd, so); 815 return; 816 } 817 uint8_t thumb_opcode = 0b11111111; 818 // Thumb1. 819 uint8_t dp_opcode = 0b01; 820 uint8_t opcode_shift = 6; 821 uint8_t rd_shift = 0; 822 uint8_t rn_shift = 3; 823 uint8_t immediate_shift = 0; 824 bool use_immediate = false; 825 uint8_t immediate = 0; 826 827 if (opcode == MOV && so.IsRegister() && so.IsShift()) { 828 // Convert shifted mov operand2 into 16 bit opcodes. 829 dp_opcode = 0; 830 opcode_shift = 11; 831 832 use_immediate = true; 833 immediate = so.GetImmediate(); 834 immediate_shift = 6; 835 836 rn = so.GetRegister(); 837 838 switch (so.GetShift()) { 839 case LSL: thumb_opcode = 0b00; break; 840 case LSR: thumb_opcode = 0b01; break; 841 case ASR: thumb_opcode = 0b10; break; 842 case ROR: 843 // ROR doesn't allow immediates. 844 thumb_opcode = 0b111; 845 dp_opcode = 0b01; 846 opcode_shift = 6; 847 use_immediate = false; 848 break; 849 case RRX: break; 850 default: 851 break; 852 } 853 } else { 854 if (so.IsImmediate()) { 855 use_immediate = true; 856 immediate = so.GetImmediate(); 857 } 858 859 switch (opcode) { 860 case AND: thumb_opcode = 0b0000; break; 861 case EOR: thumb_opcode = 0b0001; break; 862 case SUB: break; 863 case RSB: thumb_opcode = 0b1001; break; 864 case ADD: break; 865 case ADC: thumb_opcode = 0b0101; break; 866 case SBC: thumb_opcode = 0b0110; break; 867 case RSC: break; 868 case TST: thumb_opcode = 0b1000; rn = so.GetRegister(); break; 869 case TEQ: break; 870 case CMP: 871 if (use_immediate) { 872 // T2 encoding. 873 dp_opcode = 0; 874 opcode_shift = 11; 875 thumb_opcode = 0b101; 876 rd_shift = 8; 877 rn_shift = 8; 878 } else { 879 thumb_opcode = 0b1010; 880 rd = rn; 881 rn = so.GetRegister(); 882 } 883 884 break; 885 case CMN: thumb_opcode = 0b1011; rn = so.GetRegister(); break; 886 case ORR: thumb_opcode = 0b1100; break; 887 case MOV: 888 dp_opcode = 0; 889 if (use_immediate) { 890 // T2 encoding. 891 opcode_shift = 11; 892 thumb_opcode = 0b100; 893 rd_shift = 8; 894 rn_shift = 8; 895 } else { 896 rn = so.GetRegister(); 897 if (IsHighRegister(rn) || IsHighRegister(rd)) { 898 // Special mov for high registers. 899 dp_opcode = 0b01; 900 opcode_shift = 7; 901 // Put the top bit of rd into the bottom bit of the opcode. 902 thumb_opcode = 0b0001100 | static_cast<uint32_t>(rd) >> 3; 903 rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111); 904 } else { 905 thumb_opcode = 0; 906 } 907 } 908 break; 909 case BIC: thumb_opcode = 0b1110; break; 910 case MVN: thumb_opcode = 0b1111; rn = so.GetRegister(); break; 911 default: 912 break; 913 } 914 } 915 916 if (thumb_opcode == 0b11111111) { 917 LOG(FATAL) << "Invalid thumb1 opcode " << opcode; 918 } 919 920 int16_t encoding = dp_opcode << 14 | 921 (thumb_opcode << opcode_shift) | 922 rd << rd_shift | 923 rn << rn_shift | 924 (use_immediate ? (immediate << immediate_shift) : 0); 925 926 Emit16(encoding); 927} 928 929 930// ADD and SUB are complex enough to warrant their own emitter. 931void Thumb2Assembler::Emit16BitAddSub(Condition cond, 932 Opcode opcode, 933 int set_cc, 934 Register rn, 935 Register rd, 936 const ShifterOperand& so) { 937 uint8_t dp_opcode = 0; 938 uint8_t opcode_shift = 6; 939 uint8_t rd_shift = 0; 940 uint8_t rn_shift = 3; 941 uint8_t immediate_shift = 0; 942 bool use_immediate = false; 943 uint8_t immediate = 0; 944 uint8_t thumb_opcode;; 945 946 if (so.IsImmediate()) { 947 use_immediate = true; 948 immediate = so.GetImmediate(); 949 } 950 951 switch (opcode) { 952 case ADD: 953 if (so.IsRegister()) { 954 Register rm = so.GetRegister(); 955 if (rn == rd) { 956 // Can use T2 encoding (allows 4 bit registers) 957 dp_opcode = 0b01; 958 opcode_shift = 10; 959 thumb_opcode = 0b0001; 960 // Make Rn also contain the top bit of rd. 961 rn = static_cast<Register>(static_cast<uint32_t>(rm) | 962 (static_cast<uint32_t>(rd) & 0b1000) << 1); 963 rd = static_cast<Register>(static_cast<uint32_t>(rd) & 0b111); 964 } else { 965 // T1. 966 opcode_shift = 9; 967 thumb_opcode = 0b01100; 968 immediate = static_cast<uint32_t>(so.GetRegister()); 969 use_immediate = true; 970 immediate_shift = 6; 971 } 972 } else { 973 // Immediate. 974 if (rd == SP && rn == SP) { 975 // ADD sp, sp, #imm 976 dp_opcode = 0b10; 977 thumb_opcode = 0b11; 978 opcode_shift = 12; 979 CHECK_LT(immediate, (1 << 9)); 980 CHECK_EQ((immediate & 0b11), 0); 981 982 // Remove rd and rn from instruction by orring it with immed and clearing bits. 983 rn = R0; 984 rd = R0; 985 rd_shift = 0; 986 rn_shift = 0; 987 immediate >>= 2; 988 } else if (rd != SP && rn == SP) { 989 // ADD rd, SP, #imm 990 dp_opcode = 0b10; 991 thumb_opcode = 0b101; 992 opcode_shift = 11; 993 CHECK_LT(immediate, (1 << 10)); 994 CHECK_EQ((immediate & 0b11), 0); 995 996 // Remove rn from instruction. 997 rn = R0; 998 rn_shift = 0; 999 rd_shift = 8; 1000 immediate >>= 2; 1001 } else if (rn != rd) { 1002 // Must use T1. 1003 opcode_shift = 9; 1004 thumb_opcode = 0b01110; 1005 immediate_shift = 6; 1006 } else { 1007 // T2 encoding. 1008 opcode_shift = 11; 1009 thumb_opcode = 0b110; 1010 rd_shift = 8; 1011 rn_shift = 8; 1012 } 1013 } 1014 break; 1015 1016 case SUB: 1017 if (so.IsRegister()) { 1018 // T1. 1019 opcode_shift = 9; 1020 thumb_opcode = 0b01101; 1021 immediate = static_cast<uint32_t>(so.GetRegister()); 1022 use_immediate = true; 1023 immediate_shift = 6; 1024 } else { 1025 if (rd == SP && rn == SP) { 1026 // SUB sp, sp, #imm 1027 dp_opcode = 0b10; 1028 thumb_opcode = 0b1100001; 1029 opcode_shift = 7; 1030 CHECK_LT(immediate, (1 << 9)); 1031 CHECK_EQ((immediate & 0b11), 0); 1032 1033 // Remove rd and rn from instruction by orring it with immed and clearing bits. 1034 rn = R0; 1035 rd = R0; 1036 rd_shift = 0; 1037 rn_shift = 0; 1038 immediate >>= 2; 1039 } else if (rn != rd) { 1040 // Must use T1. 1041 opcode_shift = 9; 1042 thumb_opcode = 0b01111; 1043 immediate_shift = 6; 1044 } else { 1045 // T2 encoding. 1046 opcode_shift = 11; 1047 thumb_opcode = 0b111; 1048 rd_shift = 8; 1049 rn_shift = 8; 1050 } 1051 } 1052 break; 1053 default: 1054 LOG(FATAL) << "This opcode is not an ADD or SUB: " << opcode; 1055 return; 1056 } 1057 1058 int16_t encoding = dp_opcode << 14 | 1059 (thumb_opcode << opcode_shift) | 1060 rd << rd_shift | 1061 rn << rn_shift | 1062 (use_immediate ? (immediate << immediate_shift) : 0); 1063 1064 Emit16(encoding); 1065} 1066 1067 1068void Thumb2Assembler::EmitDataProcessing(Condition cond, 1069 Opcode opcode, 1070 int set_cc, 1071 Register rn, 1072 Register rd, 1073 const ShifterOperand& so) { 1074 CHECK_NE(rd, kNoRegister); 1075 CheckCondition(cond); 1076 1077 if (Is32BitDataProcessing(cond, opcode, set_cc, rn, rd, so)) { 1078 Emit32BitDataProcessing(cond, opcode, set_cc, rn, rd, so); 1079 } else { 1080 Emit16BitDataProcessing(cond, opcode, set_cc, rn, rd, so); 1081 } 1082} 1083 1084void Thumb2Assembler::EmitShift(Register rd, Register rm, Shift shift, uint8_t amount, bool setcc) { 1085 CHECK_LT(amount, (1 << 5)); 1086 if (IsHighRegister(rd) || IsHighRegister(rm) || shift == ROR || shift == RRX) { 1087 uint16_t opcode = 0; 1088 switch (shift) { 1089 case LSL: opcode = 0b00; break; 1090 case LSR: opcode = 0b01; break; 1091 case ASR: opcode = 0b10; break; 1092 case ROR: opcode = 0b11; break; 1093 case RRX: opcode = 0b11; amount = 0; break; 1094 default: 1095 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1096 } 1097 // 32 bit. 1098 int32_t encoding = B31 | B30 | B29 | B27 | B25 | B22 | 1099 0xf << 16 | (setcc ? B20 : 0); 1100 uint32_t imm3 = amount >> 2; 1101 uint32_t imm2 = amount & 0b11; 1102 encoding |= imm3 << 12 | imm2 << 6 | static_cast<int16_t>(rm) | 1103 static_cast<int16_t>(rd) << 8 | opcode << 4; 1104 Emit32(encoding); 1105 } else { 1106 // 16 bit shift 1107 uint16_t opcode = 0; 1108 switch (shift) { 1109 case LSL: opcode = 0b00; break; 1110 case LSR: opcode = 0b01; break; 1111 case ASR: opcode = 0b10; break; 1112 default: 1113 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1114 } 1115 int16_t encoding = opcode << 11 | amount << 6 | static_cast<int16_t>(rm) << 3 | 1116 static_cast<int16_t>(rd); 1117 Emit16(encoding); 1118 } 1119} 1120 1121void Thumb2Assembler::EmitShift(Register rd, Register rn, Shift shift, Register rm, bool setcc) { 1122 CHECK_NE(shift, RRX); 1123 bool must_be_32bit = false; 1124 if (IsHighRegister(rd) || IsHighRegister(rm) || IsHighRegister(rn) || rd != rn) { 1125 must_be_32bit = true; 1126 } 1127 1128 if (must_be_32bit) { 1129 uint16_t opcode = 0; 1130 switch (shift) { 1131 case LSL: opcode = 0b00; break; 1132 case LSR: opcode = 0b01; break; 1133 case ASR: opcode = 0b10; break; 1134 case ROR: opcode = 0b11; break; 1135 default: 1136 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1137 } 1138 // 32 bit. 1139 int32_t encoding = B31 | B30 | B29 | B28 | B27 | B25 | 1140 0xf << 12 | (setcc ? B20 : 0); 1141 encoding |= static_cast<int16_t>(rn) << 16 | static_cast<int16_t>(rm) | 1142 static_cast<int16_t>(rd) << 8 | opcode << 21; 1143 Emit32(encoding); 1144 } else { 1145 uint16_t opcode = 0; 1146 switch (shift) { 1147 case LSL: opcode = 0b0010; break; 1148 case LSR: opcode = 0b0011; break; 1149 case ASR: opcode = 0b0100; break; 1150 default: 1151 LOG(FATAL) << "Unsupported thumb2 shift opcode"; 1152 } 1153 int16_t encoding = B14 | opcode << 6 | static_cast<int16_t>(rm) << 3 | 1154 static_cast<int16_t>(rd); 1155 Emit16(encoding); 1156 } 1157} 1158 1159 1160 1161void Thumb2Assembler::Branch::Emit(AssemblerBuffer* buffer) const { 1162 bool link = type_ == kUnconditionalLinkX || type_ == kUnconditionalLink; 1163 bool x = type_ == kUnconditionalX || type_ == kUnconditionalLinkX; 1164 int32_t offset = target_ - location_; 1165 1166 if (size_ == k32Bit) { 1167 int32_t encoding = B31 | B30 | B29 | B28 | B15; 1168 if (link) { 1169 // BL or BLX immediate. 1170 encoding |= B14; 1171 if (!x) { 1172 encoding |= B12; 1173 } else { 1174 // Bottom bit of offset must be 0. 1175 CHECK_EQ((offset & 1), 0); 1176 } 1177 } else { 1178 if (x) { 1179 LOG(FATAL) << "Invalid use of BX"; 1180 } else { 1181 if (cond_ == AL) { 1182 // Can use the T4 encoding allowing a 24 bit offset. 1183 if (!x) { 1184 encoding |= B12; 1185 } 1186 } else { 1187 // Must be T3 encoding with a 20 bit offset. 1188 encoding |= cond_ << 22; 1189 } 1190 } 1191 } 1192 encoding = Thumb2Assembler::EncodeBranchOffset(offset, encoding); 1193 buffer->Store<int16_t>(location_, static_cast<int16_t>(encoding >> 16)); 1194 buffer->Store<int16_t>(location_+2, static_cast<int16_t>(encoding & 0xffff)); 1195 } else { 1196 if (IsCompareAndBranch()) { 1197 offset -= 4; 1198 uint16_t i = (offset >> 6) & 1; 1199 uint16_t imm5 = (offset >> 1) & 0b11111; 1200 int16_t encoding = B15 | B13 | B12 | 1201 (type_ == kCompareAndBranchNonZero ? B11 : 0) | 1202 static_cast<uint32_t>(rn_) | 1203 B8 | 1204 i << 9 | 1205 imm5 << 3; 1206 buffer->Store<int16_t>(location_, encoding); 1207 } else { 1208 offset -= 4; // Account for PC offset. 1209 int16_t encoding; 1210 // 16 bit. 1211 if (cond_ == AL) { 1212 encoding = B15 | B14 | B13 | 1213 ((offset >> 1) & 0x7ff); 1214 } else { 1215 encoding = B15 | B14 | B12 | 1216 cond_ << 8 | ((offset >> 1) & 0xff); 1217 } 1218 buffer->Store<int16_t>(location_, encoding); 1219 } 1220 } 1221} 1222 1223 1224uint16_t Thumb2Assembler::EmitCompareAndBranch(Register rn, uint16_t prev, bool n) { 1225 uint32_t location = buffer_.Size(); 1226 1227 // This is always unresolved as it must be a forward branch. 1228 Emit16(prev); // Previous link. 1229 return AddBranch(n ? Branch::kCompareAndBranchNonZero : Branch::kCompareAndBranchZero, 1230 location, rn); 1231} 1232 1233 1234// NOTE: this only support immediate offsets, not [rx,ry]. 1235// TODO: support [rx,ry] instructions. 1236void Thumb2Assembler::EmitLoadStore(Condition cond, 1237 bool load, 1238 bool byte, 1239 bool half, 1240 bool is_signed, 1241 Register rd, 1242 const Address& ad) { 1243 CHECK_NE(rd, kNoRegister); 1244 CheckCondition(cond); 1245 bool must_be_32bit = force_32bit_; 1246 if (IsHighRegister(rd)) { 1247 must_be_32bit = true; 1248 } 1249 1250 Register rn = ad.GetRegister(); 1251 if (IsHighRegister(rn) && rn != SP && rn != PC) { 1252 must_be_32bit = true; 1253 } 1254 1255 if (is_signed || ad.GetOffset() < 0 || ad.GetMode() != Address::Offset) { 1256 must_be_32bit = true; 1257 } 1258 1259 if (ad.IsImmediate()) { 1260 // Immediate offset 1261 int32_t offset = ad.GetOffset(); 1262 1263 // The 16 bit SP relative instruction can only have a 10 bit offset. 1264 if (rn == SP && offset >= (1 << 10)) { 1265 must_be_32bit = true; 1266 } 1267 1268 if (byte) { 1269 // 5 bit offset, no shift. 1270 if (offset >= (1 << 5)) { 1271 must_be_32bit = true; 1272 } 1273 } else if (half) { 1274 // 6 bit offset, shifted by 1. 1275 if (offset >= (1 << 6)) { 1276 must_be_32bit = true; 1277 } 1278 } else { 1279 // 7 bit offset, shifted by 2. 1280 if (offset >= (1 << 7)) { 1281 must_be_32bit = true; 1282 } 1283 } 1284 1285 if (must_be_32bit) { 1286 int32_t encoding = B31 | B30 | B29 | B28 | B27 | 1287 (load ? B20 : 0) | 1288 (is_signed ? B24 : 0) | 1289 static_cast<uint32_t>(rd) << 12 | 1290 ad.encodingThumb(true) | 1291 (byte ? 0 : half ? B21 : B22); 1292 Emit32(encoding); 1293 } else { 1294 // 16 bit thumb1. 1295 uint8_t opA = 0; 1296 bool sp_relative = false; 1297 1298 if (byte) { 1299 opA = 0b0111; 1300 } else if (half) { 1301 opA = 0b1000; 1302 } else { 1303 if (rn == SP) { 1304 opA = 0b1001; 1305 sp_relative = true; 1306 } else { 1307 opA = 0b0110; 1308 } 1309 } 1310 int16_t encoding = opA << 12 | 1311 (load ? B11 : 0); 1312 1313 CHECK_GE(offset, 0); 1314 if (sp_relative) { 1315 // SP relative, 10 bit offset. 1316 CHECK_LT(offset, (1 << 10)); 1317 CHECK_EQ((offset & 0b11), 0); 1318 encoding |= rd << 8 | offset >> 2; 1319 } else { 1320 // No SP relative. The offset is shifted right depending on 1321 // the size of the load/store. 1322 encoding |= static_cast<uint32_t>(rd); 1323 1324 if (byte) { 1325 // 5 bit offset, no shift. 1326 CHECK_LT(offset, (1 << 5)); 1327 } else if (half) { 1328 // 6 bit offset, shifted by 1. 1329 CHECK_LT(offset, (1 << 6)); 1330 CHECK_EQ((offset & 0b1), 0); 1331 offset >>= 1; 1332 } else { 1333 // 7 bit offset, shifted by 2. 1334 CHECK_LT(offset, (1 << 7)); 1335 CHECK_EQ((offset & 0b11), 0); 1336 offset >>= 2; 1337 } 1338 encoding |= rn << 3 | offset << 6; 1339 } 1340 1341 Emit16(encoding); 1342 } 1343 } else { 1344 // Register shift. 1345 if (ad.GetRegister() == PC) { 1346 // PC relative literal encoding. 1347 int32_t offset = ad.GetOffset(); 1348 if (must_be_32bit || offset < 0 || offset >= (1 << 10) || !load) { 1349 int32_t up = B23; 1350 if (offset < 0) { 1351 offset = -offset; 1352 up = 0; 1353 } 1354 CHECK_LT(offset, (1 << 12)); 1355 int32_t encoding = 0x1f << 27 | 0xf << 16 | B22 | (load ? B20 : 0) | 1356 offset | up | 1357 static_cast<uint32_t>(rd) << 12; 1358 Emit32(encoding); 1359 } else { 1360 // 16 bit literal load. 1361 CHECK_GE(offset, 0); 1362 CHECK_LT(offset, (1 << 10)); 1363 int32_t encoding = B14 | (load ? B11 : 0) | static_cast<uint32_t>(rd) << 8 | offset >> 2; 1364 Emit16(encoding); 1365 } 1366 } else { 1367 if (ad.GetShiftCount() != 0) { 1368 // If there is a shift count this must be 32 bit. 1369 must_be_32bit = true; 1370 } else if (IsHighRegister(ad.GetRegisterOffset())) { 1371 must_be_32bit = true; 1372 } 1373 1374 if (must_be_32bit) { 1375 int32_t encoding = 0x1f << 27 | B22 | (load ? B20 : 0) | static_cast<uint32_t>(rd) << 12 | 1376 ad.encodingThumb(true); 1377 Emit32(encoding); 1378 } else { 1379 // 16 bit register offset. 1380 int32_t encoding = B14 | B12 | (load ? B11 : 0) | static_cast<uint32_t>(rd) | 1381 ad.encodingThumb(false); 1382 Emit16(encoding); 1383 } 1384 } 1385 } 1386} 1387 1388 1389void Thumb2Assembler::EmitMultiMemOp(Condition cond, 1390 BlockAddressMode am, 1391 bool load, 1392 Register base, 1393 RegList regs) { 1394 CHECK_NE(base, kNoRegister); 1395 CheckCondition(cond); 1396 bool must_be_32bit = force_32bit_; 1397 1398 if ((regs & 0xff00) != 0) { 1399 must_be_32bit = true; 1400 } 1401 1402 uint32_t w_bit = am == IA_W || am == DB_W || am == DA_W || am == IB_W; 1403 // 16 bit always uses writeback. 1404 if (!w_bit) { 1405 must_be_32bit = true; 1406 } 1407 1408 if (must_be_32bit) { 1409 uint32_t op = 0; 1410 switch (am) { 1411 case IA: 1412 case IA_W: 1413 op = 0b01; 1414 break; 1415 case DB: 1416 case DB_W: 1417 op = 0b10; 1418 break; 1419 case DA: 1420 case IB: 1421 case DA_W: 1422 case IB_W: 1423 LOG(FATAL) << "LDM/STM mode not supported on thumb: " << am; 1424 } 1425 if (load) { 1426 // Cannot have SP in the list. 1427 CHECK_EQ((regs & (1 << SP)), 0); 1428 } else { 1429 // Cannot have PC or SP in the list. 1430 CHECK_EQ((regs & (1 << PC | 1 << SP)), 0); 1431 } 1432 int32_t encoding = B31 | B30 | B29 | B27 | 1433 (op << 23) | 1434 (load ? B20 : 0) | 1435 base << 16 | 1436 regs | 1437 (w_bit << 21); 1438 Emit32(encoding); 1439 } else { 1440 int16_t encoding = B15 | B14 | 1441 (load ? B11 : 0) | 1442 base << 8 | 1443 regs; 1444 Emit16(encoding); 1445 } 1446} 1447 1448 1449void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x) { 1450 uint32_t pc = buffer_.Size(); 1451 Branch::Type branch_type; 1452 if (cond == AL) { 1453 if (link) { 1454 if (x) { 1455 branch_type = Branch::kUnconditionalLinkX; // BLX. 1456 } else { 1457 branch_type = Branch::kUnconditionalLink; // BX. 1458 } 1459 } else { 1460 branch_type = Branch::kUnconditional; // B. 1461 } 1462 } else { 1463 branch_type = Branch::kConditional; // B<cond>. 1464 } 1465 1466 if (label->IsBound()) { 1467 Branch::Size size = AddBranch(branch_type, pc, label->Position(), cond); // Resolved branch. 1468 1469 // The branch is to a bound label which means that it's a backwards branch. We know the 1470 // current size of it so we can emit the appropriate space. Note that if it's a 16 bit 1471 // branch the size may change if it so happens that other branches change size that change 1472 // the distance to the target and that distance puts this branch over the limit for 16 bits. 1473 if (size == Branch::k16Bit) { 1474 DCHECK(!force_32bit_branches_); 1475 Emit16(0); // Space for a 16 bit branch. 1476 } else { 1477 Emit32(0); // Space for a 32 bit branch. 1478 } 1479 } else { 1480 // Branch is to an unbound label. Emit space for it. 1481 uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch. 1482 if (force_32bit_branches_ || force_32bit_) { 1483 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1484 Emit16(0); // another 16 bits. 1485 } else { 1486 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1487 } 1488 label->LinkTo(branch_id); // Link to the branch ID. 1489 } 1490} 1491 1492 1493void Thumb2Assembler::clz(Register rd, Register rm, Condition cond) { 1494 CHECK_NE(rd, kNoRegister); 1495 CHECK_NE(rm, kNoRegister); 1496 CheckCondition(cond); 1497 CHECK_NE(rd, PC); 1498 CHECK_NE(rm, PC); 1499 int32_t encoding = B31 | B30 | B29 | B28 | B27 | 1500 B25 | B23 | B21 | B20 | 1501 static_cast<uint32_t>(rm) << 16 | 1502 0xf << 12 | 1503 static_cast<uint32_t>(rd) << 8 | 1504 B7 | 1505 static_cast<uint32_t>(rm); 1506 Emit32(encoding); 1507} 1508 1509 1510void Thumb2Assembler::movw(Register rd, uint16_t imm16, Condition cond) { 1511 CheckCondition(cond); 1512 bool must_be_32bit = force_32bit_; 1513 if (IsHighRegister(rd)|| imm16 >= 256u) { 1514 must_be_32bit = true; 1515 } 1516 1517 if (must_be_32bit) { 1518 // Use encoding T3. 1519 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1520 uint32_t i = (imm16 >> 11) & 0b1; 1521 uint32_t imm3 = (imm16 >> 8) & 0b111; 1522 uint32_t imm8 = imm16 & 0xff; 1523 int32_t encoding = B31 | B30 | B29 | B28 | 1524 B25 | B22 | 1525 static_cast<uint32_t>(rd) << 8 | 1526 i << 26 | 1527 imm4 << 16 | 1528 imm3 << 12 | 1529 imm8; 1530 Emit32(encoding); 1531 } else { 1532 int16_t encoding = B13 | static_cast<uint16_t>(rd) << 8 | 1533 imm16; 1534 Emit16(encoding); 1535 } 1536} 1537 1538 1539void Thumb2Assembler::movt(Register rd, uint16_t imm16, Condition cond) { 1540 CheckCondition(cond); 1541 // Always 32 bits. 1542 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1543 uint32_t i = (imm16 >> 11) & 0b1; 1544 uint32_t imm3 = (imm16 >> 8) & 0b111; 1545 uint32_t imm8 = imm16 & 0xff; 1546 int32_t encoding = B31 | B30 | B29 | B28 | 1547 B25 | B23 | B22 | 1548 static_cast<uint32_t>(rd) << 8 | 1549 i << 26 | 1550 imm4 << 16 | 1551 imm3 << 12 | 1552 imm8; 1553 Emit32(encoding); 1554} 1555 1556 1557void Thumb2Assembler::ldrex(Register rt, Register rn, uint16_t imm, Condition cond) { 1558 CHECK_NE(rn, kNoRegister); 1559 CHECK_NE(rt, kNoRegister); 1560 CheckCondition(cond); 1561 CHECK_NE(rn, kNoRegister); 1562 CHECK_NE(rt, kNoRegister); 1563 CheckCondition(cond); 1564 CHECK_LT(imm, (1u << 10)); 1565 1566 int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 | 1567 static_cast<uint32_t>(rn) << 16 | 1568 static_cast<uint32_t>(rt) << 12 | 1569 0xf << 8 | 1570 imm >> 2; 1571 Emit32(encoding); 1572} 1573 1574 1575void Thumb2Assembler::ldrex(Register rt, Register rn, Condition cond) { 1576 ldrex(rt, rn, 0, cond); 1577} 1578 1579 1580void Thumb2Assembler::strex(Register rd, 1581 Register rt, 1582 Register rn, 1583 uint16_t imm, 1584 Condition cond) { 1585 CHECK_NE(rn, kNoRegister); 1586 CHECK_NE(rd, kNoRegister); 1587 CHECK_NE(rt, kNoRegister); 1588 CheckCondition(cond); 1589 CHECK_LT(imm, (1u << 10)); 1590 1591 int32_t encoding = B31 | B30 | B29 | B27 | B22 | 1592 static_cast<uint32_t>(rn) << 16 | 1593 static_cast<uint32_t>(rt) << 12 | 1594 static_cast<uint32_t>(rd) << 8 | 1595 imm >> 2; 1596 Emit32(encoding); 1597} 1598 1599 1600void Thumb2Assembler::strex(Register rd, 1601 Register rt, 1602 Register rn, 1603 Condition cond) { 1604 strex(rd, rt, rn, 0, cond); 1605} 1606 1607 1608void Thumb2Assembler::clrex(Condition cond) { 1609 CheckCondition(cond); 1610 int32_t encoding = B31 | B30 | B29 | B27 | B28 | B25 | B24 | B23 | 1611 B21 | B20 | 1612 0xf << 16 | 1613 B15 | 1614 0xf << 8 | 1615 B5 | 1616 0xf; 1617 Emit32(encoding); 1618} 1619 1620 1621void Thumb2Assembler::nop(Condition cond) { 1622 CheckCondition(cond); 1623 int16_t encoding = B15 | B13 | B12 | 1624 B11 | B10 | B9 | B8; 1625 Emit16(encoding); 1626} 1627 1628 1629void Thumb2Assembler::vmovsr(SRegister sn, Register rt, Condition cond) { 1630 CHECK_NE(sn, kNoSRegister); 1631 CHECK_NE(rt, kNoRegister); 1632 CHECK_NE(rt, SP); 1633 CHECK_NE(rt, PC); 1634 CheckCondition(cond); 1635 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1636 B27 | B26 | B25 | 1637 ((static_cast<int32_t>(sn) >> 1)*B16) | 1638 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1639 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1640 Emit32(encoding); 1641} 1642 1643 1644void Thumb2Assembler::vmovrs(Register rt, SRegister sn, Condition cond) { 1645 CHECK_NE(sn, kNoSRegister); 1646 CHECK_NE(rt, kNoRegister); 1647 CHECK_NE(rt, SP); 1648 CHECK_NE(rt, PC); 1649 CheckCondition(cond); 1650 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1651 B27 | B26 | B25 | B20 | 1652 ((static_cast<int32_t>(sn) >> 1)*B16) | 1653 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1654 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1655 Emit32(encoding); 1656} 1657 1658 1659void Thumb2Assembler::vmovsrr(SRegister sm, Register rt, Register rt2, 1660 Condition cond) { 1661 CHECK_NE(sm, kNoSRegister); 1662 CHECK_NE(sm, S31); 1663 CHECK_NE(rt, kNoRegister); 1664 CHECK_NE(rt, SP); 1665 CHECK_NE(rt, PC); 1666 CHECK_NE(rt2, kNoRegister); 1667 CHECK_NE(rt2, SP); 1668 CHECK_NE(rt2, PC); 1669 CheckCondition(cond); 1670 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1671 B27 | B26 | B22 | 1672 (static_cast<int32_t>(rt2)*B16) | 1673 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1674 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1675 (static_cast<int32_t>(sm) >> 1); 1676 Emit32(encoding); 1677} 1678 1679 1680void Thumb2Assembler::vmovrrs(Register rt, Register rt2, SRegister sm, 1681 Condition cond) { 1682 CHECK_NE(sm, kNoSRegister); 1683 CHECK_NE(sm, S31); 1684 CHECK_NE(rt, kNoRegister); 1685 CHECK_NE(rt, SP); 1686 CHECK_NE(rt, PC); 1687 CHECK_NE(rt2, kNoRegister); 1688 CHECK_NE(rt2, SP); 1689 CHECK_NE(rt2, PC); 1690 CHECK_NE(rt, rt2); 1691 CheckCondition(cond); 1692 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1693 B27 | B26 | B22 | B20 | 1694 (static_cast<int32_t>(rt2)*B16) | 1695 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1696 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1697 (static_cast<int32_t>(sm) >> 1); 1698 Emit32(encoding); 1699} 1700 1701 1702void Thumb2Assembler::vmovdrr(DRegister dm, Register rt, Register rt2, 1703 Condition cond) { 1704 CHECK_NE(dm, kNoDRegister); 1705 CHECK_NE(rt, kNoRegister); 1706 CHECK_NE(rt, SP); 1707 CHECK_NE(rt, PC); 1708 CHECK_NE(rt2, kNoRegister); 1709 CHECK_NE(rt2, SP); 1710 CHECK_NE(rt2, PC); 1711 CheckCondition(cond); 1712 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1713 B27 | B26 | B22 | 1714 (static_cast<int32_t>(rt2)*B16) | 1715 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1716 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1717 (static_cast<int32_t>(dm) & 0xf); 1718 Emit32(encoding); 1719} 1720 1721 1722void Thumb2Assembler::vmovrrd(Register rt, Register rt2, DRegister dm, 1723 Condition cond) { 1724 CHECK_NE(dm, kNoDRegister); 1725 CHECK_NE(rt, kNoRegister); 1726 CHECK_NE(rt, SP); 1727 CHECK_NE(rt, PC); 1728 CHECK_NE(rt2, kNoRegister); 1729 CHECK_NE(rt2, SP); 1730 CHECK_NE(rt2, PC); 1731 CHECK_NE(rt, rt2); 1732 CheckCondition(cond); 1733 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1734 B27 | B26 | B22 | B20 | 1735 (static_cast<int32_t>(rt2)*B16) | 1736 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1737 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1738 (static_cast<int32_t>(dm) & 0xf); 1739 Emit32(encoding); 1740} 1741 1742 1743void Thumb2Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) { 1744 const Address& addr = static_cast<const Address&>(ad); 1745 CHECK_NE(sd, kNoSRegister); 1746 CheckCondition(cond); 1747 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1748 B27 | B26 | B24 | B20 | 1749 ((static_cast<int32_t>(sd) & 1)*B22) | 1750 ((static_cast<int32_t>(sd) >> 1)*B12) | 1751 B11 | B9 | addr.vencoding(); 1752 Emit32(encoding); 1753} 1754 1755 1756void Thumb2Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) { 1757 const Address& addr = static_cast<const Address&>(ad); 1758 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1759 CHECK_NE(sd, kNoSRegister); 1760 CheckCondition(cond); 1761 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1762 B27 | B26 | B24 | 1763 ((static_cast<int32_t>(sd) & 1)*B22) | 1764 ((static_cast<int32_t>(sd) >> 1)*B12) | 1765 B11 | B9 | addr.vencoding(); 1766 Emit32(encoding); 1767} 1768 1769 1770void Thumb2Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) { 1771 const Address& addr = static_cast<const Address&>(ad); 1772 CHECK_NE(dd, kNoDRegister); 1773 CheckCondition(cond); 1774 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1775 B27 | B26 | B24 | B20 | 1776 ((static_cast<int32_t>(dd) >> 4)*B22) | 1777 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1778 B11 | B9 | B8 | addr.vencoding(); 1779 Emit32(encoding); 1780} 1781 1782 1783void Thumb2Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) { 1784 const Address& addr = static_cast<const Address&>(ad); 1785 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1786 CHECK_NE(dd, kNoDRegister); 1787 CheckCondition(cond); 1788 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1789 B27 | B26 | B24 | 1790 ((static_cast<int32_t>(dd) >> 4)*B22) | 1791 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1792 B11 | B9 | B8 | addr.vencoding(); 1793 Emit32(encoding); 1794} 1795 1796 1797void Thumb2Assembler::vpushs(SRegister reg, int nregs, Condition cond) { 1798 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond); 1799} 1800 1801 1802void Thumb2Assembler::vpushd(DRegister reg, int nregs, Condition cond) { 1803 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond); 1804} 1805 1806 1807void Thumb2Assembler::vpops(SRegister reg, int nregs, Condition cond) { 1808 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond); 1809} 1810 1811 1812void Thumb2Assembler::vpopd(DRegister reg, int nregs, Condition cond) { 1813 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond); 1814} 1815 1816 1817void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) { 1818 CheckCondition(cond); 1819 1820 uint32_t D; 1821 uint32_t Vd; 1822 if (dbl) { 1823 // Encoded as D:Vd. 1824 D = (reg >> 4) & 1; 1825 Vd = reg & 0b1111; 1826 } else { 1827 // Encoded as Vd:D. 1828 D = reg & 1; 1829 Vd = (reg >> 1) & 0b1111; 1830 } 1831 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 | 1832 B11 | B9 | 1833 (dbl ? B8 : 0) | 1834 (push ? B24 : (B23 | B20)) | 1835 0b1110 << 28 | 1836 nregs << (dbl ? 1 : 0) | 1837 D << 22 | 1838 Vd << 12; 1839 Emit32(encoding); 1840} 1841 1842 1843void Thumb2Assembler::EmitVFPsss(Condition cond, int32_t opcode, 1844 SRegister sd, SRegister sn, SRegister sm) { 1845 CHECK_NE(sd, kNoSRegister); 1846 CHECK_NE(sn, kNoSRegister); 1847 CHECK_NE(sm, kNoSRegister); 1848 CheckCondition(cond); 1849 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1850 B27 | B26 | B25 | B11 | B9 | opcode | 1851 ((static_cast<int32_t>(sd) & 1)*B22) | 1852 ((static_cast<int32_t>(sn) >> 1)*B16) | 1853 ((static_cast<int32_t>(sd) >> 1)*B12) | 1854 ((static_cast<int32_t>(sn) & 1)*B7) | 1855 ((static_cast<int32_t>(sm) & 1)*B5) | 1856 (static_cast<int32_t>(sm) >> 1); 1857 Emit32(encoding); 1858} 1859 1860 1861void Thumb2Assembler::EmitVFPddd(Condition cond, int32_t opcode, 1862 DRegister dd, DRegister dn, DRegister dm) { 1863 CHECK_NE(dd, kNoDRegister); 1864 CHECK_NE(dn, kNoDRegister); 1865 CHECK_NE(dm, kNoDRegister); 1866 CheckCondition(cond); 1867 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1868 B27 | B26 | B25 | B11 | B9 | B8 | opcode | 1869 ((static_cast<int32_t>(dd) >> 4)*B22) | 1870 ((static_cast<int32_t>(dn) & 0xf)*B16) | 1871 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1872 ((static_cast<int32_t>(dn) >> 4)*B7) | 1873 ((static_cast<int32_t>(dm) >> 4)*B5) | 1874 (static_cast<int32_t>(dm) & 0xf); 1875 Emit32(encoding); 1876} 1877 1878 1879void Thumb2Assembler::EmitVFPsd(Condition cond, int32_t opcode, 1880 SRegister sd, DRegister dm) { 1881 CHECK_NE(sd, kNoSRegister); 1882 CHECK_NE(dm, kNoDRegister); 1883 CheckCondition(cond); 1884 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1885 B27 | B26 | B25 | B11 | B9 | opcode | 1886 ((static_cast<int32_t>(sd) & 1)*B22) | 1887 ((static_cast<int32_t>(sd) >> 1)*B12) | 1888 ((static_cast<int32_t>(dm) >> 4)*B5) | 1889 (static_cast<int32_t>(dm) & 0xf); 1890 Emit32(encoding); 1891} 1892 1893 1894void Thumb2Assembler::EmitVFPds(Condition cond, int32_t opcode, 1895 DRegister dd, SRegister sm) { 1896 CHECK_NE(dd, kNoDRegister); 1897 CHECK_NE(sm, kNoSRegister); 1898 CheckCondition(cond); 1899 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1900 B27 | B26 | B25 | B11 | B9 | opcode | 1901 ((static_cast<int32_t>(dd) >> 4)*B22) | 1902 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1903 ((static_cast<int32_t>(sm) & 1)*B5) | 1904 (static_cast<int32_t>(sm) >> 1); 1905 Emit32(encoding); 1906} 1907 1908 1909void Thumb2Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR. 1910 CheckCondition(cond); 1911 UNIMPLEMENTED(FATAL) << "Unimplemented thumb instruction"; 1912} 1913 1914 1915void Thumb2Assembler::svc(uint32_t imm8) { 1916 CHECK(IsUint(8, imm8)) << imm8; 1917 int16_t encoding = B15 | B14 | B12 | 1918 B11 | B10 | B9 | B8 | 1919 imm8; 1920 Emit16(encoding); 1921} 1922 1923 1924void Thumb2Assembler::bkpt(uint16_t imm8) { 1925 CHECK(IsUint(8, imm8)) << imm8; 1926 int16_t encoding = B15 | B13 | B12 | 1927 B11 | B10 | B9 | 1928 imm8; 1929 Emit16(encoding); 1930} 1931 1932// Convert the given IT state to a mask bit given bit 0 of the first 1933// condition and a shift position. 1934static uint8_t ToItMask(ItState s, uint8_t firstcond0, uint8_t shift) { 1935 switch (s) { 1936 case kItOmitted: return 1 << shift; 1937 case kItThen: return firstcond0 << shift; 1938 case kItElse: return !firstcond0 << shift; 1939 } 1940 return 0; 1941} 1942 1943 1944// Set the IT condition in the given position for the given state. This is used 1945// to check that conditional instructions match the preceding IT statement. 1946void Thumb2Assembler::SetItCondition(ItState s, Condition cond, uint8_t index) { 1947 switch (s) { 1948 case kItOmitted: it_conditions_[index] = AL; break; 1949 case kItThen: it_conditions_[index] = cond; break; 1950 case kItElse: 1951 it_conditions_[index] = static_cast<Condition>(static_cast<uint8_t>(cond) ^ 1); 1952 break; 1953 } 1954} 1955 1956 1957void Thumb2Assembler::it(Condition firstcond, ItState i1, ItState i2, ItState i3) { 1958 CheckCondition(AL); // Not allowed in IT block. 1959 uint8_t firstcond0 = static_cast<uint8_t>(firstcond) & 1; 1960 1961 // All conditions to AL. 1962 for (uint8_t i = 0; i < 4; ++i) { 1963 it_conditions_[i] = AL; 1964 } 1965 1966 SetItCondition(kItThen, firstcond, 0); 1967 uint8_t mask = ToItMask(i1, firstcond0, 3); 1968 SetItCondition(i1, firstcond, 1); 1969 1970 if (i1 != kItOmitted) { 1971 mask |= ToItMask(i2, firstcond0, 2); 1972 SetItCondition(i2, firstcond, 2); 1973 if (i2 != kItOmitted) { 1974 mask |= ToItMask(i3, firstcond0, 1); 1975 SetItCondition(i3, firstcond, 3); 1976 if (i3 != kItOmitted) { 1977 mask |= 0b0001; 1978 } 1979 } 1980 } 1981 1982 // Start at first condition. 1983 it_cond_index_ = 0; 1984 next_condition_ = it_conditions_[0]; 1985 uint16_t encoding = B15 | B13 | B12 | 1986 B11 | B10 | B9 | B8 | 1987 firstcond << 4 | 1988 mask; 1989 Emit16(encoding); 1990} 1991 1992 1993void Thumb2Assembler::cbz(Register rn, Label* label) { 1994 CheckCondition(AL); 1995 if (label->IsBound()) { 1996 LOG(FATAL) << "cbz can only be used to branch forwards"; 1997 } else { 1998 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), false); 1999 label->LinkTo(branchid); 2000 } 2001} 2002 2003 2004void Thumb2Assembler::cbnz(Register rn, Label* label) { 2005 CheckCondition(AL); 2006 if (label->IsBound()) { 2007 LOG(FATAL) << "cbnz can only be used to branch forwards"; 2008 } else { 2009 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), true); 2010 label->LinkTo(branchid); 2011 } 2012} 2013 2014 2015void Thumb2Assembler::blx(Register rm, Condition cond) { 2016 CHECK_NE(rm, kNoRegister); 2017 CheckCondition(cond); 2018 int16_t encoding = B14 | B10 | B9 | B8 | B7 | static_cast<int16_t>(rm) << 3; 2019 Emit16(encoding); 2020} 2021 2022 2023void Thumb2Assembler::bx(Register rm, Condition cond) { 2024 CHECK_NE(rm, kNoRegister); 2025 CheckCondition(cond); 2026 int16_t encoding = B14 | B10 | B9 | B8 | static_cast<int16_t>(rm) << 3; 2027 Emit16(encoding); 2028} 2029 2030 2031void Thumb2Assembler::Push(Register rd, Condition cond) { 2032 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond); 2033} 2034 2035 2036void Thumb2Assembler::Pop(Register rd, Condition cond) { 2037 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond); 2038} 2039 2040 2041void Thumb2Assembler::PushList(RegList regs, Condition cond) { 2042 stm(DB_W, SP, regs, cond); 2043} 2044 2045 2046void Thumb2Assembler::PopList(RegList regs, Condition cond) { 2047 ldm(IA_W, SP, regs, cond); 2048} 2049 2050 2051void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) { 2052 if (cond != AL || rd != rm) { 2053 mov(rd, ShifterOperand(rm), cond); 2054 } 2055} 2056 2057 2058// A branch has changed size. Make a hole for it. 2059void Thumb2Assembler::MakeHoleForBranch(uint32_t location, uint32_t delta) { 2060 // Move the contents of the buffer using: Move(newposition, oldposition) 2061 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2062 buffer_.Move(location + delta, location); 2063} 2064 2065 2066void Thumb2Assembler::Bind(Label* label) { 2067 CHECK(!label->IsBound()); 2068 uint32_t bound_pc = buffer_.Size(); 2069 std::vector<Branch*> changed_branches; 2070 2071 while (label->IsLinked()) { 2072 uint16_t position = label->Position(); // Branch id for linked branch. 2073 Branch* branch = GetBranch(position); // Get the branch at this id. 2074 bool changed = branch->Resolve(bound_pc); // Branch can be resolved now. 2075 uint32_t branch_location = branch->GetLocation(); 2076 uint16_t next = buffer_.Load<uint16_t>(branch_location); // Get next in chain. 2077 if (changed) { 2078 DCHECK(!force_32bit_branches_); 2079 MakeHoleForBranch(branch->GetLocation(), 2); 2080 if (branch->IsCompareAndBranch()) { 2081 // A cbz/cbnz instruction has changed size. There is no valid encoding for 2082 // a 32 bit cbz/cbnz so we need to change this to an instruction pair: 2083 // cmp rn, #0 2084 // b<eq|ne> target 2085 bool n = branch->GetType() == Branch::kCompareAndBranchNonZero; 2086 Condition cond = n ? NE : EQ; 2087 branch->Move(2); // Move the branch forward by 2 bytes. 2088 branch->ResetTypeAndCondition(Branch::kConditional, cond); 2089 branch->ResetSize(Branch::k16Bit); 2090 2091 // Now add a compare instruction in the place the branch was. 2092 int16_t cmp = B13 | B11 | static_cast<int16_t>(branch->GetRegister()) << 8; 2093 buffer_.Store<int16_t>(branch_location, cmp); 2094 2095 // Since have moved made a hole in the code we need to reload the 2096 // current pc. 2097 bound_pc = buffer_.Size(); 2098 2099 // Now resolve the newly added branch. 2100 changed = branch->Resolve(bound_pc); 2101 if (changed) { 2102 MakeHoleForBranch(branch->GetLocation(), 2); 2103 changed_branches.push_back(branch); 2104 } 2105 } else { 2106 changed_branches.push_back(branch); 2107 } 2108 } 2109 label->position_ = next; // Move to next. 2110 } 2111 label->BindTo(bound_pc); 2112 2113 // Now relocate any changed branches. Do this until there are no more changes. 2114 std::vector<Branch*> branches_to_process = changed_branches; 2115 while (branches_to_process.size() != 0) { 2116 changed_branches.clear(); 2117 for (auto& changed_branch : branches_to_process) { 2118 for (auto& branch : branches_) { 2119 bool changed = branch->Relocate(changed_branch->GetLocation(), 2); 2120 if (changed) { 2121 changed_branches.push_back(branch); 2122 } 2123 } 2124 branches_to_process = changed_branches; 2125 } 2126 } 2127} 2128 2129 2130void Thumb2Assembler::EmitBranches() { 2131 for (auto& branch : branches_) { 2132 branch->Emit(&buffer_); 2133 } 2134} 2135 2136 2137void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, 2138 bool setcc, Condition cond) { 2139 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted. 2140 CheckCondition(cond); 2141 EmitShift(rd, rm, LSL, shift_imm, setcc); 2142} 2143 2144 2145void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, 2146 bool setcc, Condition cond) { 2147 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted. 2148 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2149 CheckCondition(cond); 2150 EmitShift(rd, rm, LSR, shift_imm, setcc); 2151} 2152 2153 2154void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, 2155 bool setcc, Condition cond) { 2156 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted. 2157 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2158 CheckCondition(cond); 2159 EmitShift(rd, rm, ASR, shift_imm, setcc); 2160} 2161 2162 2163void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm, 2164 bool setcc, Condition cond) { 2165 CHECK_NE(shift_imm, 0u); // Use Rrx instruction. 2166 CheckCondition(cond); 2167 EmitShift(rd, rm, ROR, shift_imm, setcc); 2168} 2169 2170 2171void Thumb2Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) { 2172 CheckCondition(cond); 2173 EmitShift(rd, rm, RRX, rm, setcc); 2174} 2175 2176 2177void Thumb2Assembler::Lsl(Register rd, Register rm, Register rn, 2178 bool setcc, Condition cond) { 2179 CheckCondition(cond); 2180 EmitShift(rd, rm, LSL, rn, setcc); 2181} 2182 2183 2184void Thumb2Assembler::Lsr(Register rd, Register rm, Register rn, 2185 bool setcc, Condition cond) { 2186 CheckCondition(cond); 2187 EmitShift(rd, rm, LSR, rn, setcc); 2188} 2189 2190 2191void Thumb2Assembler::Asr(Register rd, Register rm, Register rn, 2192 bool setcc, Condition cond) { 2193 CheckCondition(cond); 2194 EmitShift(rd, rm, ASR, rn, setcc); 2195} 2196 2197 2198void Thumb2Assembler::Ror(Register rd, Register rm, Register rn, 2199 bool setcc, Condition cond) { 2200 CheckCondition(cond); 2201 EmitShift(rd, rm, ROR, rn, setcc); 2202} 2203 2204 2205int32_t Thumb2Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { 2206 // The offset is off by 4 due to the way the ARM CPUs read PC. 2207 offset -= 4; 2208 offset >>= 1; 2209 2210 uint32_t value = 0; 2211 // There are two different encodings depending on the value of bit 12. In one case 2212 // intermediate values are calculated using the sign bit. 2213 if ((inst & B12) == B12) { 2214 // 25 bits of offset. 2215 uint32_t signbit = (offset >> 31) & 0x1; 2216 uint32_t i1 = (offset >> 22) & 0x1; 2217 uint32_t i2 = (offset >> 21) & 0x1; 2218 uint32_t imm10 = (offset >> 11) & 0x03ff; 2219 uint32_t imm11 = offset & 0x07ff; 2220 uint32_t j1 = (i1 ^ signbit) ? 0 : 1; 2221 uint32_t j2 = (i2 ^ signbit) ? 0 : 1; 2222 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm10 << 16) | 2223 imm11; 2224 // Remove the offset from the current encoding. 2225 inst &= ~(0x3ff << 16 | 0x7ff); 2226 } else { 2227 uint32_t signbit = (offset >> 31) & 0x1; 2228 uint32_t imm6 = (offset >> 11) & 0x03f; 2229 uint32_t imm11 = offset & 0x07ff; 2230 uint32_t j1 = (offset >> 19) & 1; 2231 uint32_t j2 = (offset >> 17) & 1; 2232 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm6 << 16) | 2233 imm11; 2234 // Remove the offset from the current encoding. 2235 inst &= ~(0x3f << 16 | 0x7ff); 2236 } 2237 // Mask out offset bits in current instruction. 2238 inst &= ~(B26 | B13 | B11); 2239 inst |= value; 2240 return inst; 2241} 2242 2243 2244int Thumb2Assembler::DecodeBranchOffset(int32_t instr) { 2245 int32_t imm32; 2246 if ((instr & B12) == B12) { 2247 uint32_t S = (instr >> 26) & 1; 2248 uint32_t J2 = (instr >> 11) & 1; 2249 uint32_t J1 = (instr >> 13) & 1; 2250 uint32_t imm10 = (instr >> 16) & 0x3FF; 2251 uint32_t imm11 = instr & 0x7FF; 2252 2253 uint32_t I1 = ~(J1 ^ S) & 1; 2254 uint32_t I2 = ~(J2 ^ S) & 1; 2255 imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2256 imm32 = (imm32 << 8) >> 8; // sign extend 24 bit immediate. 2257 } else { 2258 uint32_t S = (instr >> 26) & 1; 2259 uint32_t J2 = (instr >> 11) & 1; 2260 uint32_t J1 = (instr >> 13) & 1; 2261 uint32_t imm6 = (instr >> 16) & 0x3F; 2262 uint32_t imm11 = instr & 0x7FF; 2263 2264 imm32 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2265 imm32 = (imm32 << 11) >> 11; // sign extend 21 bit immediate. 2266 } 2267 imm32 += 4; 2268 return imm32; 2269} 2270 2271 2272void Thumb2Assembler::AddConstant(Register rd, int32_t value, Condition cond) { 2273 AddConstant(rd, rd, value, cond); 2274} 2275 2276 2277void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value, 2278 Condition cond) { 2279 if (value == 0) { 2280 if (rd != rn) { 2281 mov(rd, ShifterOperand(rn), cond); 2282 } 2283 return; 2284 } 2285 // We prefer to select the shorter code sequence rather than selecting add for 2286 // positive values and sub for negatives ones, which would slightly improve 2287 // the readability of generated code for some constants. 2288 ShifterOperand shifter_op; 2289 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2290 add(rd, rn, shifter_op, cond); 2291 } else if (ShifterOperand::CanHoldThumb(rd, rn, SUB, -value, &shifter_op)) { 2292 sub(rd, rn, shifter_op, cond); 2293 } else { 2294 CHECK(rn != IP); 2295 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2296 mvn(IP, shifter_op, cond); 2297 add(rd, rn, ShifterOperand(IP), cond); 2298 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2299 mvn(IP, shifter_op, cond); 2300 sub(rd, rn, ShifterOperand(IP), cond); 2301 } else { 2302 movw(IP, Low16Bits(value), cond); 2303 uint16_t value_high = High16Bits(value); 2304 if (value_high != 0) { 2305 movt(IP, value_high, cond); 2306 } 2307 add(rd, rn, ShifterOperand(IP), cond); 2308 } 2309 } 2310} 2311 2312 2313void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value, 2314 Condition cond) { 2315 ShifterOperand shifter_op; 2316 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2317 adds(rd, rn, shifter_op, cond); 2318 } else if (ShifterOperand::CanHoldThumb(rd, rn, ADD, -value, &shifter_op)) { 2319 subs(rd, rn, shifter_op, cond); 2320 } else { 2321 CHECK(rn != IP); 2322 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2323 mvn(IP, shifter_op, cond); 2324 adds(rd, rn, ShifterOperand(IP), cond); 2325 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2326 mvn(IP, shifter_op, cond); 2327 subs(rd, rn, ShifterOperand(IP), cond); 2328 } else { 2329 movw(IP, Low16Bits(value), cond); 2330 uint16_t value_high = High16Bits(value); 2331 if (value_high != 0) { 2332 movt(IP, value_high, cond); 2333 } 2334 adds(rd, rn, ShifterOperand(IP), cond); 2335 } 2336 } 2337} 2338 2339 2340void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { 2341 ShifterOperand shifter_op; 2342 if (ShifterOperand::CanHoldThumb(rd, R0, MOV, value, &shifter_op)) { 2343 mov(rd, shifter_op, cond); 2344 } else if (ShifterOperand::CanHoldThumb(rd, R0, MVN, ~value, &shifter_op)) { 2345 mvn(rd, shifter_op, cond); 2346 } else { 2347 movw(rd, Low16Bits(value), cond); 2348 uint16_t value_high = High16Bits(value); 2349 if (value_high != 0) { 2350 movt(rd, value_high, cond); 2351 } 2352 } 2353} 2354 2355// Implementation note: this method must emit at most one instruction when 2356// Address::CanHoldLoadOffsetThumb. 2357void Thumb2Assembler::LoadFromOffset(LoadOperandType type, 2358 Register reg, 2359 Register base, 2360 int32_t offset, 2361 Condition cond) { 2362 if (!Address::CanHoldLoadOffsetThumb(type, offset)) { 2363 CHECK(base != IP); 2364 LoadImmediate(IP, offset, cond); 2365 add(IP, IP, ShifterOperand(base), cond); 2366 base = IP; 2367 offset = 0; 2368 } 2369 CHECK(Address::CanHoldLoadOffsetThumb(type, offset)); 2370 switch (type) { 2371 case kLoadSignedByte: 2372 ldrsb(reg, Address(base, offset), cond); 2373 break; 2374 case kLoadUnsignedByte: 2375 ldrb(reg, Address(base, offset), cond); 2376 break; 2377 case kLoadSignedHalfword: 2378 ldrsh(reg, Address(base, offset), cond); 2379 break; 2380 case kLoadUnsignedHalfword: 2381 ldrh(reg, Address(base, offset), cond); 2382 break; 2383 case kLoadWord: 2384 ldr(reg, Address(base, offset), cond); 2385 break; 2386 case kLoadWordPair: 2387 ldrd(reg, Address(base, offset), cond); 2388 break; 2389 default: 2390 LOG(FATAL) << "UNREACHABLE"; 2391 } 2392} 2393 2394 2395// Implementation note: this method must emit at most one instruction when 2396// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2397void Thumb2Assembler::LoadSFromOffset(SRegister reg, 2398 Register base, 2399 int32_t offset, 2400 Condition cond) { 2401 if (!Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)) { 2402 CHECK_NE(base, IP); 2403 LoadImmediate(IP, offset, cond); 2404 add(IP, IP, ShifterOperand(base), cond); 2405 base = IP; 2406 offset = 0; 2407 } 2408 CHECK(Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)); 2409 vldrs(reg, Address(base, offset), cond); 2410} 2411 2412 2413// Implementation note: this method must emit at most one instruction when 2414// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2415void Thumb2Assembler::LoadDFromOffset(DRegister reg, 2416 Register base, 2417 int32_t offset, 2418 Condition cond) { 2419 if (!Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)) { 2420 CHECK_NE(base, IP); 2421 LoadImmediate(IP, offset, cond); 2422 add(IP, IP, ShifterOperand(base), cond); 2423 base = IP; 2424 offset = 0; 2425 } 2426 CHECK(Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)); 2427 vldrd(reg, Address(base, offset), cond); 2428} 2429 2430 2431// Implementation note: this method must emit at most one instruction when 2432// Address::CanHoldStoreOffsetThumb. 2433void Thumb2Assembler::StoreToOffset(StoreOperandType type, 2434 Register reg, 2435 Register base, 2436 int32_t offset, 2437 Condition cond) { 2438 if (!Address::CanHoldStoreOffsetThumb(type, offset)) { 2439 CHECK(reg != IP); 2440 CHECK(base != IP); 2441 LoadImmediate(IP, offset, cond); 2442 add(IP, IP, ShifterOperand(base), cond); 2443 base = IP; 2444 offset = 0; 2445 } 2446 CHECK(Address::CanHoldStoreOffsetThumb(type, offset)); 2447 switch (type) { 2448 case kStoreByte: 2449 strb(reg, Address(base, offset), cond); 2450 break; 2451 case kStoreHalfword: 2452 strh(reg, Address(base, offset), cond); 2453 break; 2454 case kStoreWord: 2455 str(reg, Address(base, offset), cond); 2456 break; 2457 case kStoreWordPair: 2458 strd(reg, Address(base, offset), cond); 2459 break; 2460 default: 2461 LOG(FATAL) << "UNREACHABLE"; 2462 } 2463} 2464 2465 2466// Implementation note: this method must emit at most one instruction when 2467// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreToOffset. 2468void Thumb2Assembler::StoreSToOffset(SRegister reg, 2469 Register base, 2470 int32_t offset, 2471 Condition cond) { 2472 if (!Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)) { 2473 CHECK_NE(base, IP); 2474 LoadImmediate(IP, offset, cond); 2475 add(IP, IP, ShifterOperand(base), cond); 2476 base = IP; 2477 offset = 0; 2478 } 2479 CHECK(Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)); 2480 vstrs(reg, Address(base, offset), cond); 2481} 2482 2483 2484// Implementation note: this method must emit at most one instruction when 2485// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreSToOffset. 2486void Thumb2Assembler::StoreDToOffset(DRegister reg, 2487 Register base, 2488 int32_t offset, 2489 Condition cond) { 2490 if (!Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)) { 2491 CHECK_NE(base, IP); 2492 LoadImmediate(IP, offset, cond); 2493 add(IP, IP, ShifterOperand(base), cond); 2494 base = IP; 2495 offset = 0; 2496 } 2497 CHECK(Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)); 2498 vstrd(reg, Address(base, offset), cond); 2499} 2500 2501 2502void Thumb2Assembler::MemoryBarrier(ManagedRegister mscratch) { 2503 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12); 2504#if ANDROID_SMP != 0 2505 int32_t encoding = 0xf3bf8f5f; // dmb in T1 encoding. 2506 Emit32(encoding); 2507#endif 2508} 2509 2510 2511void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) { 2512 cbz(r, label); 2513} 2514 2515 2516void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) { 2517 cbnz(r, label); 2518} 2519} // namespace arm 2520} // namespace art 2521