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