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