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