assembler_thumb2.cc revision 20dfc797dc631bf8d655dcf123f46f13332d3074
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 == IA_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 == DB || am == DB_W); 356 Address::Mode strmode = am == DB_W ? 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 return false; // 16 bit good. 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) && rn == SP) { 762 // There are special ADD/SUB rd, SP, #imm12 instructions. 763 if (opcode == SUB) { 764 thumb_opcode = 0b0101; 765 } else { 766 thumb_opcode = 0; 767 } 768 uint32_t imm = so.GetImmediate(); 769 CHECK_LT(imm, (1u << 12)); 770 771 uint32_t i = (imm >> 11) & 1; 772 uint32_t imm3 = (imm >> 8) & 0b111; 773 uint32_t imm8 = imm & 0xff; 774 775 encoding = B31 | B30 | B29 | B28 | B25 | 776 B19 | B18 | B16 | 777 thumb_opcode << 21 | 778 rd << 8 | 779 i << 26 | 780 imm3 << 12 | 781 imm8; 782 } else { 783 // Modified immediate. 784 uint32_t imm = ModifiedImmediate(so.encodingThumb(2)); 785 if (imm == kInvalidModifiedImmediate) { 786 LOG(FATAL) << "Immediate value cannot fit in thumb2 modified immediate"; 787 } 788 encoding = B31 | B30 | B29 | B28 | 789 thumb_opcode << 21 | 790 set_cc << 20 | 791 rn << 16 | 792 rd << 8 | 793 imm; 794 } 795 } else if (so.IsRegister()) { 796 // Register (possibly shifted) 797 encoding = B31 | B30 | B29 | B27 | B25 | 798 thumb_opcode << 21 | 799 set_cc << 20 | 800 rn << 16 | 801 rd << 8 | 802 so.encodingThumb(2); 803 } 804 Emit32(encoding); 805} 806 807 808void Thumb2Assembler::Emit16BitDataProcessing(Condition cond, 809 Opcode opcode, 810 int set_cc, 811 Register rn, 812 Register rd, 813 const ShifterOperand& so) { 814 if (opcode == ADD || opcode == SUB) { 815 Emit16BitAddSub(cond, opcode, set_cc, rn, rd, so); 816 return; 817 } 818 uint8_t thumb_opcode = 0b11111111; 819 // Thumb1. 820 uint8_t dp_opcode = 0b01; 821 uint8_t opcode_shift = 6; 822 uint8_t rd_shift = 0; 823 uint8_t rn_shift = 3; 824 uint8_t immediate_shift = 0; 825 bool use_immediate = false; 826 uint8_t immediate = 0; 827 828 if (opcode == MOV && so.IsRegister() && so.IsShift()) { 829 // Convert shifted mov operand2 into 16 bit opcodes. 830 dp_opcode = 0; 831 opcode_shift = 11; 832 833 use_immediate = true; 834 immediate = so.GetImmediate(); 835 immediate_shift = 6; 836 837 rn = so.GetRegister(); 838 839 switch (so.GetShift()) { 840 case LSL: thumb_opcode = 0b00; break; 841 case LSR: thumb_opcode = 0b01; break; 842 case ASR: thumb_opcode = 0b10; break; 843 case ROR: 844 // ROR doesn't allow immediates. 845 thumb_opcode = 0b111; 846 dp_opcode = 0b01; 847 opcode_shift = 6; 848 use_immediate = false; 849 break; 850 case RRX: break; 851 default: 852 break; 853 } 854 } else { 855 if (so.IsImmediate()) { 856 use_immediate = true; 857 immediate = so.GetImmediate(); 858 } 859 860 switch (opcode) { 861 case AND: thumb_opcode = 0b0000; break; 862 case EOR: thumb_opcode = 0b0001; break; 863 case SUB: break; 864 case RSB: thumb_opcode = 0b1001; break; 865 case ADD: break; 866 case ADC: thumb_opcode = 0b0101; break; 867 case SBC: thumb_opcode = 0b0110; break; 868 case RSC: break; 869 case TST: thumb_opcode = 0b1000; rn = so.GetRegister(); break; 870 case TEQ: break; 871 case CMP: 872 if (use_immediate) { 873 // T2 encoding. 874 dp_opcode = 0; 875 opcode_shift = 11; 876 thumb_opcode = 0b101; 877 rd_shift = 8; 878 rn_shift = 8; 879 } else { 880 thumb_opcode = 0b1010; 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 1084 1085void Thumb2Assembler::Branch::Emit(AssemblerBuffer* buffer) const { 1086 bool link = type_ == kUnconditionalLinkX || type_ == kUnconditionalLink; 1087 bool x = type_ == kUnconditionalX || type_ == kUnconditionalLinkX; 1088 int32_t offset = target_ - location_; 1089 1090 if (size_ == k32Bit) { 1091 int32_t encoding = B31 | B30 | B29 | B28 | B15; 1092 if (link) { 1093 // BL or BLX immediate. 1094 encoding |= B14; 1095 if (!x) { 1096 encoding |= B12; 1097 } else { 1098 // Bottom bit of offset must be 0. 1099 CHECK_EQ((offset & 1), 0); 1100 } 1101 } else { 1102 if (x) { 1103 LOG(FATAL) << "Invalid use of BX"; 1104 } else { 1105 if (cond_ == AL) { 1106 // Can use the T4 encoding allowing a 24 bit offset. 1107 if (!x) { 1108 encoding |= B12; 1109 } 1110 } else { 1111 // Must be T3 encoding with a 20 bit offset. 1112 encoding |= cond_ << 22; 1113 } 1114 } 1115 } 1116 encoding = Thumb2Assembler::EncodeBranchOffset(offset, encoding); 1117 buffer->Store<int16_t>(location_, static_cast<int16_t>(encoding >> 16)); 1118 buffer->Store<int16_t>(location_+2, static_cast<int16_t>(encoding & 0xffff)); 1119 } else { 1120 if (IsCompareAndBranch()) { 1121 offset -= 4; 1122 uint16_t i = (offset >> 6) & 1; 1123 uint16_t imm5 = (offset >> 1) & 0b11111; 1124 int16_t encoding = B15 | B13 | B12 | 1125 (type_ == kCompareAndBranchNonZero ? B11 : 0) | 1126 static_cast<uint32_t>(rn_) | 1127 B8 | 1128 i << 9 | 1129 imm5 << 3; 1130 buffer->Store<int16_t>(location_, encoding); 1131 } else { 1132 offset -= 4; // Account for PC offset. 1133 int16_t encoding; 1134 // 16 bit. 1135 if (cond_ == AL) { 1136 encoding = B15 | B14 | B13 | 1137 ((offset >> 1) & 0x7ff); 1138 } else { 1139 encoding = B15 | B14 | B12 | 1140 cond_ << 8 | ((offset >> 1) & 0xff); 1141 } 1142 buffer->Store<int16_t>(location_, encoding); 1143 } 1144 } 1145} 1146 1147 1148uint16_t Thumb2Assembler::EmitCompareAndBranch(Register rn, uint16_t prev, bool n) { 1149 uint32_t location = buffer_.Size(); 1150 1151 // This is always unresolved as it must be a forward branch. 1152 Emit16(prev); // Previous link. 1153 return AddBranch(n ? Branch::kCompareAndBranchNonZero : Branch::kCompareAndBranchZero, 1154 location, rn); 1155} 1156 1157 1158// NOTE: this only support immediate offsets, not [rx,ry]. 1159// TODO: support [rx,ry] instructions. 1160void Thumb2Assembler::EmitLoadStore(Condition cond, 1161 bool load, 1162 bool byte, 1163 bool half, 1164 bool is_signed, 1165 Register rd, 1166 const Address& ad) { 1167 CHECK_NE(rd, kNoRegister); 1168 CheckCondition(cond); 1169 bool must_be_32bit = force_32bit_; 1170 if (IsHighRegister(rd)) { 1171 must_be_32bit = true; 1172 } 1173 1174 Register rn = ad.GetRegister(); 1175 if (IsHighRegister(rn) && rn != SP) { 1176 must_be_32bit = true; 1177 } 1178 1179 if (is_signed || ad.GetOffset() < 0 || ad.GetMode() != Address::Offset) { 1180 must_be_32bit = true; 1181 } 1182 1183 int32_t offset = ad.GetOffset(); 1184 1185 // The 16 bit SP relative instruction can only have a 10 bit offset. 1186 if (rn == SP && offset > 1024) { 1187 must_be_32bit = true; 1188 } 1189 1190 if (byte) { 1191 // 5 bit offset, no shift. 1192 if (offset > 32) { 1193 must_be_32bit = true; 1194 } 1195 } else if (half) { 1196 // 6 bit offset, shifted by 1. 1197 if (offset > 64) { 1198 must_be_32bit = true; 1199 } 1200 } else { 1201 // 7 bit offset, shifted by 2. 1202 if (offset > 128) { 1203 must_be_32bit = true; 1204 } 1205 } 1206 1207 if (must_be_32bit) { 1208 int32_t encoding = B31 | B30 | B29 | B28 | B27 | 1209 (load ? B20 : 0) | 1210 (is_signed ? B24 : 0) | 1211 static_cast<uint32_t>(rd) << 12 | 1212 ad.encodingThumb(2) | 1213 (byte ? 0 : half ? B21 : B22); 1214 Emit32(encoding); 1215 } else { 1216 // 16 bit thumb1. 1217 uint8_t opA = 0; 1218 bool sp_relative = false; 1219 1220 if (byte) { 1221 opA = 0b0111; 1222 } else if (half) { 1223 opA = 0b1000; 1224 } else { 1225 if (rn == SP) { 1226 opA = 0b1001; 1227 sp_relative = true; 1228 } else { 1229 opA = 0b0110; 1230 } 1231 } 1232 int16_t encoding = opA << 12 | 1233 (load ? B11 : 0); 1234 1235 CHECK_GE(offset, 0); 1236 if (sp_relative) { 1237 // SP relative, 10 bit offset. 1238 CHECK_LT(offset, 1024); 1239 CHECK_EQ((offset & 0b11), 0); 1240 encoding |= rd << 8 | offset >> 2; 1241 } else { 1242 // No SP relative. The offset is shifted right depending on 1243 // the size of the load/store. 1244 encoding |= static_cast<uint32_t>(rd); 1245 1246 if (byte) { 1247 // 5 bit offset, no shift. 1248 CHECK_LT(offset, 32); 1249 } else if (half) { 1250 // 6 bit offset, shifted by 1. 1251 CHECK_LT(offset, 64); 1252 CHECK_EQ((offset & 0b1), 0); 1253 offset >>= 1; 1254 } else { 1255 // 7 bit offset, shifted by 2. 1256 CHECK_LT(offset, 128); 1257 CHECK_EQ((offset & 0b11), 0); 1258 offset >>= 2; 1259 } 1260 encoding |= rn << 3 | offset << 6; 1261 } 1262 1263 Emit16(encoding); 1264 } 1265} 1266 1267 1268void Thumb2Assembler::EmitMultiMemOp(Condition cond, 1269 BlockAddressMode am, 1270 bool load, 1271 Register base, 1272 RegList regs) { 1273 CHECK_NE(base, kNoRegister); 1274 CheckCondition(cond); 1275 bool must_be_32bit = force_32bit_; 1276 1277 if ((regs & 0xff00) != 0) { 1278 must_be_32bit = true; 1279 } 1280 1281 uint32_t w_bit = am == IA_W || am == DB_W || am == DA_W || am == IB_W; 1282 // 16 bit always uses writeback. 1283 if (!w_bit) { 1284 must_be_32bit = true; 1285 } 1286 1287 if (must_be_32bit) { 1288 uint32_t op = 0; 1289 switch (am) { 1290 case IA: 1291 case IA_W: 1292 op = 0b01; 1293 break; 1294 case DB: 1295 case DB_W: 1296 op = 0b10; 1297 break; 1298 case DA: 1299 case IB: 1300 case DA_W: 1301 case IB_W: 1302 LOG(FATAL) << "LDM/STM mode not supported on thumb: " << am; 1303 } 1304 if (load) { 1305 // Cannot have SP in the list. 1306 CHECK_EQ((regs & (1 << SP)), 0); 1307 } else { 1308 // Cannot have PC or SP in the list. 1309 CHECK_EQ((regs & (1 << PC | 1 << SP)), 0); 1310 } 1311 int32_t encoding = B31 | B30 | B29 | B27 | 1312 (op << 23) | 1313 (load ? B20 : 0) | 1314 base << 16 | 1315 regs | 1316 (w_bit << 21); 1317 Emit32(encoding); 1318 } else { 1319 int16_t encoding = B15 | B14 | 1320 (load ? B11 : 0) | 1321 base << 8 | 1322 regs; 1323 Emit16(encoding); 1324 } 1325} 1326 1327 1328void Thumb2Assembler::EmitBranch(Condition cond, Label* label, bool link, bool x) { 1329 uint32_t pc = buffer_.Size(); 1330 Branch::Type branch_type; 1331 if (cond == AL) { 1332 if (link) { 1333 if (x) { 1334 branch_type = Branch::kUnconditionalLinkX; // BLX. 1335 } else { 1336 branch_type = Branch::kUnconditionalLink; // BX. 1337 } 1338 } else { 1339 branch_type = Branch::kUnconditional; // B. 1340 } 1341 } else { 1342 branch_type = Branch::kConditional; // B<cond>. 1343 } 1344 1345 if (label->IsBound()) { 1346 Branch::Size size = AddBranch(branch_type, pc, label->Position(), cond); // Resolved branch. 1347 1348 // The branch is to a bound label which means that it's a backwards branch. We know the 1349 // current size of it so we can emit the appropriate space. Note that if it's a 16 bit 1350 // branch the size may change if it so happens that other branches change size that change 1351 // the distance to the target and that distance puts this branch over the limit for 16 bits. 1352 if (size == Branch::k16Bit) { 1353 Emit16(0); // Space for a 16 bit branch. 1354 } else { 1355 Emit32(0); // Space for a 32 bit branch. 1356 } 1357 } else { 1358 // Branch is to an unbound label. Emit space for it. 1359 uint16_t branch_id = AddBranch(branch_type, pc, cond); // Unresolved branch. 1360 if (force_32bit_) { 1361 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1362 Emit16(0); // another 16 bits. 1363 } else { 1364 Emit16(static_cast<uint16_t>(label->position_)); // Emit current label link. 1365 } 1366 label->LinkTo(branch_id); // Link to the branch ID. 1367 } 1368} 1369 1370 1371void Thumb2Assembler::clz(Register rd, Register rm, Condition cond) { 1372 CHECK_NE(rd, kNoRegister); 1373 CHECK_NE(rm, kNoRegister); 1374 CheckCondition(cond); 1375 CHECK_NE(rd, PC); 1376 CHECK_NE(rm, PC); 1377 int32_t encoding = B31 | B30 | B29 | B28 | B27 | 1378 B25 | B23 | B21 | B20 | 1379 static_cast<uint32_t>(rm) << 16 | 1380 0xf << 12 | 1381 static_cast<uint32_t>(rd) << 8 | 1382 B7 | 1383 static_cast<uint32_t>(rm); 1384 Emit32(encoding); 1385} 1386 1387 1388void Thumb2Assembler::movw(Register rd, uint16_t imm16, Condition cond) { 1389 CheckCondition(cond); 1390 bool must_be_32bit = force_32bit_; 1391 if (IsHighRegister(rd)|| imm16 >= 256u) { 1392 must_be_32bit = true; 1393 } 1394 1395 if (must_be_32bit) { 1396 // Use encoding T3. 1397 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1398 uint32_t i = (imm16 >> 11) & 0b1; 1399 uint32_t imm3 = (imm16 >> 8) & 0b111; 1400 uint32_t imm8 = imm16 & 0xff; 1401 int32_t encoding = B31 | B30 | B29 | B28 | 1402 B25 | B22 | 1403 static_cast<uint32_t>(rd) << 8 | 1404 i << 26 | 1405 imm4 << 16 | 1406 imm3 << 12 | 1407 imm8; 1408 Emit32(encoding); 1409 } else { 1410 int16_t encoding = B13 | static_cast<uint16_t>(rd) << 8 | 1411 imm16; 1412 Emit16(encoding); 1413 } 1414} 1415 1416 1417void Thumb2Assembler::movt(Register rd, uint16_t imm16, Condition cond) { 1418 CheckCondition(cond); 1419 // Always 32 bits. 1420 uint32_t imm4 = (imm16 >> 12) & 0b1111; 1421 uint32_t i = (imm16 >> 11) & 0b1; 1422 uint32_t imm3 = (imm16 >> 8) & 0b111; 1423 uint32_t imm8 = imm16 & 0xff; 1424 int32_t encoding = B31 | B30 | B29 | B28 | 1425 B25 | B23 | B22 | 1426 static_cast<uint32_t>(rd) << 8 | 1427 i << 26 | 1428 imm4 << 16 | 1429 imm3 << 12 | 1430 imm8; 1431 Emit32(encoding); 1432} 1433 1434 1435void Thumb2Assembler::ldrex(Register rt, Register rn, uint16_t imm, Condition cond) { 1436 CHECK_NE(rn, kNoRegister); 1437 CHECK_NE(rt, kNoRegister); 1438 CheckCondition(cond); 1439 CHECK_NE(rn, kNoRegister); 1440 CHECK_NE(rt, kNoRegister); 1441 CheckCondition(cond); 1442 CHECK_LT(imm, (1u << 10)); 1443 1444 int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 | 1445 static_cast<uint32_t>(rn) << 16 | 1446 static_cast<uint32_t>(rt) << 12 | 1447 0xf << 8 | 1448 imm >> 2; 1449 Emit32(encoding); 1450} 1451 1452 1453void Thumb2Assembler::ldrex(Register rt, Register rn, Condition cond) { 1454 ldrex(rt, rn, 0, cond); 1455} 1456 1457 1458void Thumb2Assembler::strex(Register rd, 1459 Register rt, 1460 Register rn, 1461 uint16_t imm, 1462 Condition cond) { 1463 CHECK_NE(rn, kNoRegister); 1464 CHECK_NE(rd, kNoRegister); 1465 CHECK_NE(rt, kNoRegister); 1466 CheckCondition(cond); 1467 CHECK_LT(imm, (1u << 10)); 1468 1469 int32_t encoding = B31 | B30 | B29 | B27 | B22 | 1470 static_cast<uint32_t>(rn) << 16 | 1471 static_cast<uint32_t>(rt) << 12 | 1472 static_cast<uint32_t>(rd) << 8 | 1473 imm >> 2; 1474 Emit32(encoding); 1475} 1476 1477 1478void Thumb2Assembler::strex(Register rd, 1479 Register rt, 1480 Register rn, 1481 Condition cond) { 1482 strex(rd, rt, rn, 0, cond); 1483} 1484 1485 1486void Thumb2Assembler::clrex(Condition cond) { 1487 CheckCondition(cond); 1488 int32_t encoding = B31 | B30 | B29 | B27 | B28 | B25 | B24 | B23 | 1489 B21 | B20 | 1490 0xf << 16 | 1491 B15 | 1492 0xf << 8 | 1493 B5 | 1494 0xf; 1495 Emit32(encoding); 1496} 1497 1498 1499void Thumb2Assembler::nop(Condition cond) { 1500 CheckCondition(cond); 1501 int16_t encoding = B15 | B13 | B12 | 1502 B11 | B10 | B9 | B8; 1503 Emit16(encoding); 1504} 1505 1506 1507void Thumb2Assembler::vmovsr(SRegister sn, Register rt, Condition cond) { 1508 CHECK_NE(sn, kNoSRegister); 1509 CHECK_NE(rt, kNoRegister); 1510 CHECK_NE(rt, SP); 1511 CHECK_NE(rt, PC); 1512 CheckCondition(cond); 1513 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1514 B27 | B26 | B25 | 1515 ((static_cast<int32_t>(sn) >> 1)*B16) | 1516 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1517 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1518 Emit32(encoding); 1519} 1520 1521 1522void Thumb2Assembler::vmovrs(Register rt, SRegister sn, Condition cond) { 1523 CHECK_NE(sn, kNoSRegister); 1524 CHECK_NE(rt, kNoRegister); 1525 CHECK_NE(rt, SP); 1526 CHECK_NE(rt, PC); 1527 CheckCondition(cond); 1528 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1529 B27 | B26 | B25 | B20 | 1530 ((static_cast<int32_t>(sn) >> 1)*B16) | 1531 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1532 ((static_cast<int32_t>(sn) & 1)*B7) | B4; 1533 Emit32(encoding); 1534} 1535 1536 1537void Thumb2Assembler::vmovsrr(SRegister sm, Register rt, Register rt2, 1538 Condition cond) { 1539 CHECK_NE(sm, kNoSRegister); 1540 CHECK_NE(sm, S31); 1541 CHECK_NE(rt, kNoRegister); 1542 CHECK_NE(rt, SP); 1543 CHECK_NE(rt, PC); 1544 CHECK_NE(rt2, kNoRegister); 1545 CHECK_NE(rt2, SP); 1546 CHECK_NE(rt2, PC); 1547 CheckCondition(cond); 1548 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1549 B27 | B26 | B22 | 1550 (static_cast<int32_t>(rt2)*B16) | 1551 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1552 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1553 (static_cast<int32_t>(sm) >> 1); 1554 Emit32(encoding); 1555} 1556 1557 1558void Thumb2Assembler::vmovrrs(Register rt, Register rt2, SRegister sm, 1559 Condition cond) { 1560 CHECK_NE(sm, kNoSRegister); 1561 CHECK_NE(sm, S31); 1562 CHECK_NE(rt, kNoRegister); 1563 CHECK_NE(rt, SP); 1564 CHECK_NE(rt, PC); 1565 CHECK_NE(rt2, kNoRegister); 1566 CHECK_NE(rt2, SP); 1567 CHECK_NE(rt2, PC); 1568 CHECK_NE(rt, rt2); 1569 CheckCondition(cond); 1570 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1571 B27 | B26 | B22 | B20 | 1572 (static_cast<int32_t>(rt2)*B16) | 1573 (static_cast<int32_t>(rt)*B12) | B11 | B9 | 1574 ((static_cast<int32_t>(sm) & 1)*B5) | B4 | 1575 (static_cast<int32_t>(sm) >> 1); 1576 Emit32(encoding); 1577} 1578 1579 1580void Thumb2Assembler::vmovdrr(DRegister dm, Register rt, Register rt2, 1581 Condition cond) { 1582 CHECK_NE(dm, kNoDRegister); 1583 CHECK_NE(rt, kNoRegister); 1584 CHECK_NE(rt, SP); 1585 CHECK_NE(rt, PC); 1586 CHECK_NE(rt2, kNoRegister); 1587 CHECK_NE(rt2, SP); 1588 CHECK_NE(rt2, PC); 1589 CheckCondition(cond); 1590 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1591 B27 | B26 | B22 | 1592 (static_cast<int32_t>(rt2)*B16) | 1593 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1594 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1595 (static_cast<int32_t>(dm) & 0xf); 1596 Emit32(encoding); 1597} 1598 1599 1600void Thumb2Assembler::vmovrrd(Register rt, Register rt2, DRegister dm, 1601 Condition cond) { 1602 CHECK_NE(dm, kNoDRegister); 1603 CHECK_NE(rt, kNoRegister); 1604 CHECK_NE(rt, SP); 1605 CHECK_NE(rt, PC); 1606 CHECK_NE(rt2, kNoRegister); 1607 CHECK_NE(rt2, SP); 1608 CHECK_NE(rt2, PC); 1609 CHECK_NE(rt, rt2); 1610 CheckCondition(cond); 1611 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1612 B27 | B26 | B22 | B20 | 1613 (static_cast<int32_t>(rt2)*B16) | 1614 (static_cast<int32_t>(rt)*B12) | B11 | B9 | B8 | 1615 ((static_cast<int32_t>(dm) >> 4)*B5) | B4 | 1616 (static_cast<int32_t>(dm) & 0xf); 1617 Emit32(encoding); 1618} 1619 1620 1621void Thumb2Assembler::vldrs(SRegister sd, const Address& ad, Condition cond) { 1622 const Address& addr = static_cast<const Address&>(ad); 1623 CHECK_NE(sd, kNoSRegister); 1624 CheckCondition(cond); 1625 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1626 B27 | B26 | B24 | B20 | 1627 ((static_cast<int32_t>(sd) & 1)*B22) | 1628 ((static_cast<int32_t>(sd) >> 1)*B12) | 1629 B11 | B9 | addr.vencoding(); 1630 Emit32(encoding); 1631} 1632 1633 1634void Thumb2Assembler::vstrs(SRegister sd, const Address& ad, Condition cond) { 1635 const Address& addr = static_cast<const Address&>(ad); 1636 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1637 CHECK_NE(sd, kNoSRegister); 1638 CheckCondition(cond); 1639 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1640 B27 | B26 | B24 | 1641 ((static_cast<int32_t>(sd) & 1)*B22) | 1642 ((static_cast<int32_t>(sd) >> 1)*B12) | 1643 B11 | B9 | addr.vencoding(); 1644 Emit32(encoding); 1645} 1646 1647 1648void Thumb2Assembler::vldrd(DRegister dd, const Address& ad, Condition cond) { 1649 const Address& addr = static_cast<const Address&>(ad); 1650 CHECK_NE(dd, kNoDRegister); 1651 CheckCondition(cond); 1652 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1653 B27 | B26 | B24 | B20 | 1654 ((static_cast<int32_t>(dd) >> 4)*B22) | 1655 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1656 B11 | B9 | B8 | addr.vencoding(); 1657 Emit32(encoding); 1658} 1659 1660 1661void Thumb2Assembler::vstrd(DRegister dd, const Address& ad, Condition cond) { 1662 const Address& addr = static_cast<const Address&>(ad); 1663 CHECK_NE(static_cast<Register>(addr.encodingArm() & (0xf << kRnShift)), PC); 1664 CHECK_NE(dd, kNoDRegister); 1665 CheckCondition(cond); 1666 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1667 B27 | B26 | B24 | 1668 ((static_cast<int32_t>(dd) >> 4)*B22) | 1669 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1670 B11 | B9 | B8 | addr.vencoding(); 1671 Emit32(encoding); 1672} 1673 1674 1675void Thumb2Assembler::vpushs(SRegister reg, int nregs, Condition cond) { 1676 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, false, cond); 1677} 1678 1679 1680void Thumb2Assembler::vpushd(DRegister reg, int nregs, Condition cond) { 1681 EmitVPushPop(static_cast<uint32_t>(reg), nregs, true, true, cond); 1682} 1683 1684 1685void Thumb2Assembler::vpops(SRegister reg, int nregs, Condition cond) { 1686 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, false, cond); 1687} 1688 1689 1690void Thumb2Assembler::vpopd(DRegister reg, int nregs, Condition cond) { 1691 EmitVPushPop(static_cast<uint32_t>(reg), nregs, false, true, cond); 1692} 1693 1694 1695void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) { 1696 CheckCondition(cond); 1697 1698 uint32_t D; 1699 uint32_t Vd; 1700 if (dbl) { 1701 // Encoded as D:Vd. 1702 D = (reg >> 4) & 1; 1703 Vd = reg & 0b1111; 1704 } else { 1705 // Encoded as Vd:D. 1706 D = reg & 1; 1707 Vd = (reg >> 1) & 0b1111; 1708 } 1709 int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 | 1710 B11 | B9 | 1711 (dbl ? B8 : 0) | 1712 (push ? B24 : (B23 | B20)) | 1713 0b1110 << 28 | 1714 nregs << (dbl ? 1 : 0) | 1715 D << 22 | 1716 Vd << 12; 1717 Emit32(encoding); 1718} 1719 1720 1721void Thumb2Assembler::EmitVFPsss(Condition cond, int32_t opcode, 1722 SRegister sd, SRegister sn, SRegister sm) { 1723 CHECK_NE(sd, kNoSRegister); 1724 CHECK_NE(sn, kNoSRegister); 1725 CHECK_NE(sm, kNoSRegister); 1726 CheckCondition(cond); 1727 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1728 B27 | B26 | B25 | B11 | B9 | opcode | 1729 ((static_cast<int32_t>(sd) & 1)*B22) | 1730 ((static_cast<int32_t>(sn) >> 1)*B16) | 1731 ((static_cast<int32_t>(sd) >> 1)*B12) | 1732 ((static_cast<int32_t>(sn) & 1)*B7) | 1733 ((static_cast<int32_t>(sm) & 1)*B5) | 1734 (static_cast<int32_t>(sm) >> 1); 1735 Emit32(encoding); 1736} 1737 1738 1739void Thumb2Assembler::EmitVFPddd(Condition cond, int32_t opcode, 1740 DRegister dd, DRegister dn, DRegister dm) { 1741 CHECK_NE(dd, kNoDRegister); 1742 CHECK_NE(dn, kNoDRegister); 1743 CHECK_NE(dm, kNoDRegister); 1744 CheckCondition(cond); 1745 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1746 B27 | B26 | B25 | B11 | B9 | B8 | opcode | 1747 ((static_cast<int32_t>(dd) >> 4)*B22) | 1748 ((static_cast<int32_t>(dn) & 0xf)*B16) | 1749 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1750 ((static_cast<int32_t>(dn) >> 4)*B7) | 1751 ((static_cast<int32_t>(dm) >> 4)*B5) | 1752 (static_cast<int32_t>(dm) & 0xf); 1753 Emit32(encoding); 1754} 1755 1756 1757void Thumb2Assembler::EmitVFPsd(Condition cond, int32_t opcode, 1758 SRegister sd, DRegister dm) { 1759 CHECK_NE(sd, kNoSRegister); 1760 CHECK_NE(dm, kNoDRegister); 1761 CheckCondition(cond); 1762 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1763 B27 | B26 | B25 | B11 | B9 | opcode | 1764 ((static_cast<int32_t>(sd) & 1)*B22) | 1765 ((static_cast<int32_t>(sd) >> 1)*B12) | 1766 ((static_cast<int32_t>(dm) >> 4)*B5) | 1767 (static_cast<int32_t>(dm) & 0xf); 1768 Emit32(encoding); 1769} 1770 1771 1772void Thumb2Assembler::EmitVFPds(Condition cond, int32_t opcode, 1773 DRegister dd, SRegister sm) { 1774 CHECK_NE(dd, kNoDRegister); 1775 CHECK_NE(sm, kNoSRegister); 1776 CheckCondition(cond); 1777 int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) | 1778 B27 | B26 | B25 | B11 | B9 | opcode | 1779 ((static_cast<int32_t>(dd) >> 4)*B22) | 1780 ((static_cast<int32_t>(dd) & 0xf)*B12) | 1781 ((static_cast<int32_t>(sm) & 1)*B5) | 1782 (static_cast<int32_t>(sm) >> 1); 1783 Emit32(encoding); 1784} 1785 1786 1787void Thumb2Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR. 1788 CheckCondition(cond); 1789 UNIMPLEMENTED(FATAL) << "Unimplemented thumb instruction"; 1790} 1791 1792 1793void Thumb2Assembler::svc(uint32_t imm8) { 1794 CHECK(IsUint(8, imm8)) << imm8; 1795 int16_t encoding = B15 | B14 | B12 | 1796 B11 | B10 | B9 | B8 | 1797 imm8; 1798 Emit16(encoding); 1799} 1800 1801 1802void Thumb2Assembler::bkpt(uint16_t imm8) { 1803 CHECK(IsUint(8, imm8)) << imm8; 1804 int16_t encoding = B15 | B13 | B12 | 1805 B11 | B10 | B9 | 1806 imm8; 1807 Emit16(encoding); 1808} 1809 1810// Convert the given IT state to a mask bit given bit 0 of the first 1811// condition and a shift position. 1812static uint8_t ToItMask(ItState s, uint8_t firstcond0, uint8_t shift) { 1813 switch (s) { 1814 case kItOmitted: return 1 << shift; 1815 case kItThen: return firstcond0 << shift; 1816 case kItElse: return !firstcond0 << shift; 1817 } 1818 return 0; 1819} 1820 1821 1822// Set the IT condition in the given position for the given state. This is used 1823// to check that conditional instructions match the preceding IT statement. 1824void Thumb2Assembler::SetItCondition(ItState s, Condition cond, uint8_t index) { 1825 switch (s) { 1826 case kItOmitted: it_conditions_[index] = AL; break; 1827 case kItThen: it_conditions_[index] = cond; break; 1828 case kItElse: 1829 it_conditions_[index] = static_cast<Condition>(static_cast<uint8_t>(cond) ^ 1); 1830 break; 1831 } 1832} 1833 1834 1835void Thumb2Assembler::it(Condition firstcond, ItState i1, ItState i2, ItState i3) { 1836 CheckCondition(AL); // Not allowed in IT block. 1837 uint8_t firstcond0 = static_cast<uint8_t>(firstcond) & 1; 1838 1839 // All conditions to AL. 1840 for (uint8_t i = 0; i < 4; ++i) { 1841 it_conditions_[i] = AL; 1842 } 1843 1844 SetItCondition(kItThen, firstcond, 0); 1845 uint8_t mask = ToItMask(i1, firstcond0, 3); 1846 SetItCondition(i1, firstcond, 1); 1847 1848 if (i1 != kItOmitted) { 1849 mask |= ToItMask(i2, firstcond0, 2); 1850 SetItCondition(i2, firstcond, 2); 1851 if (i2 != kItOmitted) { 1852 mask |= ToItMask(i3, firstcond0, 1); 1853 SetItCondition(i3, firstcond, 3); 1854 if (i3 != kItOmitted) { 1855 mask |= 0b0001; 1856 } 1857 } 1858 } 1859 1860 // Start at first condition. 1861 it_cond_index_ = 0; 1862 next_condition_ = it_conditions_[0]; 1863 uint16_t encoding = B15 | B13 | B12 | 1864 B11 | B10 | B9 | B8 | 1865 firstcond << 4 | 1866 mask; 1867 Emit16(encoding); 1868} 1869 1870 1871void Thumb2Assembler::cbz(Register rn, Label* label) { 1872 CheckCondition(AL); 1873 if (label->IsBound()) { 1874 LOG(FATAL) << "cbz can only be used to branch forwards"; 1875 } else { 1876 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), false); 1877 label->LinkTo(branchid); 1878 } 1879} 1880 1881 1882void Thumb2Assembler::cbnz(Register rn, Label* label) { 1883 CheckCondition(AL); 1884 if (label->IsBound()) { 1885 LOG(FATAL) << "cbnz can only be used to branch forwards"; 1886 } else { 1887 uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), true); 1888 label->LinkTo(branchid); 1889 } 1890} 1891 1892 1893void Thumb2Assembler::blx(Register rm, Condition cond) { 1894 CHECK_NE(rm, kNoRegister); 1895 CheckCondition(cond); 1896 int16_t encoding = B14 | B10 | B9 | B8 | B7 | static_cast<int16_t>(rm) << 3; 1897 Emit16(encoding); 1898} 1899 1900 1901void Thumb2Assembler::bx(Register rm, Condition cond) { 1902 CHECK_NE(rm, kNoRegister); 1903 CheckCondition(cond); 1904 int16_t encoding = B14 | B10 | B9 | B8 | static_cast<int16_t>(rm) << 3; 1905 Emit16(encoding); 1906} 1907 1908 1909void Thumb2Assembler::Push(Register rd, Condition cond) { 1910 str(rd, Address(SP, -kRegisterSize, Address::PreIndex), cond); 1911} 1912 1913 1914void Thumb2Assembler::Pop(Register rd, Condition cond) { 1915 ldr(rd, Address(SP, kRegisterSize, Address::PostIndex), cond); 1916} 1917 1918 1919void Thumb2Assembler::PushList(RegList regs, Condition cond) { 1920 stm(DB_W, SP, regs, cond); 1921} 1922 1923 1924void Thumb2Assembler::PopList(RegList regs, Condition cond) { 1925 ldm(IA_W, SP, regs, cond); 1926} 1927 1928 1929void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) { 1930 if (cond != AL || rd != rm) { 1931 mov(rd, ShifterOperand(rm), cond); 1932 } 1933} 1934 1935 1936// A branch has changed size. Make a hole for it. 1937void Thumb2Assembler::MakeHoleForBranch(uint32_t location, uint32_t delta) { 1938 // Move the contents of the buffer using: Move(newposition, oldposition) 1939 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 1940 buffer_.Move(location + delta, location); 1941} 1942 1943 1944void Thumb2Assembler::Bind(Label* label) { 1945 CHECK(!label->IsBound()); 1946 uint32_t bound_pc = buffer_.Size(); 1947 std::vector<Branch*> changed_branches; 1948 1949 while (label->IsLinked()) { 1950 uint16_t position = label->Position(); // Branch id for linked branch. 1951 Branch* branch = GetBranch(position); // Get the branch at this id. 1952 bool changed = branch->Resolve(bound_pc); // Branch can be resolved now. 1953 uint32_t branch_location = branch->GetLocation(); 1954 uint16_t next = buffer_.Load<uint16_t>(branch_location); // Get next in chain. 1955 if (changed) { 1956 MakeHoleForBranch(branch->GetLocation(), 2); 1957 if (branch->IsCompareAndBranch()) { 1958 // A cbz/cbnz instruction has changed size. There is no valid encoding for 1959 // a 32 bit cbz/cbnz so we need to change this to an instruction pair: 1960 // cmp rn, #0 1961 // b<eq|ne> target 1962 bool n = branch->GetType() == Branch::kCompareAndBranchNonZero; 1963 Condition cond = n ? NE : EQ; 1964 branch->Move(2); // Move the branch forward by 2 bytes. 1965 branch->ResetTypeAndCondition(Branch::kConditional, cond); 1966 branch->ResetSize(Branch::k16Bit); 1967 1968 // Now add a compare instruction in the place the branch was. 1969 int16_t cmp = B13 | B11 | static_cast<int16_t>(branch->GetRegister()) << 8; 1970 buffer_.Store<int16_t>(branch_location, cmp); 1971 1972 // Since have moved made a hole in the code we need to reload the 1973 // current pc. 1974 bound_pc = buffer_.Size(); 1975 1976 // Now resolve the newly added branch. 1977 changed = branch->Resolve(bound_pc); 1978 if (changed) { 1979 MakeHoleForBranch(branch->GetLocation(), 2); 1980 changed_branches.push_back(branch); 1981 } 1982 } else { 1983 changed_branches.push_back(branch); 1984 } 1985 } 1986 label->position_ = next; // Move to next. 1987 } 1988 label->BindTo(bound_pc); 1989 1990 // Now relocate any changed branches. Do this until there are no more changes. 1991 std::vector<Branch*> branches_to_process = changed_branches; 1992 while (branches_to_process.size() != 0) { 1993 changed_branches.clear(); 1994 for (auto& changed_branch : branches_to_process) { 1995 for (auto& branch : branches_) { 1996 bool changed = branch->Relocate(changed_branch->GetLocation(), 2); 1997 if (changed) { 1998 changed_branches.push_back(branch); 1999 } 2000 } 2001 branches_to_process = changed_branches; 2002 } 2003 } 2004} 2005 2006 2007void Thumb2Assembler::EmitBranches() { 2008 for (auto& branch : branches_) { 2009 branch->Emit(&buffer_); 2010 } 2011} 2012 2013 2014void Thumb2Assembler::Lsl(Register rd, Register rm, uint32_t shift_imm, 2015 Condition cond) { 2016 CHECK_NE(shift_imm, 0u); // Do not use Lsl if no shift is wanted. 2017 mov(rd, ShifterOperand(rm, LSL, shift_imm), cond); 2018} 2019 2020 2021void Thumb2Assembler::Lsr(Register rd, Register rm, uint32_t shift_imm, 2022 Condition cond) { 2023 CHECK_NE(shift_imm, 0u); // Do not use Lsr if no shift is wanted. 2024 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2025 mov(rd, ShifterOperand(rm, LSR, shift_imm), cond); 2026} 2027 2028 2029void Thumb2Assembler::Asr(Register rd, Register rm, uint32_t shift_imm, 2030 Condition cond) { 2031 CHECK_NE(shift_imm, 0u); // Do not use Asr if no shift is wanted. 2032 if (shift_imm == 32) shift_imm = 0; // Comply to UAL syntax. 2033 mov(rd, ShifterOperand(rm, ASR, shift_imm), cond); 2034} 2035 2036 2037void Thumb2Assembler::Ror(Register rd, Register rm, uint32_t shift_imm, 2038 Condition cond) { 2039 CHECK_NE(shift_imm, 0u); // Use Rrx instruction. 2040 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond); 2041} 2042 2043 2044void Thumb2Assembler::Rrx(Register rd, Register rm, Condition cond) { 2045 mov(rd, ShifterOperand(rm, ROR, 0), cond); 2046} 2047 2048 2049int32_t Thumb2Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { 2050 // The offset is off by 4 due to the way the ARM CPUs read PC. 2051 offset -= 4; 2052 offset >>= 1; 2053 2054 uint32_t value = 0; 2055 // There are two different encodings depending on the value of bit 12. In one case 2056 // intermediate values are calculated using the sign bit. 2057 if ((inst & B12) == B12) { 2058 // 25 bits of offset. 2059 uint32_t signbit = (offset >> 31) & 0x1; 2060 uint32_t i1 = (offset >> 22) & 0x1; 2061 uint32_t i2 = (offset >> 21) & 0x1; 2062 uint32_t imm10 = (offset >> 11) & 0x03ff; 2063 uint32_t imm11 = offset & 0x07ff; 2064 uint32_t j1 = (i1 ^ signbit) ? 0 : 1; 2065 uint32_t j2 = (i2 ^ signbit) ? 0 : 1; 2066 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm10 << 16) | 2067 imm11; 2068 // Remove the offset from the current encoding. 2069 inst &= ~(0x3ff << 16 | 0x7ff); 2070 } else { 2071 uint32_t signbit = (offset >> 31) & 0x1; 2072 uint32_t imm6 = (offset >> 11) & 0x03f; 2073 uint32_t imm11 = offset & 0x07ff; 2074 uint32_t j1 = (offset >> 19) & 1; 2075 uint32_t j2 = (offset >> 17) & 1; 2076 value = (signbit << 26) | (j1 << 13) | (j2 << 11) | (imm6 << 16) | 2077 imm11; 2078 // Remove the offset from the current encoding. 2079 inst &= ~(0x3f << 16 | 0x7ff); 2080 } 2081 // Mask out offset bits in current instruction. 2082 inst &= ~(B26 | B13 | B11); 2083 inst |= value; 2084 return inst; 2085} 2086 2087 2088int Thumb2Assembler::DecodeBranchOffset(int32_t instr) { 2089 int32_t imm32; 2090 if ((instr & B12) == B12) { 2091 uint32_t S = (instr >> 26) & 1; 2092 uint32_t J2 = (instr >> 11) & 1; 2093 uint32_t J1 = (instr >> 13) & 1; 2094 uint32_t imm10 = (instr >> 16) & 0x3FF; 2095 uint32_t imm11 = instr & 0x7FF; 2096 2097 uint32_t I1 = ~(J1 ^ S) & 1; 2098 uint32_t I2 = ~(J2 ^ S) & 1; 2099 imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2100 imm32 = (imm32 << 8) >> 8; // sign extend 24 bit immediate. 2101 } else { 2102 uint32_t S = (instr >> 26) & 1; 2103 uint32_t J2 = (instr >> 11) & 1; 2104 uint32_t J1 = (instr >> 13) & 1; 2105 uint32_t imm6 = (instr >> 16) & 0x3F; 2106 uint32_t imm11 = instr & 0x7FF; 2107 2108 imm32 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2109 imm32 = (imm32 << 11) >> 11; // sign extend 21 bit immediate. 2110 } 2111 imm32 += 4; 2112 return imm32; 2113} 2114 2115 2116void Thumb2Assembler::AddConstant(Register rd, int32_t value, Condition cond) { 2117 AddConstant(rd, rd, value, cond); 2118} 2119 2120 2121void Thumb2Assembler::AddConstant(Register rd, Register rn, int32_t value, 2122 Condition cond) { 2123 if (value == 0) { 2124 if (rd != rn) { 2125 mov(rd, ShifterOperand(rn), cond); 2126 } 2127 return; 2128 } 2129 // We prefer to select the shorter code sequence rather than selecting add for 2130 // positive values and sub for negatives ones, which would slightly improve 2131 // the readability of generated code for some constants. 2132 ShifterOperand shifter_op; 2133 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2134 add(rd, rn, shifter_op, cond); 2135 } else if (ShifterOperand::CanHoldThumb(rd, rn, SUB, -value, &shifter_op)) { 2136 sub(rd, rn, shifter_op, cond); 2137 } else { 2138 CHECK(rn != IP); 2139 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2140 mvn(IP, shifter_op, cond); 2141 add(rd, rn, ShifterOperand(IP), cond); 2142 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2143 mvn(IP, shifter_op, cond); 2144 sub(rd, rn, ShifterOperand(IP), cond); 2145 } else { 2146 movw(IP, Low16Bits(value), cond); 2147 uint16_t value_high = High16Bits(value); 2148 if (value_high != 0) { 2149 movt(IP, value_high, cond); 2150 } 2151 add(rd, rn, ShifterOperand(IP), cond); 2152 } 2153 } 2154} 2155 2156 2157void Thumb2Assembler::AddConstantSetFlags(Register rd, Register rn, int32_t value, 2158 Condition cond) { 2159 ShifterOperand shifter_op; 2160 if (ShifterOperand::CanHoldThumb(rd, rn, ADD, value, &shifter_op)) { 2161 adds(rd, rn, shifter_op, cond); 2162 } else if (ShifterOperand::CanHoldThumb(rd, rn, ADD, -value, &shifter_op)) { 2163 subs(rd, rn, shifter_op, cond); 2164 } else { 2165 CHECK(rn != IP); 2166 if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~value, &shifter_op)) { 2167 mvn(IP, shifter_op, cond); 2168 adds(rd, rn, ShifterOperand(IP), cond); 2169 } else if (ShifterOperand::CanHoldThumb(rd, rn, MVN, ~(-value), &shifter_op)) { 2170 mvn(IP, shifter_op, cond); 2171 subs(rd, rn, ShifterOperand(IP), cond); 2172 } else { 2173 movw(IP, Low16Bits(value), cond); 2174 uint16_t value_high = High16Bits(value); 2175 if (value_high != 0) { 2176 movt(IP, value_high, cond); 2177 } 2178 adds(rd, rn, ShifterOperand(IP), cond); 2179 } 2180 } 2181} 2182 2183 2184void Thumb2Assembler::LoadImmediate(Register rd, int32_t value, Condition cond) { 2185 ShifterOperand shifter_op; 2186 if (ShifterOperand::CanHoldThumb(rd, R0, MOV, value, &shifter_op)) { 2187 mov(rd, shifter_op, cond); 2188 } else if (ShifterOperand::CanHoldThumb(rd, R0, MVN, ~value, &shifter_op)) { 2189 mvn(rd, shifter_op, cond); 2190 } else { 2191 movw(rd, Low16Bits(value), cond); 2192 uint16_t value_high = High16Bits(value); 2193 if (value_high != 0) { 2194 movt(rd, value_high, cond); 2195 } 2196 } 2197} 2198 2199// Implementation note: this method must emit at most one instruction when 2200// Address::CanHoldLoadOffsetThumb. 2201void Thumb2Assembler::LoadFromOffset(LoadOperandType type, 2202 Register reg, 2203 Register base, 2204 int32_t offset, 2205 Condition cond) { 2206 if (!Address::CanHoldLoadOffsetThumb(type, offset)) { 2207 CHECK(base != IP); 2208 LoadImmediate(IP, offset, cond); 2209 add(IP, IP, ShifterOperand(base), cond); 2210 base = IP; 2211 offset = 0; 2212 } 2213 CHECK(Address::CanHoldLoadOffsetThumb(type, offset)); 2214 switch (type) { 2215 case kLoadSignedByte: 2216 ldrsb(reg, Address(base, offset), cond); 2217 break; 2218 case kLoadUnsignedByte: 2219 ldrb(reg, Address(base, offset), cond); 2220 break; 2221 case kLoadSignedHalfword: 2222 ldrsh(reg, Address(base, offset), cond); 2223 break; 2224 case kLoadUnsignedHalfword: 2225 ldrh(reg, Address(base, offset), cond); 2226 break; 2227 case kLoadWord: 2228 ldr(reg, Address(base, offset), cond); 2229 break; 2230 case kLoadWordPair: 2231 ldrd(reg, Address(base, offset), cond); 2232 break; 2233 default: 2234 LOG(FATAL) << "UNREACHABLE"; 2235 } 2236} 2237 2238 2239// Implementation note: this method must emit at most one instruction when 2240// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2241void Thumb2Assembler::LoadSFromOffset(SRegister reg, 2242 Register base, 2243 int32_t offset, 2244 Condition cond) { 2245 if (!Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)) { 2246 CHECK_NE(base, IP); 2247 LoadImmediate(IP, offset, cond); 2248 add(IP, IP, ShifterOperand(base), cond); 2249 base = IP; 2250 offset = 0; 2251 } 2252 CHECK(Address::CanHoldLoadOffsetThumb(kLoadSWord, offset)); 2253 vldrs(reg, Address(base, offset), cond); 2254} 2255 2256 2257// Implementation note: this method must emit at most one instruction when 2258// Address::CanHoldLoadOffsetThumb, as expected by JIT::GuardedLoadFromOffset. 2259void Thumb2Assembler::LoadDFromOffset(DRegister reg, 2260 Register base, 2261 int32_t offset, 2262 Condition cond) { 2263 if (!Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)) { 2264 CHECK_NE(base, IP); 2265 LoadImmediate(IP, offset, cond); 2266 add(IP, IP, ShifterOperand(base), cond); 2267 base = IP; 2268 offset = 0; 2269 } 2270 CHECK(Address::CanHoldLoadOffsetThumb(kLoadDWord, offset)); 2271 vldrd(reg, Address(base, offset), cond); 2272} 2273 2274 2275// Implementation note: this method must emit at most one instruction when 2276// Address::CanHoldStoreOffsetThumb. 2277void Thumb2Assembler::StoreToOffset(StoreOperandType type, 2278 Register reg, 2279 Register base, 2280 int32_t offset, 2281 Condition cond) { 2282 if (!Address::CanHoldStoreOffsetThumb(type, offset)) { 2283 CHECK(reg != IP); 2284 CHECK(base != IP); 2285 LoadImmediate(IP, offset, cond); 2286 add(IP, IP, ShifterOperand(base), cond); 2287 base = IP; 2288 offset = 0; 2289 } 2290 CHECK(Address::CanHoldStoreOffsetThumb(type, offset)); 2291 switch (type) { 2292 case kStoreByte: 2293 strb(reg, Address(base, offset), cond); 2294 break; 2295 case kStoreHalfword: 2296 strh(reg, Address(base, offset), cond); 2297 break; 2298 case kStoreWord: 2299 str(reg, Address(base, offset), cond); 2300 break; 2301 case kStoreWordPair: 2302 strd(reg, Address(base, offset), cond); 2303 break; 2304 default: 2305 LOG(FATAL) << "UNREACHABLE"; 2306 } 2307} 2308 2309 2310// Implementation note: this method must emit at most one instruction when 2311// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreToOffset. 2312void Thumb2Assembler::StoreSToOffset(SRegister reg, 2313 Register base, 2314 int32_t offset, 2315 Condition cond) { 2316 if (!Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)) { 2317 CHECK_NE(base, IP); 2318 LoadImmediate(IP, offset, cond); 2319 add(IP, IP, ShifterOperand(base), cond); 2320 base = IP; 2321 offset = 0; 2322 } 2323 CHECK(Address::CanHoldStoreOffsetThumb(kStoreSWord, offset)); 2324 vstrs(reg, Address(base, offset), cond); 2325} 2326 2327 2328// Implementation note: this method must emit at most one instruction when 2329// Address::CanHoldStoreOffsetThumb, as expected by JIT::GuardedStoreSToOffset. 2330void Thumb2Assembler::StoreDToOffset(DRegister reg, 2331 Register base, 2332 int32_t offset, 2333 Condition cond) { 2334 if (!Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)) { 2335 CHECK_NE(base, IP); 2336 LoadImmediate(IP, offset, cond); 2337 add(IP, IP, ShifterOperand(base), cond); 2338 base = IP; 2339 offset = 0; 2340 } 2341 CHECK(Address::CanHoldStoreOffsetThumb(kStoreDWord, offset)); 2342 vstrd(reg, Address(base, offset), cond); 2343} 2344 2345 2346void Thumb2Assembler::MemoryBarrier(ManagedRegister mscratch) { 2347 CHECK_EQ(mscratch.AsArm().AsCoreRegister(), R12); 2348#if ANDROID_SMP != 0 2349 int32_t encoding = 0xf3bf8f5f; // dmb in T1 encoding. 2350 Emit32(encoding); 2351#endif 2352} 2353 2354 2355void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) { 2356 cbz(r, label); 2357} 2358 2359 2360void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) { 2361 cbnz(r, label); 2362} 2363} // namespace arm 2364} // namespace art 2365