assembler_thumb2.cc revision 1a43dd78d054dbad8d7af9ba4829ea2f1cb70b53
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 | (load ? B20 : 0) | static_cast<uint32_t>(rd) << 12 | 1380 ad.encodingThumb(true); 1381 if (half) { 1382 encoding |= B21; 1383 } else if (!byte) { 1384 encoding |= B22; 1385 } 1386 Emit32(encoding); 1387 } else { 1388 // 16 bit register offset. 1389 int32_t encoding = B14 | B12 | (load ? B11 : 0) | static_cast<uint32_t>(rd) | 1390 ad.encodingThumb(false); 1391 if (byte) { 1392 encoding |= B10; 1393 } else if (half) { 1394 encoding |= B9; 1395 } 1396 Emit16(encoding); 1397 } 1398 } 1399 } 1400} 1401 1402 1403void Thumb2Assembler::EmitMultiMemOp(Condition cond, 1404 BlockAddressMode am, 1405 bool load, 1406 Register base, 1407 RegList regs) { 1408 CHECK_NE(base, kNoRegister); 1409 CheckCondition(cond); 1410 bool must_be_32bit = force_32bit_; 1411 1412 if ((regs & 0xff00) != 0) { 1413 must_be_32bit = true; 1414 } 1415 1416 uint32_t w_bit = am == IA_W || am == DB_W || am == DA_W || am == IB_W; 1417 // 16 bit always uses writeback. 1418 if (!w_bit) { 1419 must_be_32bit = true; 1420 } 1421 1422 if (must_be_32bit) { 1423 uint32_t op = 0; 1424 switch (am) { 1425 case IA: 1426 case IA_W: 1427 op = 0b01; 1428 break; 1429 case DB: 1430 case DB_W: 1431 op = 0b10; 1432 break; 1433 case DA: 1434 case IB: 1435 case DA_W: 1436 case IB_W: 1437 LOG(FATAL) << "LDM/STM mode not supported on thumb: " << am; 1438 } 1439 if (load) { 1440 // Cannot have SP in the list. 1441 CHECK_EQ((regs & (1 << SP)), 0); 1442 } else { 1443 // Cannot have PC or SP in the list. 1444 CHECK_EQ((regs & (1 << PC | 1 << SP)), 0); 1445 } 1446 int32_t encoding = B31 | B30 | B29 | B27 | 1447 (op << 23) | 1448 (load ? B20 : 0) | 1449 base << 16 | 1450 regs | 1451 (w_bit << 21); 1452 Emit32(encoding); 1453 } else { 1454 int16_t encoding = B15 | B14 | 1455 (load ? B11 : 0) | 1456 base << 8 | 1457 regs; 1458 Emit16(encoding); 1459 } 1460} 1461 1462 1463void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x) { 1464 uint32_t pc = buffer_.Size(); 1465 Branch::Type branch_type; 1466 if (cond == AL) { 1467 if (link) { 1468 if (x) { 1469 branch_type = Branch::kUnconditionalLinkX; // BLX. 1470 } else { 1471 branch_type = Branch::kUnconditionalLink; // BX. 1472 } 1473 } else { 1474 branch_type = Branch::kUnconditional; // B. 1475 } 1476 } else { 1477 branch_type = Branch::kConditional; // B<cond>. 1478 } 1479 1480 if (label->IsBound()) { 1481 Branch::Size size = AddBranch(branch_type, pc, label->Position(), cond); // Resolved branch. 1482 1483 // The branch is to a bound label which means that it's a backwards branch. We know the 1484 // current size of it so we can emit the appropriate space. Note that if it's a 16 bit 1485 // branch the size may change if it so happens that other branches change size that change 1486 // the distance to the target and that distance puts this branch over the limit for 16 bits. 1487 if (size == Branch::k16Bit) { 1488 DCHECK(!force_32bit_branches_); 1489 Emit16(0); // Space for a 16 bit branch. 1490 } else { 1491 Emit32(0); // Space for a 32 bit branch. 1492 } 1493 } else { 1494 // Branch is to an unbound label. Emit space for it. 1495 uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch. 1496 if (force_32bit_branches_ || force_32bit_) { 1497 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1498 Emit16(0); // another 16 bits. 1499 } else { 1500 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1501 } 1502 label->LinkTo(branch_id); // Link to the branch ID. 1503 } 1504} 1505 1506 1507void Thumb2Assembler::clz(Register rd, Register rm, Condition cond) { 1508 CHECK_NE(rd, kNoRegister); 1509 CHECK_NE(rm, kNoRegister); 1510 CheckCondition(cond); 1511 CHECK_NE(rd, PC); 1512 CHECK_NE(rm, PC); 1513 int32_t encoding = B31 | B30 | B29 | B28 | B27 | 1514 B25 | B23 | B21 | B20 | 1515 static_cast<uint32_t>(rm) << 16 | 1516 0xf << 12 | 1517 static_cast<uint32_t>(rd) << 8 | 1518 B7 | 1519 static_cast<uint32_t>(rm); 1520 Emit32(encoding); 1521} 1522 1523 1524void Thumb2Assembler::movw(Register rd, uint16_t imm16, Condition cond) { 1525 CheckCondition(cond); 1526 bool must_be_32bit = force_32bit_; 1527 if (IsHighRegister(rd)|| imm16 >= 256u) { 1528 must_be_32bit = true; 1529 } 1530 1531 if (must_be_32bit) { 1532 // Use encoding T3. 1533 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1534 uint32_t i = (imm16 >> 11) & 0b1; 1535 uint32_t imm3 = (imm16 >> 8) & 0b111; 1536 uint32_t imm8 = imm16 & 0xff; 1537 int32_t encoding = B31 | B30 | B29 | B28 | 1538 B25 | B22 | 1539 static_cast<uint32_t>(rd) << 8 | 1540 i << 26 | 1541 imm4 << 16 | 1542 imm3 << 12 | 1543 imm8; 1544 Emit32(encoding); 1545 } else { 1546 int16_t encoding = B13 | static_cast<uint16_t>(rd) << 8 | 1547 imm16; 1548 Emit16(encoding); 1549 } 1550} 1551 1552 1553void Thumb2Assembler::movt(Register rd, uint16_t imm16, Condition cond) { 1554 CheckCondition(cond); 1555 // Always 32 bits. 1556 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1557 uint32_t i = (imm16 >> 11) & 0b1; 1558 uint32_t imm3 = (imm16 >> 8) & 0b111; 1559 uint32_t imm8 = imm16 & 0xff; 1560 int32_t encoding = B31 | B30 | B29 | B28 | 1561 B25 | B23 | B22 | 1562 static_cast<uint32_t>(rd) << 8 | 1563 i << 26 | 1564 imm4 << 16 | 1565 imm3 << 12 | 1566 imm8; 1567 Emit32(encoding); 1568} 1569 1570 1571void Thumb2Assembler::ldrex(Register rt, Register rn, uint16_t imm, Condition cond) { 1572 CHECK_NE(rn, kNoRegister); 1573 CHECK_NE(rt, kNoRegister); 1574 CheckCondition(cond); 1575 CHECK_NE(rn, kNoRegister); 1576 CHECK_NE(rt, kNoRegister); 1577 CheckCondition(cond); 1578 CHECK_LT(imm, (1u << 10)); 1579 1580 int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 | 1581 static_cast<uint32_t>(rn) << 16 | 1582 static_cast<uint32_t>(rt) << 12 | 1583 0xf << 8 | 1584 imm >> 2; 1585 Emit32(encoding); 1586} 1587 1588 1589void Thumb2Assembler::ldrex(Register rt, Register rn, Condition cond) { 1590 ldrex(rt, rn, 0, cond); 1591} 1592 1593 1594void Thumb2Assembler::strex(Register rd, 1595 Register rt, 1596 Register rn, 1597 uint16_t imm, 1598 Condition cond) { 1599 CHECK_NE(rn, kNoRegister); 1600 CHECK_NE(rd, kNoRegister); 1601 CHECK_NE(rt, kNoRegister); 1602 CheckCondition(cond); 1603 CHECK_LT(imm, (1u << 10)); 1604 1605 int32_t encoding = B31 | B30 | B29 | B27 | B22 | 1606 static_cast<uint32_t>(rn) << 16 | 1607 static_cast<uint32_t>(rt) << 12 | 1608 static_cast<uint32_t>(rd) << 8 | 1609 imm >> 2; 1610 Emit32(encoding); 1611} 1612 1613 1614void Thumb2Assembler::strex(Register rd, 1615 Register rt, 1616 Register rn, 1617 Condition cond) { 1618 strex(rd, rt, rn, 0, cond); 1619} 1620 1621 1622void Thumb2Assembler::clrex(Condition cond) { 1623 CheckCondition(cond); 1624 int32_t encoding = B31 | B30 | B29 | B27 | B28 | B25 | B24 | B23 | 1625 B21 | B20 | 1626 0xf << 16 | 1627 B15 | 1628 0xf << 8 | 1629 B5 | 1630 0xf; 1631 Emit32(encoding); 1632} 1633 1634 1635void Thumb2Assembler::nop(Condition cond) { 1636 CheckCondition(cond); 1637 int16_t encoding = B15 | B13 | B12 | 1638 B11 | B10 | B9 | B8; 1639 Emit16(encoding); 1640} 1641 1642 1643void Thumb2Assembler::vmovsr(SRegister sn, Register rt, Condition cond) { 1644 CHECK_NE(sn, kNoSRegister); 1645 CHECK_NE(rt, kNoRegister); 1646 CHECK_NE(rt, SP); 1647 CHECK_NE(rt, PC); 1648 CheckCondition(cond); 1649 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1650 B27 | B26 | B25 | 1651 ((static_cast<int32_t>(sn) >> 1)*B16) | 1652 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1653 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1654 Emit32(encoding); 1655} 1656 1657 1658void Thumb2Assembler::vmovrs(Register rt, SRegister sn, Condition cond) { 1659 CHECK_NE(sn, kNoSRegister); 1660 CHECK_NE(rt, kNoRegister); 1661 CHECK_NE(rt, SP); 1662 CHECK_NE(rt, PC); 1663 CheckCondition(cond); 1664 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1665 B27 | B26 | B25 | B20 | 1666 ((static_cast<int32_t>(sn) >> 1)*B16) | 1667 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1668 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1669 Emit32(encoding); 1670} 1671 1672 1673void Thumb2Assembler::vmovsrr(SRegister sm, Register rt, Register rt2, 1674 Condition cond) { 1675 CHECK_NE(sm, kNoSRegister); 1676 CHECK_NE(sm, S31); 1677 CHECK_NE(rt, kNoRegister); 1678 CHECK_NE(rt, SP); 1679 CHECK_NE(rt, PC); 1680 CHECK_NE(rt2, kNoRegister); 1681 CHECK_NE(rt2, SP); 1682 CHECK_NE(rt2, PC); 1683 CheckCondition(cond); 1684 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1685 B27 | B26 | B22 | 1686 (static_cast<int32_t>(rt2)*B16) | 1687 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1688 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1689 (static_cast<int32_t>(sm) >> 1); 1690 Emit32(encoding); 1691} 1692 1693 1694void Thumb2Assembler::vmovrrs(Register rt, Register rt2, SRegister sm, 1695 Condition cond) { 1696 CHECK_NE(sm, kNoSRegister); 1697 CHECK_NE(sm, S31); 1698 CHECK_NE(rt, kNoRegister); 1699 CHECK_NE(rt, SP); 1700 CHECK_NE(rt, PC); 1701 CHECK_NE(rt2, kNoRegister); 1702 CHECK_NE(rt2, SP); 1703 CHECK_NE(rt2, PC); 1704 CHECK_NE(rt, rt2); 1705 CheckCondition(cond); 1706 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1707 B27 | B26 | B22 | B20 | 1708 (static_cast<int32_t>(rt2)*B16) | 1709 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1710 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1711 (static_cast<int32_t>(sm) >> 1); 1712 Emit32(encoding); 1713} 1714 1715 1716void Thumb2Assembler::vmovdrr(DRegister dm, Register rt, Register rt2, 1717 Condition cond) { 1718 CHECK_NE(dm, kNoDRegister); 1719 CHECK_NE(rt, kNoRegister); 1720 CHECK_NE(rt, SP); 1721 CHECK_NE(rt, PC); 1722 CHECK_NE(rt2, kNoRegister); 1723 CHECK_NE(rt2, SP); 1724 CHECK_NE(rt2, PC); 1725 CheckCondition(cond); 1726 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1727 B27 | B26 | B22 | 1728 (static_cast<int32_t>(rt2)*B16) | 1729 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1730 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1731 (static_cast<int32_t>(dm) & 0xf); 1732 Emit32(encoding); 1733} 1734 1735 1736void Thumb2Assembler::vmovrrd(Register rt, Register rt2, DRegister dm, 1737 Condition cond) { 1738 CHECK_NE(dm, kNoDRegister); 1739 CHECK_NE(rt, kNoRegister); 1740 CHECK_NE(rt, SP); 1741 CHECK_NE(rt, PC); 1742 CHECK_NE(rt2, kNoRegister); 1743 CHECK_NE(rt2, SP); 1744 CHECK_NE(rt2, PC); 1745 CHECK_NE(rt, rt2); 1746 CheckCondition(cond); 1747 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1748 B27 | B26 | B22 | B20 | 1749 (static_cast<int32_t>(rt2)*B16) | 1750 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1751 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1752 (static_cast<int32_t>(dm) & 0xf); 1753 Emit32(encoding); 1754} 1755 1756 1757void Thumb2Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) { 1758 const Address& addr = static_cast<const Address&>(ad); 1759 CHECK_NE(sd, kNoSRegister); 1760 CheckCondition(cond); 1761 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1762 B27 | B26 | B24 | B20 | 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::vstrs(SRegister sd, const Address& ad, Condition cond) { 1771 const Address& addr = static_cast<const Address&>(ad); 1772 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1773 CHECK_NE(sd, kNoSRegister); 1774 CheckCondition(cond); 1775 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1776 B27 | B26 | B24 | 1777 ((static_cast<int32_t>(sd) & 1)*B22) | 1778 ((static_cast<int32_t>(sd) >> 1)*B12) | 1779 B11 | B9 | addr.vencoding(); 1780 Emit32(encoding); 1781} 1782 1783 1784void Thumb2Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) { 1785 const Address& addr = static_cast<const Address&>(ad); 1786 CHECK_NE(dd, kNoDRegister); 1787 CheckCondition(cond); 1788 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1789 B27 | B26 | B24 | B20 | 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::vstrd(DRegister dd, const Address& ad, Condition cond) { 1798 const Address& addr = static_cast<const Address&>(ad); 1799 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1800 CHECK_NE(dd, kNoDRegister); 1801 CheckCondition(cond); 1802 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1803 B27 | B26 | B24 | 1804 ((static_cast<int32_t>(dd) >> 4)*B22) | 1805 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1806 B11 | B9 | B8 | addr.vencoding(); 1807 Emit32(encoding); 1808} 1809 1810 1811void Thumb2Assembler::vpushs(SRegister reg, int nregs, Condition cond) { 1812 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond); 1813} 1814 1815 1816void Thumb2Assembler::vpushd(DRegister reg, int nregs, Condition cond) { 1817 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond); 1818} 1819 1820 1821void Thumb2Assembler::vpops(SRegister reg, int nregs, Condition cond) { 1822 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond); 1823} 1824 1825 1826void Thumb2Assembler::vpopd(DRegister reg, int nregs, Condition cond) { 1827 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond); 1828} 1829 1830 1831void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) { 1832 CheckCondition(cond); 1833 1834 uint32_t D; 1835 uint32_t Vd; 1836 if (dbl) { 1837 // Encoded as D:Vd. 1838 D = (reg >> 4) & 1; 1839 Vd = reg & 0b1111; 1840 } else { 1841 // Encoded as Vd:D. 1842 D = reg & 1; 1843 Vd = (reg >> 1) & 0b1111; 1844 } 1845 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 | 1846 B11 | B9 | 1847 (dbl ? B8 : 0) | 1848 (push ? B24 : (B23 | B20)) | 1849 0b1110 << 28 | 1850 nregs << (dbl ? 1 : 0) | 1851 D << 22 | 1852 Vd << 12; 1853 Emit32(encoding); 1854} 1855 1856 1857void Thumb2Assembler::EmitVFPsss(Condition cond, int32_t opcode, 1858 SRegister sd, SRegister sn, SRegister sm) { 1859 CHECK_NE(sd, kNoSRegister); 1860 CHECK_NE(sn, kNoSRegister); 1861 CHECK_NE(sm, kNoSRegister); 1862 CheckCondition(cond); 1863 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1864 B27 | B26 | B25 | B11 | B9 | opcode | 1865 ((static_cast<int32_t>(sd) & 1)*B22) | 1866 ((static_cast<int32_t>(sn) >> 1)*B16) | 1867 ((static_cast<int32_t>(sd) >> 1)*B12) | 1868 ((static_cast<int32_t>(sn) & 1)*B7) | 1869 ((static_cast<int32_t>(sm) & 1)*B5) | 1870 (static_cast<int32_t>(sm) >> 1); 1871 Emit32(encoding); 1872} 1873 1874 1875void Thumb2Assembler::EmitVFPddd(Condition cond, int32_t opcode, 1876 DRegister dd, DRegister dn, DRegister dm) { 1877 CHECK_NE(dd, kNoDRegister); 1878 CHECK_NE(dn, kNoDRegister); 1879 CHECK_NE(dm, kNoDRegister); 1880 CheckCondition(cond); 1881 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1882 B27 | B26 | B25 | B11 | B9 | B8 | opcode | 1883 ((static_cast<int32_t>(dd) >> 4)*B22) | 1884 ((static_cast<int32_t>(dn) & 0xf)*B16) | 1885 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1886 ((static_cast<int32_t>(dn) >> 4)*B7) | 1887 ((static_cast<int32_t>(dm) >> 4)*B5) | 1888 (static_cast<int32_t>(dm) & 0xf); 1889 Emit32(encoding); 1890} 1891 1892 1893void Thumb2Assembler::EmitVFPsd(Condition cond, int32_t opcode, 1894 SRegister sd, DRegister dm) { 1895 CHECK_NE(sd, kNoSRegister); 1896 CHECK_NE(dm, kNoDRegister); 1897 CheckCondition(cond); 1898 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1899 B27 | B26 | B25 | B11 | B9 | opcode | 1900 ((static_cast<int32_t>(sd) & 1)*B22) | 1901 ((static_cast<int32_t>(sd) >> 1)*B12) | 1902 ((static_cast<int32_t>(dm) >> 4)*B5) | 1903 (static_cast<int32_t>(dm) & 0xf); 1904 Emit32(encoding); 1905} 1906 1907 1908void Thumb2Assembler::EmitVFPds(Condition cond, int32_t opcode, 1909 DRegister dd, SRegister sm) { 1910 CHECK_NE(dd, kNoDRegister); 1911 CHECK_NE(sm, kNoSRegister); 1912 CheckCondition(cond); 1913 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1914 B27 | B26 | B25 | B11 | B9 | opcode | 1915 ((static_cast<int32_t>(dd) >> 4)*B22) | 1916 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1917 ((static_cast<int32_t>(sm) & 1)*B5) | 1918 (static_cast<int32_t>(sm) >> 1); 1919 Emit32(encoding); 1920} 1921 1922 1923void Thumb2Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR. 1924 CheckCondition(cond); 1925 UNIMPLEMENTED(FATAL) << "Unimplemented thumb instruction"; 1926} 1927 1928 1929void Thumb2Assembler::svc(uint32_t imm8) { 1930 CHECK(IsUint(8, imm8)) << imm8; 1931 int16_t encoding = B15 | B14 | B12 | 1932 B11 | B10 | B9 | B8 | 1933 imm8; 1934 Emit16(encoding); 1935} 1936 1937 1938void Thumb2Assembler::bkpt(uint16_t imm8) { 1939 CHECK(IsUint(8, imm8)) << imm8; 1940 int16_t encoding = B15 | B13 | B12 | 1941 B11 | B10 | B9 | 1942 imm8; 1943 Emit16(encoding); 1944} 1945 1946// Convert the given IT state to a mask bit given bit 0 of the first 1947// condition and a shift position. 1948static uint8_t ToItMask(ItState s, uint8_t firstcond0, uint8_t shift) { 1949 switch (s) { 1950 case kItOmitted: return 1 << shift; 1951 case kItThen: return firstcond0 << shift; 1952 case kItElse: return !firstcond0 << shift; 1953 } 1954 return 0; 1955} 1956 1957 1958// Set the IT condition in the given position for the given state. This is used 1959// to check that conditional instructions match the preceding IT statement. 1960void Thumb2Assembler::SetItCondition(ItState s, Condition cond, uint8_t index) { 1961 switch (s) { 1962 case kItOmitted: it_conditions_[index] = AL; break; 1963 case kItThen: it_conditions_[index] = cond; break; 1964 case kItElse: 1965 it_conditions_[index] = static_cast<Condition>(static_cast<uint8_t>(cond) ^ 1); 1966 break; 1967 } 1968} 1969 1970 1971void Thumb2Assembler::it(Condition firstcond, ItState i1, ItState i2, ItState i3) { 1972 CheckCondition(AL); // Not allowed in IT block. 1973 uint8_t firstcond0 = static_cast<uint8_t>(firstcond) & 1; 1974 1975 // All conditions to AL. 1976 for (uint8_t i = 0; i < 4; ++i) { 1977 it_conditions_[i] = AL; 1978 } 1979 1980 SetItCondition(kItThen, firstcond, 0); 1981 uint8_t mask = ToItMask(i1, firstcond0, 3); 1982 SetItCondition(i1, firstcond, 1); 1983 1984 if (i1 != kItOmitted) { 1985 mask |= ToItMask(i2, firstcond0, 2); 1986 SetItCondition(i2, firstcond, 2); 1987 if (i2 != kItOmitted) { 1988 mask |= ToItMask(i3, firstcond0, 1); 1989 SetItCondition(i3, firstcond, 3); 1990 if (i3 != kItOmitted) { 1991 mask |= 0b0001; 1992 } 1993 } 1994 } 1995 1996 // Start at first condition. 1997 it_cond_index_ = 0; 1998 next_condition_ = it_conditions_[0]; 1999 uint16_t encoding = B15 | B13 | B12 | 2000 B11 | B10 | B9 | B8 | 2001 firstcond << 4 | 2002 mask; 2003 Emit16(encoding); 2004} 2005 2006 2007void Thumb2Assembler::cbz(Register rn, Label* label) { 2008 CheckCondition(AL); 2009 if (label->IsBound()) { 2010 LOG(FATAL) << "cbz can only be used to branch forwards"; 2011 } else { 2012 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), false); 2013 label->LinkTo(branchid); 2014 } 2015} 2016 2017 2018void Thumb2Assembler::cbnz(Register rn, Label* label) { 2019 CheckCondition(AL); 2020 if (label->IsBound()) { 2021 LOG(FATAL) << "cbnz can only be used to branch forwards"; 2022 } else { 2023 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), true); 2024 label->LinkTo(branchid); 2025 } 2026} 2027 2028 2029void Thumb2Assembler::blx(Register rm, Condition cond) { 2030 CHECK_NE(rm, kNoRegister); 2031 CheckCondition(cond); 2032 int16_t encoding = B14 | B10 | B9 | B8 | B7 | static_cast<int16_t>(rm) << 3; 2033 Emit16(encoding); 2034} 2035 2036 2037void Thumb2Assembler::bx(Register rm, Condition cond) { 2038 CHECK_NE(rm, kNoRegister); 2039 CheckCondition(cond); 2040 int16_t encoding = B14 | B10 | B9 | B8 | static_cast<int16_t>(rm) << 3; 2041 Emit16(encoding); 2042} 2043 2044 2045void Thumb2Assembler::Push(Register rd, Condition cond) { 2046 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond); 2047} 2048 2049 2050void Thumb2Assembler::Pop(Register rd, Condition cond) { 2051 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond); 2052} 2053 2054 2055void Thumb2Assembler::PushList(RegList regs, Condition cond) { 2056 stm(DB_W, SP, regs, cond); 2057} 2058 2059 2060void Thumb2Assembler::PopList(RegList regs, Condition cond) { 2061 ldm(IA_W, SP, regs, cond); 2062} 2063 2064 2065void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) { 2066 if (cond != AL || rd != rm) { 2067 mov(rd, ShifterOperand(rm), cond); 2068 } 2069} 2070 2071 2072// A branch has changed size. Make a hole for it. 2073void Thumb2Assembler::MakeHoleForBranch(uint32_t location, uint32_t delta) { 2074 // Move the contents of the buffer using: Move(newposition, oldposition) 2075 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2076 buffer_.Move(location + delta, location); 2077} 2078 2079 2080void Thumb2Assembler::Bind(Label* label) { 2081 CHECK(!label->IsBound()); 2082 uint32_t bound_pc = buffer_.Size(); 2083 std::vector<Branch*> changed_branches; 2084 2085 while (label->IsLinked()) { 2086 uint16_t position = label->Position(); // Branch id for linked branch. 2087 Branch* branch = GetBranch(position); // Get the branch at this id. 2088 bool changed = branch->Resolve(bound_pc); // Branch can be resolved now. 2089 uint32_t branch_location = branch->GetLocation(); 2090 uint16_t next = buffer_.Load<uint16_t>(branch_location); // Get next in chain. 2091 if (changed) { 2092 DCHECK(!force_32bit_branches_); 2093 MakeHoleForBranch(branch->GetLocation(), 2); 2094 if (branch->IsCompareAndBranch()) { 2095 // A cbz/cbnz instruction has changed size. There is no valid encoding for 2096 // a 32 bit cbz/cbnz so we need to change this to an instruction pair: 2097 // cmp rn, #0 2098 // b<eq|ne> target 2099 bool n = branch->GetType() == Branch::kCompareAndBranchNonZero; 2100 Condition cond = n ? NE : EQ; 2101 branch->Move(2); // Move the branch forward by 2 bytes. 2102 branch->ResetTypeAndCondition(Branch::kConditional, cond); 2103 branch->ResetSize(Branch::k16Bit); 2104 2105 // Now add a compare instruction in the place the branch was. 2106 int16_t cmp = B13 | B11 | static_cast<int16_t>(branch->GetRegister()) << 8; 2107 buffer_.Store<int16_t>(branch_location, cmp); 2108 2109 // Since have moved made a hole in the code we need to reload the 2110 // current pc. 2111 bound_pc = buffer_.Size(); 2112 2113 // Now resolve the newly added branch. 2114 changed = branch->Resolve(bound_pc); 2115 if (changed) { 2116 MakeHoleForBranch(branch->GetLocation(), 2); 2117 changed_branches.push_back(branch); 2118 } 2119 } else { 2120 changed_branches.push_back(branch); 2121 } 2122 } 2123 label->position_ = next; // Move to next. 2124 } 2125 label->BindTo(bound_pc); 2126 2127 // Now relocate any changed branches. Do this until there are no more changes. 2128 std::vector<Branch*> branches_to_process = changed_branches; 2129 while (branches_to_process.size() != 0) { 2130 changed_branches.clear(); 2131 for (auto& changed_branch : branches_to_process) { 2132 for (auto& branch : branches_) { 2133 bool changed = branch->Relocate(changed_branch->GetLocation(), 2); 2134 if (changed) { 2135 changed_branches.push_back(branch); 2136 } 2137 } 2138 branches_to_process = changed_branches; 2139 } 2140 } 2141} 2142 2143 2144void Thumb2Assembler::EmitBranches() { 2145 for (auto& branch : branches_) { 2146 branch->Emit(&buffer_); 2147 } 2148} 2149 2150 2151void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, 2152 bool setcc, Condition cond) { 2153 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted. 2154 CheckCondition(cond); 2155 EmitShift(rd, rm, LSL, shift_imm, setcc); 2156} 2157 2158 2159void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, 2160 bool setcc, Condition cond) { 2161 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted. 2162 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2163 CheckCondition(cond); 2164 EmitShift(rd, rm, LSR, shift_imm, setcc); 2165} 2166 2167 2168void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, 2169 bool setcc, Condition cond) { 2170 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted. 2171 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2172 CheckCondition(cond); 2173 EmitShift(rd, rm, ASR, shift_imm, setcc); 2174} 2175 2176 2177void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm, 2178 bool setcc, Condition cond) { 2179 CHECK_NE(shift_imm, 0u); // Use Rrx instruction. 2180 CheckCondition(cond); 2181 EmitShift(rd, rm, ROR, shift_imm, setcc); 2182} 2183 2184 2185void Thumb2Assembler::Rrx(Register rd, Register rm, bool setcc, Condition cond) { 2186 CheckCondition(cond); 2187 EmitShift(rd, rm, RRX, rm, setcc); 2188} 2189 2190 2191void Thumb2Assembler::Lsl(Register rd, Register rm, Register rn, 2192 bool setcc, Condition cond) { 2193 CheckCondition(cond); 2194 EmitShift(rd, rm, LSL, rn, setcc); 2195} 2196 2197 2198void Thumb2Assembler::Lsr(Register rd, Register rm, Register rn, 2199 bool setcc, Condition cond) { 2200 CheckCondition(cond); 2201 EmitShift(rd, rm, LSR, rn, setcc); 2202} 2203 2204 2205void Thumb2Assembler::Asr(Register rd, Register rm, Register rn, 2206 bool setcc, Condition cond) { 2207 CheckCondition(cond); 2208 EmitShift(rd, rm, ASR, rn, setcc); 2209} 2210 2211 2212void Thumb2Assembler::Ror(Register rd, Register rm, Register rn, 2213 bool setcc, Condition cond) { 2214 CheckCondition(cond); 2215 EmitShift(rd, rm, ROR, rn, setcc); 2216} 2217 2218 2219int32_t Thumb2Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { 2220 // The offset is off by 4 due to the way the ARM CPUs read PC. 2221 offset -= 4; 2222 offset >>= 1; 2223 2224 uint32_t value = 0; 2225 // There are two different encodings depending on the value of bit 12. In one case 2226 // intermediate values are calculated using the sign bit. 2227 if ((inst & B12) == B12) { 2228 // 25 bits of offset. 2229 uint32_t signbit = (offset >> 31) & 0x1; 2230 uint32_t i1 = (offset >> 22) & 0x1; 2231 uint32_t i2 = (offset >> 21) & 0x1; 2232 uint32_t imm10 = (offset >> 11) & 0x03ff; 2233 uint32_t imm11 = offset & 0x07ff; 2234 uint32_t j1 = (i1 ^ signbit) ? 0 : 1; 2235 uint32_t j2 = (i2 ^ signbit) ? 0 : 1; 2236 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm10 << 16) | 2237 imm11; 2238 // Remove the offset from the current encoding. 2239 inst &= ~(0x3ff << 16 | 0x7ff); 2240 } else { 2241 uint32_t signbit = (offset >> 31) & 0x1; 2242 uint32_t imm6 = (offset >> 11) & 0x03f; 2243 uint32_t imm11 = offset & 0x07ff; 2244 uint32_t j1 = (offset >> 19) & 1; 2245 uint32_t j2 = (offset >> 17) & 1; 2246 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm6 << 16) | 2247 imm11; 2248 // Remove the offset from the current encoding. 2249 inst &= ~(0x3f << 16 | 0x7ff); 2250 } 2251 // Mask out offset bits in current instruction. 2252 inst &= ~(B26 | B13 | B11); 2253 inst |= value; 2254 return inst; 2255} 2256 2257 2258int Thumb2Assembler::DecodeBranchOffset(int32_t instr) { 2259 int32_t imm32; 2260 if ((instr & B12) == B12) { 2261 uint32_t S = (instr >> 26) & 1; 2262 uint32_t J2 = (instr >> 11) & 1; 2263 uint32_t J1 = (instr >> 13) & 1; 2264 uint32_t imm10 = (instr >> 16) & 0x3FF; 2265 uint32_t imm11 = instr & 0x7FF; 2266 2267 uint32_t I1 = ~(J1 ^ S) & 1; 2268 uint32_t I2 = ~(J2 ^ S) & 1; 2269 imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2270 imm32 = (imm32 << 8) >> 8; // sign extend 24 bit immediate. 2271 } else { 2272 uint32_t S = (instr >> 26) & 1; 2273 uint32_t J2 = (instr >> 11) & 1; 2274 uint32_t J1 = (instr >> 13) & 1; 2275 uint32_t imm6 = (instr >> 16) & 0x3F; 2276 uint32_t imm11 = instr & 0x7FF; 2277 2278 imm32 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2279 imm32 = (imm32 << 11) >> 11; // sign extend 21 bit immediate. 2280 } 2281 imm32 += 4; 2282 return imm32; 2283} 2284 2285 2286void Thumb2Assembler::AddConstant(Register rd, int32_t value, Condition cond) { 2287 AddConstant(rd, rd, value, cond); 2288} 2289 2290 2291void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value, 2292 Condition cond) { 2293 if (value == 0) { 2294 if (rd != rn) { 2295 mov(rd, ShifterOperand(rn), cond); 2296 } 2297 return; 2298 } 2299 // We prefer to select the shorter code sequence rather than selecting add for 2300 // positive values and sub for negatives ones, which would slightly improve 2301 // the readability of generated code for some constants. 2302 ShifterOperand shifter_op; 2303 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2304 add(rd, rn, shifter_op, cond); 2305 } else if (ShifterOperand::CanHoldThumb(rd, rn, SUB, -value, &shifter_op)) { 2306 sub(rd, rn, shifter_op, cond); 2307 } else { 2308 CHECK(rn != IP); 2309 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2310 mvn(IP, shifter_op, cond); 2311 add(rd, rn, ShifterOperand(IP), cond); 2312 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2313 mvn(IP, shifter_op, cond); 2314 sub(rd, rn, ShifterOperand(IP), cond); 2315 } else { 2316 movw(IP, Low16Bits(value), cond); 2317 uint16_t value_high = High16Bits(value); 2318 if (value_high != 0) { 2319 movt(IP, value_high, cond); 2320 } 2321 add(rd, rn, ShifterOperand(IP), cond); 2322 } 2323 } 2324} 2325 2326 2327void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value, 2328 Condition cond) { 2329 ShifterOperand shifter_op; 2330 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2331 adds(rd, rn, shifter_op, cond); 2332 } else if (ShifterOperand::CanHoldThumb(rd, rn, ADD, -value, &shifter_op)) { 2333 subs(rd, rn, shifter_op, cond); 2334 } else { 2335 CHECK(rn != IP); 2336 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2337 mvn(IP, shifter_op, cond); 2338 adds(rd, rn, ShifterOperand(IP), cond); 2339 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2340 mvn(IP, shifter_op, cond); 2341 subs(rd, rn, ShifterOperand(IP), cond); 2342 } else { 2343 movw(IP, Low16Bits(value), cond); 2344 uint16_t value_high = High16Bits(value); 2345 if (value_high != 0) { 2346 movt(IP, value_high, cond); 2347 } 2348 adds(rd, rn, ShifterOperand(IP), cond); 2349 } 2350 } 2351} 2352 2353 2354void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { 2355 ShifterOperand shifter_op; 2356 if (ShifterOperand::CanHoldThumb(rd, R0, MOV, value, &shifter_op)) { 2357 mov(rd, shifter_op, cond); 2358 } else if (ShifterOperand::CanHoldThumb(rd, R0, MVN, ~value, &shifter_op)) { 2359 mvn(rd, shifter_op, cond); 2360 } else { 2361 movw(rd, Low16Bits(value), cond); 2362 uint16_t value_high = High16Bits(value); 2363 if (value_high != 0) { 2364 movt(rd, value_high, cond); 2365 } 2366 } 2367} 2368 2369// Implementation note: this method must emit at most one instruction when 2370// Address::CanHoldLoadOffsetThumb. 2371void Thumb2Assembler::LoadFromOffset(LoadOperandType type, 2372 Register reg, 2373 Register base, 2374 int32_t offset, 2375 Condition cond) { 2376 if (!Address::CanHoldLoadOffsetThumb(type, offset)) { 2377 CHECK(base != IP); 2378 LoadImmediate(IP, offset, cond); 2379 add(IP, IP, ShifterOperand(base), cond); 2380 base = IP; 2381 offset = 0; 2382 } 2383 CHECK(Address::CanHoldLoadOffsetThumb(type, offset)); 2384 switch (type) { 2385 case kLoadSignedByte: 2386 ldrsb(reg, Address(base, offset), cond); 2387 break; 2388 case kLoadUnsignedByte: 2389 ldrb(reg, Address(base, offset), cond); 2390 break; 2391 case kLoadSignedHalfword: 2392 ldrsh(reg, Address(base, offset), cond); 2393 break; 2394 case kLoadUnsignedHalfword: 2395 ldrh(reg, Address(base, offset), cond); 2396 break; 2397 case kLoadWord: 2398 ldr(reg, Address(base, offset), cond); 2399 break; 2400 case kLoadWordPair: 2401 ldrd(reg, Address(base, offset), cond); 2402 break; 2403 default: 2404 LOG(FATAL) << "UNREACHABLE"; 2405 } 2406} 2407 2408 2409// Implementation note: this method must emit at most one instruction when 2410// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2411void Thumb2Assembler::LoadSFromOffset(SRegister reg, 2412 Register base, 2413 int32_t offset, 2414 Condition cond) { 2415 if (!Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)) { 2416 CHECK_NE(base, IP); 2417 LoadImmediate(IP, offset, cond); 2418 add(IP, IP, ShifterOperand(base), cond); 2419 base = IP; 2420 offset = 0; 2421 } 2422 CHECK(Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)); 2423 vldrs(reg, Address(base, offset), cond); 2424} 2425 2426 2427// Implementation note: this method must emit at most one instruction when 2428// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2429void Thumb2Assembler::LoadDFromOffset(DRegister reg, 2430 Register base, 2431 int32_t offset, 2432 Condition cond) { 2433 if (!Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)) { 2434 CHECK_NE(base, IP); 2435 LoadImmediate(IP, offset, cond); 2436 add(IP, IP, ShifterOperand(base), cond); 2437 base = IP; 2438 offset = 0; 2439 } 2440 CHECK(Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)); 2441 vldrd(reg, Address(base, offset), cond); 2442} 2443 2444 2445// Implementation note: this method must emit at most one instruction when 2446// Address::CanHoldStoreOffsetThumb. 2447void Thumb2Assembler::StoreToOffset(StoreOperandType type, 2448 Register reg, 2449 Register base, 2450 int32_t offset, 2451 Condition cond) { 2452 if (!Address::CanHoldStoreOffsetThumb(type, offset)) { 2453 CHECK(reg != IP); 2454 CHECK(base != IP); 2455 LoadImmediate(IP, offset, cond); 2456 add(IP, IP, ShifterOperand(base), cond); 2457 base = IP; 2458 offset = 0; 2459 } 2460 CHECK(Address::CanHoldStoreOffsetThumb(type, offset)); 2461 switch (type) { 2462 case kStoreByte: 2463 strb(reg, Address(base, offset), cond); 2464 break; 2465 case kStoreHalfword: 2466 strh(reg, Address(base, offset), cond); 2467 break; 2468 case kStoreWord: 2469 str(reg, Address(base, offset), cond); 2470 break; 2471 case kStoreWordPair: 2472 strd(reg, Address(base, offset), cond); 2473 break; 2474 default: 2475 LOG(FATAL) << "UNREACHABLE"; 2476 } 2477} 2478 2479 2480// Implementation note: this method must emit at most one instruction when 2481// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreToOffset. 2482void Thumb2Assembler::StoreSToOffset(SRegister reg, 2483 Register base, 2484 int32_t offset, 2485 Condition cond) { 2486 if (!Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)) { 2487 CHECK_NE(base, IP); 2488 LoadImmediate(IP, offset, cond); 2489 add(IP, IP, ShifterOperand(base), cond); 2490 base = IP; 2491 offset = 0; 2492 } 2493 CHECK(Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)); 2494 vstrs(reg, Address(base, offset), cond); 2495} 2496 2497 2498// Implementation note: this method must emit at most one instruction when 2499// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreSToOffset. 2500void Thumb2Assembler::StoreDToOffset(DRegister reg, 2501 Register base, 2502 int32_t offset, 2503 Condition cond) { 2504 if (!Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)) { 2505 CHECK_NE(base, IP); 2506 LoadImmediate(IP, offset, cond); 2507 add(IP, IP, ShifterOperand(base), cond); 2508 base = IP; 2509 offset = 0; 2510 } 2511 CHECK(Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)); 2512 vstrd(reg, Address(base, offset), cond); 2513} 2514 2515 2516void Thumb2Assembler::MemoryBarrier(ManagedRegister mscratch) { 2517 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12); 2518#if ANDROID_SMP != 0 2519 int32_t encoding = 0xf3bf8f5f; // dmb in T1 encoding. 2520 Emit32(encoding); 2521#endif 2522} 2523 2524 2525void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) { 2526 if (force_32bit_branches_) { 2527 cmp(r, ShifterOperand(0)); 2528 b(label, EQ); 2529 } else { 2530 cbz(r, label); 2531 } 2532} 2533 2534 2535void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) { 2536 if (force_32bit_branches_) { 2537 cmp(r, ShifterOperand(0)); 2538 b(label, NE); 2539 } else { 2540 cbnz(r, label); 2541 } 2542} 2543} // namespace arm 2544} // namespace art 2545