1 /* 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 University of Szeged 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #ifndef ARMAssembler_h 28 #define ARMAssembler_h 29 30 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) 31 32 #include "AssemblerBuffer.h" 33 #include <wtf/Assertions.h> 34 #include <wtf/Vector.h> 35 #include <stdint.h> 36 37 namespace JSC { 38 39 namespace ARMRegisters { 40 typedef enum { 41 r0, 42 r1, 43 r2, 44 r3, 45 r4, 46 r5, 47 r6, 48 r7, wr = r7, // thumb work register 49 r8, 50 r9, sb = r9, // static base 51 r10, sl = r10, // stack limit 52 r11, fp = r11, // frame pointer 53 r12, ip = r12, 54 r13, sp = r13, 55 r14, lr = r14, 56 r15, pc = r15, 57 } RegisterID; 58 59 typedef enum { 60 s0, 61 s1, 62 s2, 63 s3, 64 s4, 65 s5, 66 s6, 67 s7, 68 s8, 69 s9, 70 s10, 71 s11, 72 s12, 73 s13, 74 s14, 75 s15, 76 s16, 77 s17, 78 s18, 79 s19, 80 s20, 81 s21, 82 s22, 83 s23, 84 s24, 85 s25, 86 s26, 87 s27, 88 s28, 89 s29, 90 s30, 91 s31, 92 } FPSingleRegisterID; 93 94 typedef enum { 95 d0, 96 d1, 97 d2, 98 d3, 99 d4, 100 d5, 101 d6, 102 d7, 103 d8, 104 d9, 105 d10, 106 d11, 107 d12, 108 d13, 109 d14, 110 d15, 111 d16, 112 d17, 113 d18, 114 d19, 115 d20, 116 d21, 117 d22, 118 d23, 119 d24, 120 d25, 121 d26, 122 d27, 123 d28, 124 d29, 125 d30, 126 d31, 127 } FPDoubleRegisterID; 128 129 typedef enum { 130 q0, 131 q1, 132 q2, 133 q3, 134 q4, 135 q5, 136 q6, 137 q7, 138 q8, 139 q9, 140 q10, 141 q11, 142 q12, 143 q13, 144 q14, 145 q15, 146 q16, 147 q17, 148 q18, 149 q19, 150 q20, 151 q21, 152 q22, 153 q23, 154 q24, 155 q25, 156 q26, 157 q27, 158 q28, 159 q29, 160 q30, 161 q31, 162 } FPQuadRegisterID; 163 asSingle(FPDoubleRegisterID reg)164 inline FPSingleRegisterID asSingle(FPDoubleRegisterID reg) 165 { 166 ASSERT(reg < d16); 167 return (FPSingleRegisterID)(reg << 1); 168 } 169 asDouble(FPSingleRegisterID reg)170 inline FPDoubleRegisterID asDouble(FPSingleRegisterID reg) 171 { 172 ASSERT(!(reg & 1)); 173 return (FPDoubleRegisterID)(reg >> 1); 174 } 175 } 176 177 class ARMv7Assembler; 178 class ARMThumbImmediate { 179 friend class ARMv7Assembler; 180 181 typedef uint8_t ThumbImmediateType; 182 static const ThumbImmediateType TypeInvalid = 0; 183 static const ThumbImmediateType TypeEncoded = 1; 184 static const ThumbImmediateType TypeUInt16 = 2; 185 186 typedef union { 187 int16_t asInt; 188 struct { 189 unsigned imm8 : 8; 190 unsigned imm3 : 3; 191 unsigned i : 1; 192 unsigned imm4 : 4; 193 }; 194 // If this is an encoded immediate, then it may describe a shift, or a pattern. 195 struct { 196 unsigned shiftValue7 : 7; 197 unsigned shiftAmount : 5; 198 }; 199 struct { 200 unsigned immediate : 8; 201 unsigned pattern : 4; 202 }; 203 } ThumbImmediateValue; 204 205 // byte0 contains least significant bit; not using an array to make client code endian agnostic. 206 typedef union { 207 int32_t asInt; 208 struct { 209 uint8_t byte0; 210 uint8_t byte1; 211 uint8_t byte2; 212 uint8_t byte3; 213 }; 214 } PatternBytes; 215 countLeadingZerosPartial(uint32_t & value,int32_t & zeros,const int N)216 ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N) 217 { 218 if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */ 219 value >>= N; /* if any were set, lose the bottom N */ 220 else /* if none of the top N bits are set, */ 221 zeros += N; /* then we have identified N leading zeros */ 222 } 223 countLeadingZeros(uint32_t value)224 static int32_t countLeadingZeros(uint32_t value) 225 { 226 if (!value) 227 return 32; 228 229 int32_t zeros = 0; 230 countLeadingZerosPartial(value, zeros, 16); 231 countLeadingZerosPartial(value, zeros, 8); 232 countLeadingZerosPartial(value, zeros, 4); 233 countLeadingZerosPartial(value, zeros, 2); 234 countLeadingZerosPartial(value, zeros, 1); 235 return zeros; 236 } 237 ARMThumbImmediate()238 ARMThumbImmediate() 239 : m_type(TypeInvalid) 240 { 241 m_value.asInt = 0; 242 } 243 ARMThumbImmediate(ThumbImmediateType type,ThumbImmediateValue value)244 ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value) 245 : m_type(type) 246 , m_value(value) 247 { 248 } 249 ARMThumbImmediate(ThumbImmediateType type,uint16_t value)250 ARMThumbImmediate(ThumbImmediateType type, uint16_t value) 251 : m_type(TypeUInt16) 252 { 253 // Make sure this constructor is only reached with type TypeUInt16; 254 // this extra parameter makes the code a little clearer by making it 255 // explicit at call sites which type is being constructed 256 ASSERT_UNUSED(type, type == TypeUInt16); 257 258 m_value.asInt = value; 259 } 260 261 public: makeEncodedImm(uint32_t value)262 static ARMThumbImmediate makeEncodedImm(uint32_t value) 263 { 264 ThumbImmediateValue encoding; 265 encoding.asInt = 0; 266 267 // okay, these are easy. 268 if (value < 256) { 269 encoding.immediate = value; 270 encoding.pattern = 0; 271 return ARMThumbImmediate(TypeEncoded, encoding); 272 } 273 274 int32_t leadingZeros = countLeadingZeros(value); 275 // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case. 276 ASSERT(leadingZeros < 24); 277 278 // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32, 279 // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for 280 // zero. count(B) == 8, so the count of bits to be checked is 24 - count(Z). 281 int32_t rightShiftAmount = 24 - leadingZeros; 282 if (value == ((value >> rightShiftAmount) << rightShiftAmount)) { 283 // Shift the value down to the low byte position. The assign to 284 // shiftValue7 drops the implicit top bit. 285 encoding.shiftValue7 = value >> rightShiftAmount; 286 // The endoded shift amount is the magnitude of a right rotate. 287 encoding.shiftAmount = 8 + leadingZeros; 288 return ARMThumbImmediate(TypeEncoded, encoding); 289 } 290 291 PatternBytes bytes; 292 bytes.asInt = value; 293 294 if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) { 295 encoding.immediate = bytes.byte0; 296 encoding.pattern = 3; 297 return ARMThumbImmediate(TypeEncoded, encoding); 298 } 299 300 if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) { 301 encoding.immediate = bytes.byte0; 302 encoding.pattern = 1; 303 return ARMThumbImmediate(TypeEncoded, encoding); 304 } 305 306 if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) { 307 encoding.immediate = bytes.byte1; 308 encoding.pattern = 2; 309 return ARMThumbImmediate(TypeEncoded, encoding); 310 } 311 312 return ARMThumbImmediate(); 313 } 314 makeUInt12(int32_t value)315 static ARMThumbImmediate makeUInt12(int32_t value) 316 { 317 return (!(value & 0xfffff000)) 318 ? ARMThumbImmediate(TypeUInt16, (uint16_t)value) 319 : ARMThumbImmediate(); 320 } 321 makeUInt12OrEncodedImm(int32_t value)322 static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value) 323 { 324 // If this is not a 12-bit unsigned it, try making an encoded immediate. 325 return (!(value & 0xfffff000)) 326 ? ARMThumbImmediate(TypeUInt16, (uint16_t)value) 327 : makeEncodedImm(value); 328 } 329 330 // The 'make' methods, above, return a !isValid() value if the argument 331 // cannot be represented as the requested type. This methods is called 332 // 'get' since the argument can always be represented. makeUInt16(uint16_t value)333 static ARMThumbImmediate makeUInt16(uint16_t value) 334 { 335 return ARMThumbImmediate(TypeUInt16, value); 336 } 337 isValid()338 bool isValid() 339 { 340 return m_type != TypeInvalid; 341 } 342 343 // These methods rely on the format of encoded byte values. isUInt3()344 bool isUInt3() { return !(m_value.asInt & 0xfff8); } isUInt4()345 bool isUInt4() { return !(m_value.asInt & 0xfff0); } isUInt5()346 bool isUInt5() { return !(m_value.asInt & 0xffe0); } isUInt6()347 bool isUInt6() { return !(m_value.asInt & 0xffc0); } isUInt7()348 bool isUInt7() { return !(m_value.asInt & 0xff80); } isUInt8()349 bool isUInt8() { return !(m_value.asInt & 0xff00); } isUInt9()350 bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); } isUInt10()351 bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); } isUInt12()352 bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); } isUInt16()353 bool isUInt16() { return m_type == TypeUInt16; } getUInt3()354 uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; } getUInt4()355 uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; } getUInt5()356 uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; } getUInt6()357 uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; } getUInt7()358 uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; } getUInt8()359 uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; } getUInt9()360 uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; } getUInt10()361 uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; } getUInt12()362 uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; } getUInt16()363 uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; } 364 isEncodedImm()365 bool isEncodedImm() { return m_type == TypeEncoded; } 366 367 private: 368 ThumbImmediateType m_type; 369 ThumbImmediateValue m_value; 370 }; 371 372 typedef enum { 373 SRType_LSL, 374 SRType_LSR, 375 SRType_ASR, 376 SRType_ROR, 377 378 SRType_RRX = SRType_ROR 379 } ARMShiftType; 380 381 class ShiftTypeAndAmount { 382 friend class ARMv7Assembler; 383 384 public: ShiftTypeAndAmount()385 ShiftTypeAndAmount() 386 { 387 m_u.type = (ARMShiftType)0; 388 m_u.amount = 0; 389 } 390 ShiftTypeAndAmount(ARMShiftType type,unsigned amount)391 ShiftTypeAndAmount(ARMShiftType type, unsigned amount) 392 { 393 m_u.type = type; 394 m_u.amount = amount & 31; 395 } 396 lo4()397 unsigned lo4() { return m_u.lo4; } hi4()398 unsigned hi4() { return m_u.hi4; } 399 400 private: 401 union { 402 struct { 403 unsigned lo4 : 4; 404 unsigned hi4 : 4; 405 }; 406 struct { 407 unsigned type : 2; 408 unsigned amount : 6; 409 }; 410 } m_u; 411 }; 412 413 class ARMv7Assembler { 414 public: ~ARMv7Assembler()415 ~ARMv7Assembler() 416 { 417 ASSERT(m_jumpsToLink.isEmpty()); 418 } 419 420 typedef ARMRegisters::RegisterID RegisterID; 421 typedef ARMRegisters::FPSingleRegisterID FPSingleRegisterID; 422 typedef ARMRegisters::FPDoubleRegisterID FPDoubleRegisterID; 423 typedef ARMRegisters::FPQuadRegisterID FPQuadRegisterID; 424 425 // (HS, LO, HI, LS) -> (AE, B, A, BE) 426 // (VS, VC) -> (O, NO) 427 typedef enum { 428 ConditionEQ, 429 ConditionNE, 430 ConditionHS, ConditionCS = ConditionHS, 431 ConditionLO, ConditionCC = ConditionLO, 432 ConditionMI, 433 ConditionPL, 434 ConditionVS, 435 ConditionVC, 436 ConditionHI, 437 ConditionLS, 438 ConditionGE, 439 ConditionLT, 440 ConditionGT, 441 ConditionLE, 442 ConditionAL, 443 ConditionInvalid 444 } Condition; 445 446 enum JumpType { JumpFixed, JumpNoCondition, JumpCondition, JumpNoConditionFixedSize, JumpConditionFixedSize, JumpTypeCount }; 447 enum JumpLinkType { LinkInvalid, LinkJumpT1, LinkJumpT2, LinkJumpT3, 448 LinkJumpT4, LinkConditionalJumpT4, LinkBX, LinkConditionalBX, JumpLinkTypeCount }; 449 static const int JumpSizes[JumpLinkTypeCount]; 450 static const int JumpPaddingSizes[JumpTypeCount]; 451 class LinkRecord { 452 public: LinkRecord(intptr_t from,intptr_t to,JumpType type,Condition condition)453 LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition) 454 : m_from(from) 455 , m_to(to) 456 , m_type(type) 457 , m_linkType(LinkInvalid) 458 , m_condition(condition) 459 { 460 } from()461 intptr_t from() const { return m_from; } setFrom(intptr_t from)462 void setFrom(intptr_t from) { m_from = from; } to()463 intptr_t to() const { return m_to; } type()464 JumpType type() const { return m_type; } linkType()465 JumpLinkType linkType() const { return m_linkType; } setLinkType(JumpLinkType linkType)466 void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; } condition()467 Condition condition() const { return m_condition; } 468 private: 469 intptr_t m_from : 31; 470 intptr_t m_to : 31; 471 JumpType m_type : 3; 472 JumpLinkType m_linkType : 4; 473 Condition m_condition : 16; 474 }; 475 476 class JmpSrc { 477 friend class ARMv7Assembler; 478 friend class ARMInstructionFormatter; 479 friend class LinkBuffer; 480 public: JmpSrc()481 JmpSrc() 482 : m_offset(-1) 483 { 484 } 485 486 private: JmpSrc(int offset,JumpType type)487 JmpSrc(int offset, JumpType type) 488 : m_offset(offset) 489 , m_condition(ConditionInvalid) 490 , m_type(type) 491 { 492 ASSERT(m_type == JumpFixed || m_type == JumpNoCondition || m_type == JumpNoConditionFixedSize); 493 } 494 JmpSrc(int offset,JumpType type,Condition condition)495 JmpSrc(int offset, JumpType type, Condition condition) 496 : m_offset(offset) 497 , m_condition(condition) 498 , m_type(type) 499 { 500 ASSERT(m_type == JumpFixed || m_type == JumpCondition || m_type == JumpConditionFixedSize); 501 } 502 503 int m_offset; 504 Condition m_condition : 16; 505 JumpType m_type : 16; 506 507 }; 508 509 class JmpDst { 510 friend class ARMv7Assembler; 511 friend class ARMInstructionFormatter; 512 friend class LinkBuffer; 513 public: JmpDst()514 JmpDst() 515 : m_offset(-1) 516 , m_used(false) 517 { 518 } 519 isUsed()520 bool isUsed() const { return m_used; } isSet()521 bool isSet() const { return (m_offset != -1); } used()522 void used() { m_used = true; } 523 private: JmpDst(int offset)524 JmpDst(int offset) 525 : m_offset(offset) 526 , m_used(false) 527 { 528 ASSERT(m_offset == offset); 529 } 530 531 signed int m_offset : 31; 532 int m_used : 1; 533 }; 534 535 private: 536 537 // ARMv7, Appx-A.6.3 BadReg(RegisterID reg)538 bool BadReg(RegisterID reg) 539 { 540 return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc); 541 } 542 singleRegisterMask(FPSingleRegisterID rdNum,int highBitsShift,int lowBitShift)543 uint32_t singleRegisterMask(FPSingleRegisterID rdNum, int highBitsShift, int lowBitShift) 544 { 545 uint32_t rdMask = (rdNum >> 1) << highBitsShift; 546 if (rdNum & 1) 547 rdMask |= 1 << lowBitShift; 548 return rdMask; 549 } 550 doubleRegisterMask(FPDoubleRegisterID rdNum,int highBitShift,int lowBitsShift)551 uint32_t doubleRegisterMask(FPDoubleRegisterID rdNum, int highBitShift, int lowBitsShift) 552 { 553 uint32_t rdMask = (rdNum & 0xf) << lowBitsShift; 554 if (rdNum & 16) 555 rdMask |= 1 << highBitShift; 556 return rdMask; 557 } 558 559 typedef enum { 560 OP_ADD_reg_T1 = 0x1800, 561 OP_SUB_reg_T1 = 0x1A00, 562 OP_ADD_imm_T1 = 0x1C00, 563 OP_SUB_imm_T1 = 0x1E00, 564 OP_MOV_imm_T1 = 0x2000, 565 OP_CMP_imm_T1 = 0x2800, 566 OP_ADD_imm_T2 = 0x3000, 567 OP_SUB_imm_T2 = 0x3800, 568 OP_AND_reg_T1 = 0x4000, 569 OP_EOR_reg_T1 = 0x4040, 570 OP_TST_reg_T1 = 0x4200, 571 OP_RSB_imm_T1 = 0x4240, 572 OP_CMP_reg_T1 = 0x4280, 573 OP_ORR_reg_T1 = 0x4300, 574 OP_MVN_reg_T1 = 0x43C0, 575 OP_ADD_reg_T2 = 0x4400, 576 OP_MOV_reg_T1 = 0x4600, 577 OP_BLX = 0x4700, 578 OP_BX = 0x4700, 579 OP_STR_reg_T1 = 0x5000, 580 OP_LDR_reg_T1 = 0x5800, 581 OP_LDRH_reg_T1 = 0x5A00, 582 OP_LDRB_reg_T1 = 0x5C00, 583 OP_STR_imm_T1 = 0x6000, 584 OP_LDR_imm_T1 = 0x6800, 585 OP_LDRB_imm_T1 = 0x7800, 586 OP_LDRH_imm_T1 = 0x8800, 587 OP_STR_imm_T2 = 0x9000, 588 OP_LDR_imm_T2 = 0x9800, 589 OP_ADD_SP_imm_T1 = 0xA800, 590 OP_ADD_SP_imm_T2 = 0xB000, 591 OP_SUB_SP_imm_T1 = 0xB080, 592 OP_BKPT = 0xBE00, 593 OP_IT = 0xBF00, 594 OP_NOP_T1 = 0xBF00, 595 } OpcodeID; 596 597 typedef enum { 598 OP_B_T1 = 0xD000, 599 OP_B_T2 = 0xE000, 600 OP_AND_reg_T2 = 0xEA00, 601 OP_TST_reg_T2 = 0xEA10, 602 OP_ORR_reg_T2 = 0xEA40, 603 OP_ORR_S_reg_T2 = 0xEA50, 604 OP_ASR_imm_T1 = 0xEA4F, 605 OP_LSL_imm_T1 = 0xEA4F, 606 OP_LSR_imm_T1 = 0xEA4F, 607 OP_ROR_imm_T1 = 0xEA4F, 608 OP_MVN_reg_T2 = 0xEA6F, 609 OP_EOR_reg_T2 = 0xEA80, 610 OP_ADD_reg_T3 = 0xEB00, 611 OP_ADD_S_reg_T3 = 0xEB10, 612 OP_SUB_reg_T2 = 0xEBA0, 613 OP_SUB_S_reg_T2 = 0xEBB0, 614 OP_CMP_reg_T2 = 0xEBB0, 615 OP_VSTR = 0xED00, 616 OP_VLDR = 0xED10, 617 OP_VMOV_StoC = 0xEE00, 618 OP_VMOV_CtoS = 0xEE10, 619 OP_VMUL_T2 = 0xEE20, 620 OP_VADD_T2 = 0xEE30, 621 OP_VSUB_T2 = 0xEE30, 622 OP_VDIV = 0xEE80, 623 OP_VCMP = 0xEEB0, 624 OP_VCVT_FPIVFP = 0xEEB0, 625 OP_VMOV_IMM_T2 = 0xEEB0, 626 OP_VMRS = 0xEEB0, 627 OP_B_T3a = 0xF000, 628 OP_B_T4a = 0xF000, 629 OP_AND_imm_T1 = 0xF000, 630 OP_TST_imm = 0xF010, 631 OP_ORR_imm_T1 = 0xF040, 632 OP_MOV_imm_T2 = 0xF040, 633 OP_MVN_imm = 0xF060, 634 OP_EOR_imm_T1 = 0xF080, 635 OP_ADD_imm_T3 = 0xF100, 636 OP_ADD_S_imm_T3 = 0xF110, 637 OP_CMN_imm = 0xF110, 638 OP_SUB_imm_T3 = 0xF1A0, 639 OP_SUB_S_imm_T3 = 0xF1B0, 640 OP_CMP_imm_T2 = 0xF1B0, 641 OP_RSB_imm_T2 = 0xF1C0, 642 OP_ADD_imm_T4 = 0xF200, 643 OP_MOV_imm_T3 = 0xF240, 644 OP_SUB_imm_T4 = 0xF2A0, 645 OP_MOVT = 0xF2C0, 646 OP_NOP_T2a = 0xF3AF, 647 OP_LDRB_imm_T3 = 0xF810, 648 OP_LDRB_reg_T2 = 0xF810, 649 OP_LDRH_reg_T2 = 0xF830, 650 OP_LDRH_imm_T3 = 0xF830, 651 OP_STR_imm_T4 = 0xF840, 652 OP_STR_reg_T2 = 0xF840, 653 OP_LDR_imm_T4 = 0xF850, 654 OP_LDR_reg_T2 = 0xF850, 655 OP_LDRB_imm_T2 = 0xF890, 656 OP_LDRH_imm_T2 = 0xF8B0, 657 OP_STR_imm_T3 = 0xF8C0, 658 OP_LDR_imm_T3 = 0xF8D0, 659 OP_LSL_reg_T2 = 0xFA00, 660 OP_LSR_reg_T2 = 0xFA20, 661 OP_ASR_reg_T2 = 0xFA40, 662 OP_ROR_reg_T2 = 0xFA60, 663 OP_CLZ = 0xFAB0, 664 OP_SMULL_T1 = 0xFB80, 665 } OpcodeID1; 666 667 typedef enum { 668 OP_VADD_T2b = 0x0A00, 669 OP_VDIVb = 0x0A00, 670 OP_VLDRb = 0x0A00, 671 OP_VMOV_IMM_T2b = 0x0A00, 672 OP_VMUL_T2b = 0x0A00, 673 OP_VSTRb = 0x0A00, 674 OP_VMOV_CtoSb = 0x0A10, 675 OP_VMOV_StoCb = 0x0A10, 676 OP_VMRSb = 0x0A10, 677 OP_VCMPb = 0x0A40, 678 OP_VCVT_FPIVFPb = 0x0A40, 679 OP_VSUB_T2b = 0x0A40, 680 OP_NOP_T2b = 0x8000, 681 OP_B_T3b = 0x8000, 682 OP_B_T4b = 0x9000, 683 } OpcodeID2; 684 685 struct FourFours { FourFoursFourFours686 FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0) 687 { 688 m_u.f0 = f0; 689 m_u.f1 = f1; 690 m_u.f2 = f2; 691 m_u.f3 = f3; 692 } 693 694 union { 695 unsigned value; 696 struct { 697 unsigned f0 : 4; 698 unsigned f1 : 4; 699 unsigned f2 : 4; 700 unsigned f3 : 4; 701 }; 702 } m_u; 703 }; 704 705 class ARMInstructionFormatter; 706 707 // false means else! ifThenElseConditionBit(Condition condition,bool isIf)708 bool ifThenElseConditionBit(Condition condition, bool isIf) 709 { 710 return isIf ? (condition & 1) : !(condition & 1); 711 } ifThenElse(Condition condition,bool inst2if,bool inst3if,bool inst4if)712 uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if) 713 { 714 int mask = (ifThenElseConditionBit(condition, inst2if) << 3) 715 | (ifThenElseConditionBit(condition, inst3if) << 2) 716 | (ifThenElseConditionBit(condition, inst4if) << 1) 717 | 1; 718 ASSERT((condition != ConditionAL) || !(mask & (mask - 1))); 719 return (condition << 4) | mask; 720 } ifThenElse(Condition condition,bool inst2if,bool inst3if)721 uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if) 722 { 723 int mask = (ifThenElseConditionBit(condition, inst2if) << 3) 724 | (ifThenElseConditionBit(condition, inst3if) << 2) 725 | 2; 726 ASSERT((condition != ConditionAL) || !(mask & (mask - 1))); 727 return (condition << 4) | mask; 728 } ifThenElse(Condition condition,bool inst2if)729 uint8_t ifThenElse(Condition condition, bool inst2if) 730 { 731 int mask = (ifThenElseConditionBit(condition, inst2if) << 3) 732 | 4; 733 ASSERT((condition != ConditionAL) || !(mask & (mask - 1))); 734 return (condition << 4) | mask; 735 } 736 ifThenElse(Condition condition)737 uint8_t ifThenElse(Condition condition) 738 { 739 int mask = 8; 740 return (condition << 4) | mask; 741 } 742 743 public: 744 add(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)745 void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 746 { 747 // Rd can only be SP if Rn is also SP. 748 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 749 ASSERT(rd != ARMRegisters::pc); 750 ASSERT(rn != ARMRegisters::pc); 751 ASSERT(imm.isValid()); 752 753 if (rn == ARMRegisters::sp) { 754 if (!(rd & 8) && imm.isUInt10()) { 755 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2); 756 return; 757 } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) { 758 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2); 759 return; 760 } 761 } else if (!((rd | rn) & 8)) { 762 if (imm.isUInt3()) { 763 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 764 return; 765 } else if ((rd == rn) && imm.isUInt8()) { 766 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8()); 767 return; 768 } 769 } 770 771 if (imm.isEncodedImm()) 772 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm); 773 else { 774 ASSERT(imm.isUInt12()); 775 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm); 776 } 777 } 778 add(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)779 void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 780 { 781 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 782 ASSERT(rd != ARMRegisters::pc); 783 ASSERT(rn != ARMRegisters::pc); 784 ASSERT(!BadReg(rm)); 785 m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 786 } 787 788 // NOTE: In an IT block, add doesn't modify the flags register. add(RegisterID rd,RegisterID rn,RegisterID rm)789 void add(RegisterID rd, RegisterID rn, RegisterID rm) 790 { 791 if (rd == rn) 792 m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd); 793 else if (rd == rm) 794 m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd); 795 else if (!((rd | rn | rm) & 8)) 796 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd); 797 else 798 add(rd, rn, rm, ShiftTypeAndAmount()); 799 } 800 801 // Not allowed in an IT (if then) block. add_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)802 void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 803 { 804 // Rd can only be SP if Rn is also SP. 805 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 806 ASSERT(rd != ARMRegisters::pc); 807 ASSERT(rn != ARMRegisters::pc); 808 ASSERT(imm.isEncodedImm()); 809 810 if (!((rd | rn) & 8)) { 811 if (imm.isUInt3()) { 812 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 813 return; 814 } else if ((rd == rn) && imm.isUInt8()) { 815 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8()); 816 return; 817 } 818 } 819 820 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm); 821 } 822 823 // Not allowed in an IT (if then) block? add_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)824 void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 825 { 826 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 827 ASSERT(rd != ARMRegisters::pc); 828 ASSERT(rn != ARMRegisters::pc); 829 ASSERT(!BadReg(rm)); 830 m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 831 } 832 833 // Not allowed in an IT (if then) block. add_S(RegisterID rd,RegisterID rn,RegisterID rm)834 void add_S(RegisterID rd, RegisterID rn, RegisterID rm) 835 { 836 if (!((rd | rn | rm) & 8)) 837 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd); 838 else 839 add_S(rd, rn, rm, ShiftTypeAndAmount()); 840 } 841 ARM_and(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)842 void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 843 { 844 ASSERT(!BadReg(rd)); 845 ASSERT(!BadReg(rn)); 846 ASSERT(imm.isEncodedImm()); 847 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm); 848 } 849 ARM_and(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)850 void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 851 { 852 ASSERT(!BadReg(rd)); 853 ASSERT(!BadReg(rn)); 854 ASSERT(!BadReg(rm)); 855 m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 856 } 857 ARM_and(RegisterID rd,RegisterID rn,RegisterID rm)858 void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm) 859 { 860 if ((rd == rn) && !((rd | rm) & 8)) 861 m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd); 862 else if ((rd == rm) && !((rd | rn) & 8)) 863 m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd); 864 else 865 ARM_and(rd, rn, rm, ShiftTypeAndAmount()); 866 } 867 asr(RegisterID rd,RegisterID rm,int32_t shiftAmount)868 void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount) 869 { 870 ASSERT(!BadReg(rd)); 871 ASSERT(!BadReg(rm)); 872 ShiftTypeAndAmount shift(SRType_ASR, shiftAmount); 873 m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 874 } 875 asr(RegisterID rd,RegisterID rn,RegisterID rm)876 void asr(RegisterID rd, RegisterID rn, RegisterID rm) 877 { 878 ASSERT(!BadReg(rd)); 879 ASSERT(!BadReg(rn)); 880 ASSERT(!BadReg(rm)); 881 m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 882 } 883 884 // Only allowed in IT (if then) block if last instruction. b(JumpType type)885 JmpSrc b(JumpType type) 886 { 887 m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b); 888 return JmpSrc(m_formatter.size(), type); 889 } 890 891 // Only allowed in IT (if then) block if last instruction. blx(RegisterID rm,JumpType type)892 JmpSrc blx(RegisterID rm, JumpType type) 893 { 894 ASSERT(rm != ARMRegisters::pc); 895 m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8); 896 return JmpSrc(m_formatter.size(), type); 897 } 898 899 // Only allowed in IT (if then) block if last instruction. bx(RegisterID rm,JumpType type,Condition condition)900 JmpSrc bx(RegisterID rm, JumpType type, Condition condition) 901 { 902 m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0); 903 return JmpSrc(m_formatter.size(), type, condition); 904 } 905 bx(RegisterID rm,JumpType type)906 JmpSrc bx(RegisterID rm, JumpType type) 907 { 908 m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0); 909 return JmpSrc(m_formatter.size(), type); 910 } 911 912 void bkpt(uint8_t imm=0) 913 { 914 m_formatter.oneWordOp8Imm8(OP_BKPT, imm); 915 } 916 clz(RegisterID rd,RegisterID rm)917 void clz(RegisterID rd, RegisterID rm) 918 { 919 ASSERT(!BadReg(rd)); 920 ASSERT(!BadReg(rm)); 921 m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm)); 922 } 923 cmn(RegisterID rn,ARMThumbImmediate imm)924 void cmn(RegisterID rn, ARMThumbImmediate imm) 925 { 926 ASSERT(rn != ARMRegisters::pc); 927 ASSERT(imm.isEncodedImm()); 928 929 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm); 930 } 931 cmp(RegisterID rn,ARMThumbImmediate imm)932 void cmp(RegisterID rn, ARMThumbImmediate imm) 933 { 934 ASSERT(rn != ARMRegisters::pc); 935 ASSERT(imm.isEncodedImm()); 936 937 if (!(rn & 8) && imm.isUInt8()) 938 m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8()); 939 else 940 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm); 941 } 942 cmp(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)943 void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 944 { 945 ASSERT(rn != ARMRegisters::pc); 946 ASSERT(!BadReg(rm)); 947 m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm)); 948 } 949 cmp(RegisterID rn,RegisterID rm)950 void cmp(RegisterID rn, RegisterID rm) 951 { 952 if ((rn | rm) & 8) 953 cmp(rn, rm, ShiftTypeAndAmount()); 954 else 955 m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn); 956 } 957 958 // xor is not spelled with an 'e'. :-( eor(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)959 void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 960 { 961 ASSERT(!BadReg(rd)); 962 ASSERT(!BadReg(rn)); 963 ASSERT(imm.isEncodedImm()); 964 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm); 965 } 966 967 // xor is not spelled with an 'e'. :-( eor(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)968 void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 969 { 970 ASSERT(!BadReg(rd)); 971 ASSERT(!BadReg(rn)); 972 ASSERT(!BadReg(rm)); 973 m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 974 } 975 976 // xor is not spelled with an 'e'. :-( eor(RegisterID rd,RegisterID rn,RegisterID rm)977 void eor(RegisterID rd, RegisterID rn, RegisterID rm) 978 { 979 if ((rd == rn) && !((rd | rm) & 8)) 980 m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd); 981 else if ((rd == rm) && !((rd | rn) & 8)) 982 m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd); 983 else 984 eor(rd, rn, rm, ShiftTypeAndAmount()); 985 } 986 it(Condition cond)987 void it(Condition cond) 988 { 989 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond)); 990 } 991 it(Condition cond,bool inst2if)992 void it(Condition cond, bool inst2if) 993 { 994 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if)); 995 } 996 it(Condition cond,bool inst2if,bool inst3if)997 void it(Condition cond, bool inst2if, bool inst3if) 998 { 999 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if)); 1000 } 1001 it(Condition cond,bool inst2if,bool inst3if,bool inst4if)1002 void it(Condition cond, bool inst2if, bool inst3if, bool inst4if) 1003 { 1004 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if)); 1005 } 1006 1007 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. ldr(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1008 void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 1009 { 1010 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1011 ASSERT(imm.isUInt12()); 1012 1013 if (!((rt | rn) & 8) && imm.isUInt7()) 1014 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt); 1015 else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10()) 1016 m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2); 1017 else 1018 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12()); 1019 } 1020 1021 // If index is set, this is a regular offset or a pre-indexed load; 1022 // if index is not set then is is a post-index load. 1023 // 1024 // If wback is set rn is updated - this is a pre or post index load, 1025 // if wback is not set this is a regular offset memory access. 1026 // 1027 // (-255 <= offset <= 255) 1028 // _reg = REG[rn] 1029 // _tmp = _reg + offset 1030 // MEM[index ? _tmp : _reg] = REG[rt] 1031 // if (wback) REG[rn] = _tmp ldr(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1032 void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 1033 { 1034 ASSERT(rt != ARMRegisters::pc); 1035 ASSERT(rn != ARMRegisters::pc); 1036 ASSERT(index || wback); 1037 ASSERT(!wback | (rt != rn)); 1038 1039 bool add = true; 1040 if (offset < 0) { 1041 add = false; 1042 offset = -offset; 1043 } 1044 ASSERT((offset & ~0xff) == 0); 1045 1046 offset |= (wback << 8); 1047 offset |= (add << 9); 1048 offset |= (index << 10); 1049 offset |= (1 << 11); 1050 1051 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset); 1052 } 1053 1054 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. 1055 void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0) 1056 { 1057 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1058 ASSERT(!BadReg(rm)); 1059 ASSERT(shift <= 3); 1060 1061 if (!shift && !((rt | rn | rm) & 8)) 1062 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt); 1063 else 1064 m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1065 } 1066 1067 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. ldrh(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1068 void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 1069 { 1070 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1071 ASSERT(imm.isUInt12()); 1072 1073 if (!((rt | rn) & 8) && imm.isUInt6()) 1074 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt); 1075 else 1076 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12()); 1077 } 1078 1079 // If index is set, this is a regular offset or a pre-indexed load; 1080 // if index is not set then is is a post-index load. 1081 // 1082 // If wback is set rn is updated - this is a pre or post index load, 1083 // if wback is not set this is a regular offset memory access. 1084 // 1085 // (-255 <= offset <= 255) 1086 // _reg = REG[rn] 1087 // _tmp = _reg + offset 1088 // MEM[index ? _tmp : _reg] = REG[rt] 1089 // if (wback) REG[rn] = _tmp ldrh(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1090 void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 1091 { 1092 ASSERT(rt != ARMRegisters::pc); 1093 ASSERT(rn != ARMRegisters::pc); 1094 ASSERT(index || wback); 1095 ASSERT(!wback | (rt != rn)); 1096 1097 bool add = true; 1098 if (offset < 0) { 1099 add = false; 1100 offset = -offset; 1101 } 1102 ASSERT((offset & ~0xff) == 0); 1103 1104 offset |= (wback << 8); 1105 offset |= (add << 9); 1106 offset |= (index << 10); 1107 offset |= (1 << 11); 1108 1109 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset); 1110 } 1111 1112 void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0) 1113 { 1114 ASSERT(!BadReg(rt)); // Memory hint 1115 ASSERT(rn != ARMRegisters::pc); // LDRH (literal) 1116 ASSERT(!BadReg(rm)); 1117 ASSERT(shift <= 3); 1118 1119 if (!shift && !((rt | rn | rm) & 8)) 1120 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt); 1121 else 1122 m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1123 } 1124 ldrb(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1125 void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 1126 { 1127 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1128 ASSERT(imm.isUInt12()); 1129 1130 if (!((rt | rn) & 8) && imm.isUInt5()) 1131 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt); 1132 else 1133 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12()); 1134 } 1135 ldrb(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1136 void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 1137 { 1138 ASSERT(rt != ARMRegisters::pc); 1139 ASSERT(rn != ARMRegisters::pc); 1140 ASSERT(index || wback); 1141 ASSERT(!wback | (rt != rn)); 1142 1143 bool add = true; 1144 if (offset < 0) { 1145 add = false; 1146 offset = -offset; 1147 } 1148 1149 ASSERT(!(offset & ~0xff)); 1150 1151 offset |= (wback << 8); 1152 offset |= (add << 9); 1153 offset |= (index << 10); 1154 offset |= (1 << 11); 1155 1156 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset); 1157 } 1158 1159 void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0) 1160 { 1161 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1162 ASSERT(!BadReg(rm)); 1163 ASSERT(shift <= 3); 1164 1165 if (!shift && !((rt | rn | rm) & 8)) 1166 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt); 1167 else 1168 m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1169 } 1170 lsl(RegisterID rd,RegisterID rm,int32_t shiftAmount)1171 void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount) 1172 { 1173 ASSERT(!BadReg(rd)); 1174 ASSERT(!BadReg(rm)); 1175 ShiftTypeAndAmount shift(SRType_LSL, shiftAmount); 1176 m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1177 } 1178 lsl(RegisterID rd,RegisterID rn,RegisterID rm)1179 void lsl(RegisterID rd, RegisterID rn, RegisterID rm) 1180 { 1181 ASSERT(!BadReg(rd)); 1182 ASSERT(!BadReg(rn)); 1183 ASSERT(!BadReg(rm)); 1184 m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 1185 } 1186 lsr(RegisterID rd,RegisterID rm,int32_t shiftAmount)1187 void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount) 1188 { 1189 ASSERT(!BadReg(rd)); 1190 ASSERT(!BadReg(rm)); 1191 ShiftTypeAndAmount shift(SRType_LSR, shiftAmount); 1192 m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1193 } 1194 lsr(RegisterID rd,RegisterID rn,RegisterID rm)1195 void lsr(RegisterID rd, RegisterID rn, RegisterID rm) 1196 { 1197 ASSERT(!BadReg(rd)); 1198 ASSERT(!BadReg(rn)); 1199 ASSERT(!BadReg(rm)); 1200 m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 1201 } 1202 movT3(RegisterID rd,ARMThumbImmediate imm)1203 void movT3(RegisterID rd, ARMThumbImmediate imm) 1204 { 1205 ASSERT(imm.isValid()); 1206 ASSERT(!imm.isEncodedImm()); 1207 ASSERT(!BadReg(rd)); 1208 1209 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm); 1210 } 1211 mov(RegisterID rd,ARMThumbImmediate imm)1212 void mov(RegisterID rd, ARMThumbImmediate imm) 1213 { 1214 ASSERT(imm.isValid()); 1215 ASSERT(!BadReg(rd)); 1216 1217 if ((rd < 8) && imm.isUInt8()) 1218 m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8()); 1219 else if (imm.isEncodedImm()) 1220 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm); 1221 else 1222 movT3(rd, imm); 1223 } 1224 mov(RegisterID rd,RegisterID rm)1225 void mov(RegisterID rd, RegisterID rm) 1226 { 1227 m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd); 1228 } 1229 movt(RegisterID rd,ARMThumbImmediate imm)1230 void movt(RegisterID rd, ARMThumbImmediate imm) 1231 { 1232 ASSERT(imm.isUInt16()); 1233 ASSERT(!BadReg(rd)); 1234 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm); 1235 } 1236 mvn(RegisterID rd,ARMThumbImmediate imm)1237 void mvn(RegisterID rd, ARMThumbImmediate imm) 1238 { 1239 ASSERT(imm.isEncodedImm()); 1240 ASSERT(!BadReg(rd)); 1241 1242 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm); 1243 } 1244 mvn(RegisterID rd,RegisterID rm,ShiftTypeAndAmount shift)1245 void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift) 1246 { 1247 ASSERT(!BadReg(rd)); 1248 ASSERT(!BadReg(rm)); 1249 m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1250 } 1251 mvn(RegisterID rd,RegisterID rm)1252 void mvn(RegisterID rd, RegisterID rm) 1253 { 1254 if (!((rd | rm) & 8)) 1255 m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd); 1256 else 1257 mvn(rd, rm, ShiftTypeAndAmount()); 1258 } 1259 neg(RegisterID rd,RegisterID rm)1260 void neg(RegisterID rd, RegisterID rm) 1261 { 1262 ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0); 1263 sub(rd, zero, rm); 1264 } 1265 orr(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1266 void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 1267 { 1268 ASSERT(!BadReg(rd)); 1269 ASSERT(!BadReg(rn)); 1270 ASSERT(imm.isEncodedImm()); 1271 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm); 1272 } 1273 orr(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1274 void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1275 { 1276 ASSERT(!BadReg(rd)); 1277 ASSERT(!BadReg(rn)); 1278 ASSERT(!BadReg(rm)); 1279 m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1280 } 1281 orr(RegisterID rd,RegisterID rn,RegisterID rm)1282 void orr(RegisterID rd, RegisterID rn, RegisterID rm) 1283 { 1284 if ((rd == rn) && !((rd | rm) & 8)) 1285 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd); 1286 else if ((rd == rm) && !((rd | rn) & 8)) 1287 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd); 1288 else 1289 orr(rd, rn, rm, ShiftTypeAndAmount()); 1290 } 1291 orr_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1292 void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1293 { 1294 ASSERT(!BadReg(rd)); 1295 ASSERT(!BadReg(rn)); 1296 ASSERT(!BadReg(rm)); 1297 m_formatter.twoWordOp12Reg4FourFours(OP_ORR_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1298 } 1299 orr_S(RegisterID rd,RegisterID rn,RegisterID rm)1300 void orr_S(RegisterID rd, RegisterID rn, RegisterID rm) 1301 { 1302 if ((rd == rn) && !((rd | rm) & 8)) 1303 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd); 1304 else if ((rd == rm) && !((rd | rn) & 8)) 1305 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd); 1306 else 1307 orr_S(rd, rn, rm, ShiftTypeAndAmount()); 1308 } 1309 ror(RegisterID rd,RegisterID rm,int32_t shiftAmount)1310 void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount) 1311 { 1312 ASSERT(!BadReg(rd)); 1313 ASSERT(!BadReg(rm)); 1314 ShiftTypeAndAmount shift(SRType_ROR, shiftAmount); 1315 m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1316 } 1317 ror(RegisterID rd,RegisterID rn,RegisterID rm)1318 void ror(RegisterID rd, RegisterID rn, RegisterID rm) 1319 { 1320 ASSERT(!BadReg(rd)); 1321 ASSERT(!BadReg(rn)); 1322 ASSERT(!BadReg(rm)); 1323 m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 1324 } 1325 smull(RegisterID rdLo,RegisterID rdHi,RegisterID rn,RegisterID rm)1326 void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm) 1327 { 1328 ASSERT(!BadReg(rdLo)); 1329 ASSERT(!BadReg(rdHi)); 1330 ASSERT(!BadReg(rn)); 1331 ASSERT(!BadReg(rm)); 1332 ASSERT(rdLo != rdHi); 1333 m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm)); 1334 } 1335 1336 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. str(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1337 void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 1338 { 1339 ASSERT(rt != ARMRegisters::pc); 1340 ASSERT(rn != ARMRegisters::pc); 1341 ASSERT(imm.isUInt12()); 1342 1343 if (!((rt | rn) & 8) && imm.isUInt7()) 1344 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt); 1345 else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10()) 1346 m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2); 1347 else 1348 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12()); 1349 } 1350 1351 // If index is set, this is a regular offset or a pre-indexed store; 1352 // if index is not set then is is a post-index store. 1353 // 1354 // If wback is set rn is updated - this is a pre or post index store, 1355 // if wback is not set this is a regular offset memory access. 1356 // 1357 // (-255 <= offset <= 255) 1358 // _reg = REG[rn] 1359 // _tmp = _reg + offset 1360 // MEM[index ? _tmp : _reg] = REG[rt] 1361 // if (wback) REG[rn] = _tmp str(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1362 void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 1363 { 1364 ASSERT(rt != ARMRegisters::pc); 1365 ASSERT(rn != ARMRegisters::pc); 1366 ASSERT(index || wback); 1367 ASSERT(!wback | (rt != rn)); 1368 1369 bool add = true; 1370 if (offset < 0) { 1371 add = false; 1372 offset = -offset; 1373 } 1374 ASSERT((offset & ~0xff) == 0); 1375 1376 offset |= (wback << 8); 1377 offset |= (add << 9); 1378 offset |= (index << 10); 1379 offset |= (1 << 11); 1380 1381 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset); 1382 } 1383 1384 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. 1385 void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0) 1386 { 1387 ASSERT(rn != ARMRegisters::pc); 1388 ASSERT(!BadReg(rm)); 1389 ASSERT(shift <= 3); 1390 1391 if (!shift && !((rt | rn | rm) & 8)) 1392 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt); 1393 else 1394 m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1395 } 1396 sub(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1397 void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 1398 { 1399 // Rd can only be SP if Rn is also SP. 1400 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1401 ASSERT(rd != ARMRegisters::pc); 1402 ASSERT(rn != ARMRegisters::pc); 1403 ASSERT(imm.isValid()); 1404 1405 if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { 1406 m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2); 1407 return; 1408 } else if (!((rd | rn) & 8)) { 1409 if (imm.isUInt3()) { 1410 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 1411 return; 1412 } else if ((rd == rn) && imm.isUInt8()) { 1413 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8()); 1414 return; 1415 } 1416 } 1417 1418 if (imm.isEncodedImm()) 1419 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm); 1420 else { 1421 ASSERT(imm.isUInt12()); 1422 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm); 1423 } 1424 } 1425 sub(RegisterID rd,ARMThumbImmediate imm,RegisterID rn)1426 void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn) 1427 { 1428 ASSERT(rd != ARMRegisters::pc); 1429 ASSERT(rn != ARMRegisters::pc); 1430 ASSERT(imm.isValid()); 1431 ASSERT(imm.isUInt12()); 1432 1433 if (!((rd | rn) & 8) && !imm.getUInt12()) 1434 m_formatter.oneWordOp10Reg3Reg3(OP_RSB_imm_T1, rn, rd); 1435 else 1436 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm); 1437 } 1438 sub(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1439 void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1440 { 1441 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1442 ASSERT(rd != ARMRegisters::pc); 1443 ASSERT(rn != ARMRegisters::pc); 1444 ASSERT(!BadReg(rm)); 1445 m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1446 } 1447 1448 // NOTE: In an IT block, add doesn't modify the flags register. sub(RegisterID rd,RegisterID rn,RegisterID rm)1449 void sub(RegisterID rd, RegisterID rn, RegisterID rm) 1450 { 1451 if (!((rd | rn | rm) & 8)) 1452 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd); 1453 else 1454 sub(rd, rn, rm, ShiftTypeAndAmount()); 1455 } 1456 1457 // Not allowed in an IT (if then) block. sub_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1458 void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 1459 { 1460 // Rd can only be SP if Rn is also SP. 1461 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1462 ASSERT(rd != ARMRegisters::pc); 1463 ASSERT(rn != ARMRegisters::pc); 1464 ASSERT(imm.isValid()); 1465 1466 if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { 1467 m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2); 1468 return; 1469 } else if (!((rd | rn) & 8)) { 1470 if (imm.isUInt3()) { 1471 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 1472 return; 1473 } else if ((rd == rn) && imm.isUInt8()) { 1474 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8()); 1475 return; 1476 } 1477 } 1478 1479 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm); 1480 } 1481 1482 // Not allowed in an IT (if then) block? sub_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1483 void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1484 { 1485 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1486 ASSERT(rd != ARMRegisters::pc); 1487 ASSERT(rn != ARMRegisters::pc); 1488 ASSERT(!BadReg(rm)); 1489 m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1490 } 1491 1492 // Not allowed in an IT (if then) block. sub_S(RegisterID rd,RegisterID rn,RegisterID rm)1493 void sub_S(RegisterID rd, RegisterID rn, RegisterID rm) 1494 { 1495 if (!((rd | rn | rm) & 8)) 1496 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd); 1497 else 1498 sub_S(rd, rn, rm, ShiftTypeAndAmount()); 1499 } 1500 tst(RegisterID rn,ARMThumbImmediate imm)1501 void tst(RegisterID rn, ARMThumbImmediate imm) 1502 { 1503 ASSERT(!BadReg(rn)); 1504 ASSERT(imm.isEncodedImm()); 1505 1506 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm); 1507 } 1508 tst(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1509 void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1510 { 1511 ASSERT(!BadReg(rn)); 1512 ASSERT(!BadReg(rm)); 1513 m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm)); 1514 } 1515 tst(RegisterID rn,RegisterID rm)1516 void tst(RegisterID rn, RegisterID rm) 1517 { 1518 if ((rn | rm) & 8) 1519 tst(rn, rm, ShiftTypeAndAmount()); 1520 else 1521 m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn); 1522 } 1523 vadd_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1524 void vadd_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1525 { 1526 m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm); 1527 } 1528 vcmp_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rm)1529 void vcmp_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rm) 1530 { 1531 m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(4), rd, rm); 1532 } 1533 vcmpz_F64(FPDoubleRegisterID rd)1534 void vcmpz_F64(FPDoubleRegisterID rd) 1535 { 1536 m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0)); 1537 } 1538 vcvt_F64_S32(FPDoubleRegisterID rd,FPSingleRegisterID rm)1539 void vcvt_F64_S32(FPDoubleRegisterID rd, FPSingleRegisterID rm) 1540 { 1541 // boolean values are 64bit (toInt, unsigned, roundZero) 1542 m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm); 1543 } 1544 vcvtr_S32_F64(FPSingleRegisterID rd,FPDoubleRegisterID rm)1545 void vcvtr_S32_F64(FPSingleRegisterID rd, FPDoubleRegisterID rm) 1546 { 1547 // boolean values are 64bit (toInt, unsigned, roundZero) 1548 m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(true, false, true), rd, rm); 1549 } 1550 vdiv_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1551 void vdiv_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1552 { 1553 m_formatter.vfpOp(OP_VDIV, OP_VDIVb, true, rn, rd, rm); 1554 } 1555 vldr(FPDoubleRegisterID rd,RegisterID rn,int32_t imm)1556 void vldr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm) 1557 { 1558 m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm); 1559 } 1560 vmov(RegisterID rd,FPSingleRegisterID rn)1561 void vmov(RegisterID rd, FPSingleRegisterID rn) 1562 { 1563 ASSERT(!BadReg(rd)); 1564 m_formatter.vfpOp(OP_VMOV_CtoS, OP_VMOV_CtoSb, false, rn, rd, VFPOperand(0)); 1565 } 1566 vmov(FPSingleRegisterID rd,RegisterID rn)1567 void vmov(FPSingleRegisterID rd, RegisterID rn) 1568 { 1569 ASSERT(!BadReg(rn)); 1570 m_formatter.vfpOp(OP_VMOV_StoC, OP_VMOV_StoCb, false, rd, rn, VFPOperand(0)); 1571 } 1572 1573 void vmrs(RegisterID reg = ARMRegisters::pc) 1574 { 1575 ASSERT(reg != ARMRegisters::sp); 1576 m_formatter.vfpOp(OP_VMRS, OP_VMRSb, false, VFPOperand(1), VFPOperand(0x10 | reg), VFPOperand(0)); 1577 } 1578 vmul_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1579 void vmul_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1580 { 1581 m_formatter.vfpOp(OP_VMUL_T2, OP_VMUL_T2b, true, rn, rd, rm); 1582 } 1583 vstr(FPDoubleRegisterID rd,RegisterID rn,int32_t imm)1584 void vstr(FPDoubleRegisterID rd, RegisterID rn, int32_t imm) 1585 { 1586 m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm); 1587 } 1588 vsub_F64(FPDoubleRegisterID rd,FPDoubleRegisterID rn,FPDoubleRegisterID rm)1589 void vsub_F64(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) 1590 { 1591 m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm); 1592 } 1593 label()1594 JmpDst label() 1595 { 1596 return JmpDst(m_formatter.size()); 1597 } 1598 align(int alignment)1599 JmpDst align(int alignment) 1600 { 1601 while (!m_formatter.isAligned(alignment)) 1602 bkpt(); 1603 1604 return label(); 1605 } 1606 getRelocatedAddress(void * code,JmpSrc jump)1607 static void* getRelocatedAddress(void* code, JmpSrc jump) 1608 { 1609 ASSERT(jump.m_offset != -1); 1610 1611 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset); 1612 } 1613 getRelocatedAddress(void * code,JmpDst destination)1614 static void* getRelocatedAddress(void* code, JmpDst destination) 1615 { 1616 ASSERT(destination.m_offset != -1); 1617 1618 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset); 1619 } 1620 getDifferenceBetweenLabels(JmpDst src,JmpDst dst)1621 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst) 1622 { 1623 return dst.m_offset - src.m_offset; 1624 } 1625 getDifferenceBetweenLabels(JmpDst src,JmpSrc dst)1626 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst) 1627 { 1628 return dst.m_offset - src.m_offset; 1629 } 1630 getDifferenceBetweenLabels(JmpSrc src,JmpDst dst)1631 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst) 1632 { 1633 return dst.m_offset - src.m_offset; 1634 } 1635 executableOffsetFor(int location)1636 int executableOffsetFor(int location) 1637 { 1638 if (!location) 1639 return 0; 1640 return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1]; 1641 } 1642 jumpSizeDelta(JumpType jumpType,JumpLinkType jumpLinkType)1643 int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JumpPaddingSizes[jumpType] - JumpSizes[jumpLinkType]; } 1644 1645 // Assembler admin methods: 1646 size()1647 size_t size() const 1648 { 1649 return m_formatter.size(); 1650 } 1651 linkRecordSourceComparator(const LinkRecord & a,const LinkRecord & b)1652 static bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b) 1653 { 1654 return a.from() < b.from(); 1655 } 1656 canCompact(JumpType jumpType)1657 bool canCompact(JumpType jumpType) 1658 { 1659 // The following cannot be compacted: 1660 // JumpFixed: represents custom jump sequence 1661 // JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size 1662 // JumpConditionFixedSize: represents conditional jump that must remain a fixed size 1663 return (jumpType == JumpNoCondition) || (jumpType == JumpCondition); 1664 } 1665 computeJumpType(JumpType jumpType,const uint8_t * from,const uint8_t * to)1666 JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) 1667 { 1668 if (jumpType == JumpFixed) 1669 return LinkInvalid; 1670 1671 // for patchable jump we must leave space for the longest code sequence 1672 if (jumpType == JumpNoConditionFixedSize) 1673 return LinkBX; 1674 if (jumpType == JumpConditionFixedSize) 1675 return LinkConditionalBX; 1676 1677 const int paddingSize = JumpPaddingSizes[jumpType]; 1678 bool mayTriggerErrata = false; 1679 1680 if (jumpType == JumpCondition) { 1681 // 2-byte conditional T1 1682 const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT1])); 1683 if (canBeJumpT1(jumpT1Location, to)) 1684 return LinkJumpT1; 1685 // 4-byte conditional T3 1686 const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT3])); 1687 if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) { 1688 if (!mayTriggerErrata) 1689 return LinkJumpT3; 1690 } 1691 // 4-byte conditional T4 with IT 1692 const uint16_t* conditionalJumpT4Location = 1693 reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkConditionalJumpT4])); 1694 if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) { 1695 if (!mayTriggerErrata) 1696 return LinkConditionalJumpT4; 1697 } 1698 } else { 1699 // 2-byte unconditional T2 1700 const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT2])); 1701 if (canBeJumpT2(jumpT2Location, to)) 1702 return LinkJumpT2; 1703 // 4-byte unconditional T4 1704 const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT4])); 1705 if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) { 1706 if (!mayTriggerErrata) 1707 return LinkJumpT4; 1708 } 1709 // use long jump sequence 1710 return LinkBX; 1711 } 1712 1713 ASSERT(jumpType == JumpCondition); 1714 return LinkConditionalBX; 1715 } 1716 computeJumpType(LinkRecord & record,const uint8_t * from,const uint8_t * to)1717 JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) 1718 { 1719 JumpLinkType linkType = computeJumpType(record.type(), from, to); 1720 record.setLinkType(linkType); 1721 return linkType; 1722 } 1723 recordLinkOffsets(int32_t regionStart,int32_t regionEnd,int32_t offset)1724 void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) 1725 { 1726 int32_t ptr = regionStart / sizeof(int32_t); 1727 const int32_t end = regionEnd / sizeof(int32_t); 1728 int32_t* offsets = static_cast<int32_t*>(m_formatter.data()); 1729 while (ptr < end) 1730 offsets[ptr++] = offset; 1731 } 1732 jumpsToLink()1733 Vector<LinkRecord>& jumpsToLink() 1734 { 1735 std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator); 1736 return m_jumpsToLink; 1737 } 1738 link(LinkRecord & record,uint8_t * from,uint8_t * to)1739 void link(LinkRecord& record, uint8_t* from, uint8_t* to) 1740 { 1741 switch (record.linkType()) { 1742 case LinkJumpT1: 1743 linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to); 1744 break; 1745 case LinkJumpT2: 1746 linkJumpT2(reinterpret_cast<uint16_t*>(from), to); 1747 break; 1748 case LinkJumpT3: 1749 linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to); 1750 break; 1751 case LinkJumpT4: 1752 linkJumpT4(reinterpret_cast<uint16_t*>(from), to); 1753 break; 1754 case LinkConditionalJumpT4: 1755 linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to); 1756 break; 1757 case LinkConditionalBX: 1758 linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to); 1759 break; 1760 case LinkBX: 1761 linkBX(reinterpret_cast<uint16_t*>(from), to); 1762 break; 1763 default: 1764 ASSERT_NOT_REACHED(); 1765 break; 1766 } 1767 } 1768 unlinkedCode()1769 void* unlinkedCode() { return m_formatter.data(); } 1770 getCallReturnOffset(JmpSrc call)1771 static unsigned getCallReturnOffset(JmpSrc call) 1772 { 1773 ASSERT(call.m_offset >= 0); 1774 return call.m_offset; 1775 } 1776 1777 // Linking & patching: 1778 // 1779 // 'link' and 'patch' methods are for use on unprotected code - such as the code 1780 // within the AssemblerBuffer, and code being patched by the patch buffer. Once 1781 // code has been finalized it is (platform support permitting) within a non- 1782 // writable region of memory; to modify the code in an execute-only execuable 1783 // pool the 'repatch' and 'relink' methods should be used. 1784 linkJump(JmpSrc from,JmpDst to)1785 void linkJump(JmpSrc from, JmpDst to) 1786 { 1787 ASSERT(to.m_offset != -1); 1788 ASSERT(from.m_offset != -1); 1789 m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, from.m_type, from.m_condition)); 1790 } 1791 linkJump(void * code,JmpSrc from,void * to)1792 static void linkJump(void* code, JmpSrc from, void* to) 1793 { 1794 ASSERT(from.m_offset != -1); 1795 1796 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset); 1797 linkJumpAbsolute(location, to); 1798 } 1799 1800 // bah, this mathod should really be static, since it is used by the LinkBuffer. 1801 // return a bool saying whether the link was successful? linkCall(void * code,JmpSrc from,void * to)1802 static void linkCall(void* code, JmpSrc from, void* to) 1803 { 1804 ASSERT(!(reinterpret_cast<intptr_t>(code) & 1)); 1805 ASSERT(from.m_offset != -1); 1806 ASSERT(reinterpret_cast<intptr_t>(to) & 1); 1807 1808 setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to); 1809 } 1810 linkPointer(void * code,JmpDst where,void * value)1811 static void linkPointer(void* code, JmpDst where, void* value) 1812 { 1813 setPointer(reinterpret_cast<char*>(code) + where.m_offset, value); 1814 } 1815 relinkJump(void * from,void * to)1816 static void relinkJump(void* from, void* to) 1817 { 1818 ASSERT(!(reinterpret_cast<intptr_t>(from) & 1)); 1819 ASSERT(!(reinterpret_cast<intptr_t>(to) & 1)); 1820 1821 linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to); 1822 1823 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t)); 1824 } 1825 relinkCall(void * from,void * to)1826 static void relinkCall(void* from, void* to) 1827 { 1828 ASSERT(!(reinterpret_cast<intptr_t>(from) & 1)); 1829 ASSERT(reinterpret_cast<intptr_t>(to) & 1); 1830 1831 setPointer(reinterpret_cast<uint16_t*>(from) - 1, to); 1832 } 1833 repatchInt32(void * where,int32_t value)1834 static void repatchInt32(void* where, int32_t value) 1835 { 1836 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); 1837 1838 setInt32(where, value); 1839 } 1840 repatchPointer(void * where,void * value)1841 static void repatchPointer(void* where, void* value) 1842 { 1843 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); 1844 1845 setPointer(where, value); 1846 } 1847 1848 private: 1849 // VFP operations commonly take one or more 5-bit operands, typically representing a 1850 // floating point register number. This will commonly be encoded in the instruction 1851 // in two parts, with one single bit field, and one 4-bit field. In the case of 1852 // double precision operands the high bit of the register number will be encoded 1853 // separately, and for single precision operands the high bit of the register number 1854 // will be encoded individually. 1855 // VFPOperand encapsulates a 5-bit VFP operand, with bits 0..3 containing the 4-bit 1856 // field to be encoded together in the instruction (the low 4-bits of a double 1857 // register number, or the high 4-bits of a single register number), and bit 4 1858 // contains the bit value to be encoded individually. 1859 struct VFPOperand { VFPOperandVFPOperand1860 explicit VFPOperand(uint32_t value) 1861 : m_value(value) 1862 { 1863 ASSERT(!(m_value & ~0x1f)); 1864 } 1865 VFPOperandVFPOperand1866 VFPOperand(FPDoubleRegisterID reg) 1867 : m_value(reg) 1868 { 1869 } 1870 VFPOperandVFPOperand1871 VFPOperand(RegisterID reg) 1872 : m_value(reg) 1873 { 1874 } 1875 VFPOperandVFPOperand1876 VFPOperand(FPSingleRegisterID reg) 1877 : m_value(((reg & 1) << 4) | (reg >> 1)) // rotate the lowest bit of 'reg' to the top. 1878 { 1879 } 1880 bits1VFPOperand1881 uint32_t bits1() 1882 { 1883 return m_value >> 4; 1884 } 1885 bits4VFPOperand1886 uint32_t bits4() 1887 { 1888 return m_value & 0xf; 1889 } 1890 1891 uint32_t m_value; 1892 }; 1893 vcvtOp(bool toInteger,bool isUnsigned,bool isRoundZero)1894 VFPOperand vcvtOp(bool toInteger, bool isUnsigned, bool isRoundZero) 1895 { 1896 // Cannot specify rounding when converting to float. 1897 ASSERT(toInteger || !isRoundZero); 1898 1899 uint32_t op = 0x8; 1900 if (toInteger) { 1901 // opc2 indicates both toInteger & isUnsigned. 1902 op |= isUnsigned ? 0x4 : 0x5; 1903 // 'op' field in instruction is isRoundZero 1904 if (isRoundZero) 1905 op |= 0x10; 1906 } else { 1907 // 'op' field in instruction is isUnsigned 1908 if (!isUnsigned) 1909 op |= 0x10; 1910 } 1911 return VFPOperand(op); 1912 } 1913 setInt32(void * code,uint32_t value)1914 static void setInt32(void* code, uint32_t value) 1915 { 1916 uint16_t* location = reinterpret_cast<uint16_t*>(code); 1917 ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2)); 1918 1919 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value)); 1920 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16)); 1921 location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 1922 location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16); 1923 location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 1924 location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); 1925 1926 ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t)); 1927 } 1928 setPointer(void * code,void * value)1929 static void setPointer(void* code, void* value) 1930 { 1931 setInt32(code, reinterpret_cast<uint32_t>(value)); 1932 } 1933 isB(void * address)1934 static bool isB(void* address) 1935 { 1936 uint16_t* instruction = static_cast<uint16_t*>(address); 1937 return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b); 1938 } 1939 isBX(void * address)1940 static bool isBX(void* address) 1941 { 1942 uint16_t* instruction = static_cast<uint16_t*>(address); 1943 return (instruction[0] & 0xff87) == OP_BX; 1944 } 1945 isMOV_imm_T3(void * address)1946 static bool isMOV_imm_T3(void* address) 1947 { 1948 uint16_t* instruction = static_cast<uint16_t*>(address); 1949 return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0); 1950 } 1951 isMOVT(void * address)1952 static bool isMOVT(void* address) 1953 { 1954 uint16_t* instruction = static_cast<uint16_t*>(address); 1955 return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0); 1956 } 1957 isNOP_T1(void * address)1958 static bool isNOP_T1(void* address) 1959 { 1960 uint16_t* instruction = static_cast<uint16_t*>(address); 1961 return instruction[0] == OP_NOP_T1; 1962 } 1963 isNOP_T2(void * address)1964 static bool isNOP_T2(void* address) 1965 { 1966 uint16_t* instruction = static_cast<uint16_t*>(address); 1967 return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b); 1968 } 1969 canBeJumpT1(const uint16_t * instruction,const void * target)1970 static bool canBeJumpT1(const uint16_t* instruction, const void* target) 1971 { 1972 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1973 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 1974 1975 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 1976 // It does not appear to be documented in the ARM ARM (big surprise), but 1977 // for OP_B_T1 the branch displacement encoded in the instruction is 2 1978 // less than the actual displacement. 1979 relative -= 2; 1980 return ((relative << 23) >> 23) == relative; 1981 } 1982 canBeJumpT2(const uint16_t * instruction,const void * target)1983 static bool canBeJumpT2(const uint16_t* instruction, const void* target) 1984 { 1985 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1986 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 1987 1988 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 1989 // It does not appear to be documented in the ARM ARM (big surprise), but 1990 // for OP_B_T2 the branch displacement encoded in the instruction is 2 1991 // less than the actual displacement. 1992 relative -= 2; 1993 return ((relative << 20) >> 20) == relative; 1994 } 1995 canBeJumpT3(const uint16_t * instruction,const void * target,bool & mayTriggerErrata)1996 static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) 1997 { 1998 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1999 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2000 2001 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 2002 // From Cortex-A8 errata: 2003 // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and 2004 // the target of the branch falls within the first region it is 2005 // possible for the processor to incorrectly determine the branch 2006 // instruction, and it is also possible in some cases for the processor 2007 // to enter a deadlock state. 2008 // The instruction is spanning two pages if it ends at an address ending 0x002 2009 bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002); 2010 mayTriggerErrata = spansTwo4K; 2011 // The target is in the first page if the jump branch back by [3..0x1002] bytes 2012 bool targetInFirstPage = (relative >= -0x1002) && (relative < -2); 2013 bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage; 2014 return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata; 2015 } 2016 canBeJumpT4(const uint16_t * instruction,const void * target,bool & mayTriggerErrata)2017 static bool canBeJumpT4(const uint16_t* instruction, const void* target, bool& mayTriggerErrata) 2018 { 2019 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2020 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2021 2022 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 2023 // From Cortex-A8 errata: 2024 // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and 2025 // the target of the branch falls within the first region it is 2026 // possible for the processor to incorrectly determine the branch 2027 // instruction, and it is also possible in some cases for the processor 2028 // to enter a deadlock state. 2029 // The instruction is spanning two pages if it ends at an address ending 0x002 2030 bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002); 2031 mayTriggerErrata = spansTwo4K; 2032 // The target is in the first page if the jump branch back by [3..0x1002] bytes 2033 bool targetInFirstPage = (relative >= -0x1002) && (relative < -2); 2034 bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage; 2035 return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata; 2036 } 2037 linkJumpT1(Condition cond,uint16_t * instruction,void * target)2038 void linkJumpT1(Condition cond, uint16_t* instruction, void* target) 2039 { 2040 // FIMXE: this should be up in the MacroAssembler layer. :-( 2041 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2042 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2043 ASSERT(canBeJumpT1(instruction, target)); 2044 2045 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 2046 // It does not appear to be documented in the ARM ARM (big surprise), but 2047 // for OP_B_T1 the branch displacement encoded in the instruction is 2 2048 // less than the actual displacement. 2049 relative -= 2; 2050 2051 // All branch offsets should be an even distance. 2052 ASSERT(!(relative & 1)); 2053 instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1); 2054 } 2055 linkJumpT2(uint16_t * instruction,void * target)2056 static void linkJumpT2(uint16_t* instruction, void* target) 2057 { 2058 // FIMXE: this should be up in the MacroAssembler layer. :-( 2059 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2060 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2061 ASSERT(canBeJumpT2(instruction, target)); 2062 2063 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 2064 // It does not appear to be documented in the ARM ARM (big surprise), but 2065 // for OP_B_T2 the branch displacement encoded in the instruction is 2 2066 // less than the actual displacement. 2067 relative -= 2; 2068 2069 // All branch offsets should be an even distance. 2070 ASSERT(!(relative & 1)); 2071 instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1); 2072 } 2073 linkJumpT3(Condition cond,uint16_t * instruction,void * target)2074 void linkJumpT3(Condition cond, uint16_t* instruction, void* target) 2075 { 2076 // FIMXE: this should be up in the MacroAssembler layer. :-( 2077 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2078 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2079 bool scratch; 2080 UNUSED_PARAM(scratch); 2081 ASSERT(canBeJumpT3(instruction, target, scratch)); 2082 2083 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 2084 2085 // All branch offsets should be an even distance. 2086 ASSERT(!(relative & 1)); 2087 instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12); 2088 instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1); 2089 } 2090 linkJumpT4(uint16_t * instruction,void * target)2091 static void linkJumpT4(uint16_t* instruction, void* target) 2092 { 2093 // FIMXE: this should be up in the MacroAssembler layer. :-( 2094 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2095 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2096 bool scratch; 2097 UNUSED_PARAM(scratch); 2098 ASSERT(canBeJumpT4(instruction, target, scratch)); 2099 2100 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 2101 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 2102 if (relative >= 0) 2103 relative ^= 0xC00000; 2104 2105 // All branch offsets should be an even distance. 2106 ASSERT(!(relative & 1)); 2107 instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 2108 instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 2109 } 2110 linkConditionalJumpT4(Condition cond,uint16_t * instruction,void * target)2111 void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target) 2112 { 2113 // FIMXE: this should be up in the MacroAssembler layer. :-( 2114 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2115 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2116 2117 instruction[-3] = ifThenElse(cond) | OP_IT; 2118 linkJumpT4(instruction, target); 2119 } 2120 linkBX(uint16_t * instruction,void * target)2121 static void linkBX(uint16_t* instruction, void* target) 2122 { 2123 // FIMXE: this should be up in the MacroAssembler layer. :-( 2124 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2125 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2126 2127 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; 2128 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); 2129 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); 2130 instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 2131 instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); 2132 instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 2133 instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); 2134 instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); 2135 } 2136 linkConditionalBX(Condition cond,uint16_t * instruction,void * target)2137 void linkConditionalBX(Condition cond, uint16_t* instruction, void* target) 2138 { 2139 // FIMXE: this should be up in the MacroAssembler layer. :-( 2140 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2141 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2142 2143 linkBX(instruction, target); 2144 instruction[-6] = ifThenElse(cond, true, true) | OP_IT; 2145 } 2146 linkJumpAbsolute(uint16_t * instruction,void * target)2147 static void linkJumpAbsolute(uint16_t* instruction, void* target) 2148 { 2149 // FIMXE: this should be up in the MacroAssembler layer. :-( 2150 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 2151 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 2152 2153 ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) 2154 || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2))); 2155 2156 bool scratch; 2157 if (canBeJumpT4(instruction, target, scratch)) { 2158 // There may be a better way to fix this, but right now put the NOPs first, since in the 2159 // case of an conditional branch this will be coming after an ITTT predicating *three* 2160 // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to 2161 // variable wdith encoding - the previous instruction might *look* like an ITTT but 2162 // actually be the second half of a 2-word op. 2163 instruction[-5] = OP_NOP_T1; 2164 instruction[-4] = OP_NOP_T2a; 2165 instruction[-3] = OP_NOP_T2b; 2166 linkJumpT4(instruction, target); 2167 } else { 2168 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; 2169 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); 2170 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); 2171 instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 2172 instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); 2173 instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 2174 instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); 2175 instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); 2176 } 2177 } 2178 twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op,ARMThumbImmediate imm)2179 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm) 2180 { 2181 return op | (imm.m_value.i << 10) | imm.m_value.imm4; 2182 } 2183 twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd,ARMThumbImmediate imm)2184 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm) 2185 { 2186 return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8; 2187 } 2188 2189 class ARMInstructionFormatter { 2190 public: oneWordOp5Reg3Imm8(OpcodeID op,RegisterID rd,uint8_t imm)2191 void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm) 2192 { 2193 m_buffer.putShort(op | (rd << 8) | imm); 2194 } 2195 oneWordOp5Imm5Reg3Reg3(OpcodeID op,uint8_t imm,RegisterID reg1,RegisterID reg2)2196 void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2) 2197 { 2198 m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2); 2199 } 2200 oneWordOp7Reg3Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2,RegisterID reg3)2201 void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3) 2202 { 2203 m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3); 2204 } 2205 oneWordOp8Imm8(OpcodeID op,uint8_t imm)2206 void oneWordOp8Imm8(OpcodeID op, uint8_t imm) 2207 { 2208 m_buffer.putShort(op | imm); 2209 } 2210 oneWordOp8RegReg143(OpcodeID op,RegisterID reg1,RegisterID reg2)2211 void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2) 2212 { 2213 m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7)); 2214 } oneWordOp9Imm7(OpcodeID op,uint8_t imm)2215 void oneWordOp9Imm7(OpcodeID op, uint8_t imm) 2216 { 2217 m_buffer.putShort(op | imm); 2218 } 2219 oneWordOp10Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2)2220 void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2) 2221 { 2222 m_buffer.putShort(op | (reg1 << 3) | reg2); 2223 } 2224 twoWordOp12Reg4FourFours(OpcodeID1 op,RegisterID reg,FourFours ff)2225 void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff) 2226 { 2227 m_buffer.putShort(op | reg); 2228 m_buffer.putShort(ff.m_u.value); 2229 } 2230 twoWordOp16FourFours(OpcodeID1 op,FourFours ff)2231 void twoWordOp16FourFours(OpcodeID1 op, FourFours ff) 2232 { 2233 m_buffer.putShort(op); 2234 m_buffer.putShort(ff.m_u.value); 2235 } 2236 twoWordOp16Op16(OpcodeID1 op1,OpcodeID2 op2)2237 void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2) 2238 { 2239 m_buffer.putShort(op1); 2240 m_buffer.putShort(op2); 2241 } 2242 twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op,int imm4,RegisterID rd,ARMThumbImmediate imm)2243 void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm) 2244 { 2245 ARMThumbImmediate newImm = imm; 2246 newImm.m_value.imm4 = imm4; 2247 2248 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm)); 2249 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm)); 2250 } 2251 twoWordOp12Reg4Reg4Imm12(OpcodeID1 op,RegisterID reg1,RegisterID reg2,uint16_t imm)2252 void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm) 2253 { 2254 m_buffer.putShort(op | reg1); 2255 m_buffer.putShort((reg2 << 12) | imm); 2256 } 2257 2258 // Formats up instructions of the pattern: 2259 // 111111111B11aaaa:bbbb222SA2C2cccc 2260 // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit. 2261 // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc. vfpOp(OpcodeID1 op1,OpcodeID2 op2,bool size,VFPOperand a,VFPOperand b,VFPOperand c)2262 void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c) 2263 { 2264 ASSERT(!(op1 & 0x004f)); 2265 ASSERT(!(op2 & 0xf1af)); 2266 m_buffer.putShort(op1 | b.bits1() << 6 | a.bits4()); 2267 m_buffer.putShort(op2 | b.bits4() << 12 | size << 8 | a.bits1() << 7 | c.bits1() << 5 | c.bits4()); 2268 } 2269 2270 // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. 2271 // (i.e. +/-(0..255) 32-bit words) vfpMemOp(OpcodeID1 op1,OpcodeID2 op2,bool size,RegisterID rn,VFPOperand rd,int32_t imm)2272 void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm) 2273 { 2274 bool up = true; 2275 if (imm < 0) { 2276 imm = -imm; 2277 up = false; 2278 } 2279 2280 uint32_t offset = imm; 2281 ASSERT(!(offset & ~0x3fc)); 2282 offset >>= 2; 2283 2284 m_buffer.putShort(op1 | (up << 7) | rd.bits1() << 6 | rn); 2285 m_buffer.putShort(op2 | rd.bits4() << 12 | size << 8 | offset); 2286 } 2287 2288 // Administrative methods: 2289 size()2290 size_t size() const { return m_buffer.size(); } isAligned(int alignment)2291 bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } data()2292 void* data() const { return m_buffer.data(); } executableCopy(ExecutablePool * allocator)2293 void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); } 2294 2295 #ifndef NDEBUG debugOffset()2296 unsigned debugOffset() { return m_formatter.debugOffset(); } 2297 #endif 2298 2299 private: 2300 AssemblerBuffer m_buffer; 2301 } m_formatter; 2302 2303 Vector<LinkRecord> m_jumpsToLink; 2304 Vector<int32_t> m_offsets; 2305 }; 2306 2307 } // namespace JSC 2308 2309 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) 2310 2311 #endif // ARMAssembler_h 2312