1 /* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef ARMAssembler_h 27 #define ARMAssembler_h 28 29 #include <wtf/Platform.h> 30 31 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) 32 33 #include "AssemblerBuffer.h" 34 #include <wtf/Assertions.h> 35 #include <wtf/Vector.h> 36 #include <stdint.h> 37 38 namespace JSC { 39 40 namespace ARMRegisters { 41 typedef enum { 42 r0, 43 r1, 44 r2, 45 r3, 46 r4, 47 r5, 48 r6, 49 r7, wr = r7, // thumb work register 50 r8, 51 r9, sb = r9, // static base 52 r10, sl = r10, // stack limit 53 r11, fp = r11, // frame pointer 54 r12, ip = r12, 55 r13, sp = r13, 56 r14, lr = r14, 57 r15, pc = r15, 58 } RegisterID; 59 60 // s0 == d0 == q0 61 // s4 == d2 == q1 62 // etc 63 typedef enum { 64 s0 = 0, 65 s1 = 1, 66 s2 = 2, 67 s3 = 3, 68 s4 = 4, 69 s5 = 5, 70 s6 = 6, 71 s7 = 7, 72 s8 = 8, 73 s9 = 9, 74 s10 = 10, 75 s11 = 11, 76 s12 = 12, 77 s13 = 13, 78 s14 = 14, 79 s15 = 15, 80 s16 = 16, 81 s17 = 17, 82 s18 = 18, 83 s19 = 19, 84 s20 = 20, 85 s21 = 21, 86 s22 = 22, 87 s23 = 23, 88 s24 = 24, 89 s25 = 25, 90 s26 = 26, 91 s27 = 27, 92 s28 = 28, 93 s29 = 29, 94 s30 = 30, 95 s31 = 31, 96 d0 = 0 << 1, 97 d1 = 1 << 1, 98 d2 = 2 << 1, 99 d3 = 3 << 1, 100 d4 = 4 << 1, 101 d5 = 5 << 1, 102 d6 = 6 << 1, 103 d7 = 7 << 1, 104 d8 = 8 << 1, 105 d9 = 9 << 1, 106 d10 = 10 << 1, 107 d11 = 11 << 1, 108 d12 = 12 << 1, 109 d13 = 13 << 1, 110 d14 = 14 << 1, 111 d15 = 15 << 1, 112 d16 = 16 << 1, 113 d17 = 17 << 1, 114 d18 = 18 << 1, 115 d19 = 19 << 1, 116 d20 = 20 << 1, 117 d21 = 21 << 1, 118 d22 = 22 << 1, 119 d23 = 23 << 1, 120 d24 = 24 << 1, 121 d25 = 25 << 1, 122 d26 = 26 << 1, 123 d27 = 27 << 1, 124 d28 = 28 << 1, 125 d29 = 29 << 1, 126 d30 = 30 << 1, 127 d31 = 31 << 1, 128 q0 = 0 << 2, 129 q1 = 1 << 2, 130 q2 = 2 << 2, 131 q3 = 3 << 2, 132 q4 = 4 << 2, 133 q5 = 5 << 2, 134 q6 = 6 << 2, 135 q7 = 7 << 2, 136 q8 = 8 << 2, 137 q9 = 9 << 2, 138 q10 = 10 << 2, 139 q11 = 11 << 2, 140 q12 = 12 << 2, 141 q13 = 13 << 2, 142 q14 = 14 << 2, 143 q15 = 15 << 2, 144 q16 = 16 << 2, 145 q17 = 17 << 2, 146 q18 = 18 << 2, 147 q19 = 19 << 2, 148 q20 = 20 << 2, 149 q21 = 21 << 2, 150 q22 = 22 << 2, 151 q23 = 23 << 2, 152 q24 = 24 << 2, 153 q25 = 25 << 2, 154 q26 = 26 << 2, 155 q27 = 27 << 2, 156 q28 = 28 << 2, 157 q29 = 29 << 2, 158 q30 = 30 << 2, 159 q31 = 31 << 2, 160 } FPRegisterID; 161 } 162 163 class ARMv7Assembler; 164 class ARMThumbImmediate { 165 friend class ARMv7Assembler; 166 167 typedef uint8_t ThumbImmediateType; 168 static const ThumbImmediateType TypeInvalid = 0; 169 static const ThumbImmediateType TypeEncoded = 1; 170 static const ThumbImmediateType TypeUInt16 = 2; 171 172 typedef union { 173 int16_t asInt; 174 struct { 175 unsigned imm8 : 8; 176 unsigned imm3 : 3; 177 unsigned i : 1; 178 unsigned imm4 : 4; 179 }; 180 // If this is an encoded immediate, then it may describe a shift, or a pattern. 181 struct { 182 unsigned shiftValue7 : 7; 183 unsigned shiftAmount : 5; 184 }; 185 struct { 186 unsigned immediate : 8; 187 unsigned pattern : 4; 188 }; 189 } ThumbImmediateValue; 190 191 // byte0 contains least significant bit; not using an array to make client code endian agnostic. 192 typedef union { 193 int32_t asInt; 194 struct { 195 uint8_t byte0; 196 uint8_t byte1; 197 uint8_t byte2; 198 uint8_t byte3; 199 }; 200 } PatternBytes; 201 countLeadingZerosPartial(uint32_t & value,int32_t & zeros,const int N)202 ALWAYS_INLINE static void countLeadingZerosPartial(uint32_t& value, int32_t& zeros, const int N) 203 { 204 if (value & ~((1 << N) - 1)) /* check for any of the top N bits (of 2N bits) are set */ 205 value >>= N; /* if any were set, lose the bottom N */ 206 else /* if none of the top N bits are set, */ 207 zeros += N; /* then we have identified N leading zeros */ 208 } 209 countLeadingZeros(uint32_t value)210 static int32_t countLeadingZeros(uint32_t value) 211 { 212 if (!value) 213 return 32; 214 215 int32_t zeros = 0; 216 countLeadingZerosPartial(value, zeros, 16); 217 countLeadingZerosPartial(value, zeros, 8); 218 countLeadingZerosPartial(value, zeros, 4); 219 countLeadingZerosPartial(value, zeros, 2); 220 countLeadingZerosPartial(value, zeros, 1); 221 return zeros; 222 } 223 ARMThumbImmediate()224 ARMThumbImmediate() 225 : m_type(TypeInvalid) 226 { 227 m_value.asInt = 0; 228 } 229 ARMThumbImmediate(ThumbImmediateType type,ThumbImmediateValue value)230 ARMThumbImmediate(ThumbImmediateType type, ThumbImmediateValue value) 231 : m_type(type) 232 , m_value(value) 233 { 234 } 235 ARMThumbImmediate(ThumbImmediateType type,uint16_t value)236 ARMThumbImmediate(ThumbImmediateType type, uint16_t value) 237 : m_type(TypeUInt16) 238 { 239 // Make sure this constructor is only reached with type TypeUInt16; 240 // this extra parameter makes the code a little clearer by making it 241 // explicit at call sites which type is being constructed 242 ASSERT_UNUSED(type, type == TypeUInt16); 243 244 m_value.asInt = value; 245 } 246 247 public: makeEncodedImm(uint32_t value)248 static ARMThumbImmediate makeEncodedImm(uint32_t value) 249 { 250 ThumbImmediateValue encoding; 251 encoding.asInt = 0; 252 253 // okay, these are easy. 254 if (value < 256) { 255 encoding.immediate = value; 256 encoding.pattern = 0; 257 return ARMThumbImmediate(TypeEncoded, encoding); 258 } 259 260 int32_t leadingZeros = countLeadingZeros(value); 261 // if there were 24 or more leading zeros, then we'd have hit the (value < 256) case. 262 ASSERT(leadingZeros < 24); 263 264 // Given a number with bit fields Z:B:C, where count(Z)+count(B)+count(C) == 32, 265 // Z are the bits known zero, B is the 8-bit immediate, C are the bits to check for 266 // zero. count(B) == 8, so the count of bits to be checked is 24 - count(Z). 267 int32_t rightShiftAmount = 24 - leadingZeros; 268 if (value == ((value >> rightShiftAmount) << rightShiftAmount)) { 269 // Shift the value down to the low byte position. The assign to 270 // shiftValue7 drops the implicit top bit. 271 encoding.shiftValue7 = value >> rightShiftAmount; 272 // The endoded shift amount is the magnitude of a right rotate. 273 encoding.shiftAmount = 8 + leadingZeros; 274 return ARMThumbImmediate(TypeEncoded, encoding); 275 } 276 277 PatternBytes bytes; 278 bytes.asInt = value; 279 280 if ((bytes.byte0 == bytes.byte1) && (bytes.byte0 == bytes.byte2) && (bytes.byte0 == bytes.byte3)) { 281 encoding.immediate = bytes.byte0; 282 encoding.pattern = 3; 283 return ARMThumbImmediate(TypeEncoded, encoding); 284 } 285 286 if ((bytes.byte0 == bytes.byte2) && !(bytes.byte1 | bytes.byte3)) { 287 encoding.immediate = bytes.byte0; 288 encoding.pattern = 1; 289 return ARMThumbImmediate(TypeEncoded, encoding); 290 } 291 292 if ((bytes.byte1 == bytes.byte3) && !(bytes.byte0 | bytes.byte2)) { 293 encoding.immediate = bytes.byte0; 294 encoding.pattern = 2; 295 return ARMThumbImmediate(TypeEncoded, encoding); 296 } 297 298 return ARMThumbImmediate(); 299 } 300 makeUInt12(int32_t value)301 static ARMThumbImmediate makeUInt12(int32_t value) 302 { 303 return (!(value & 0xfffff000)) 304 ? ARMThumbImmediate(TypeUInt16, (uint16_t)value) 305 : ARMThumbImmediate(); 306 } 307 makeUInt12OrEncodedImm(int32_t value)308 static ARMThumbImmediate makeUInt12OrEncodedImm(int32_t value) 309 { 310 // If this is not a 12-bit unsigned it, try making an encoded immediate. 311 return (!(value & 0xfffff000)) 312 ? ARMThumbImmediate(TypeUInt16, (uint16_t)value) 313 : makeEncodedImm(value); 314 } 315 316 // The 'make' methods, above, return a !isValid() value if the argument 317 // cannot be represented as the requested type. This methods is called 318 // 'get' since the argument can always be represented. makeUInt16(uint16_t value)319 static ARMThumbImmediate makeUInt16(uint16_t value) 320 { 321 return ARMThumbImmediate(TypeUInt16, value); 322 } 323 isValid()324 bool isValid() 325 { 326 return m_type != TypeInvalid; 327 } 328 329 // These methods rely on the format of encoded byte values. isUInt3()330 bool isUInt3() { return !(m_value.asInt & 0xfff8); } isUInt4()331 bool isUInt4() { return !(m_value.asInt & 0xfff0); } isUInt5()332 bool isUInt5() { return !(m_value.asInt & 0xffe0); } isUInt6()333 bool isUInt6() { return !(m_value.asInt & 0xffc0); } isUInt7()334 bool isUInt7() { return !(m_value.asInt & 0xff80); } isUInt8()335 bool isUInt8() { return !(m_value.asInt & 0xff00); } isUInt9()336 bool isUInt9() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfe00); } isUInt10()337 bool isUInt10() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xfc00); } isUInt12()338 bool isUInt12() { return (m_type == TypeUInt16) && !(m_value.asInt & 0xf000); } isUInt16()339 bool isUInt16() { return m_type == TypeUInt16; } getUInt3()340 uint8_t getUInt3() { ASSERT(isUInt3()); return m_value.asInt; } getUInt4()341 uint8_t getUInt4() { ASSERT(isUInt4()); return m_value.asInt; } getUInt5()342 uint8_t getUInt5() { ASSERT(isUInt5()); return m_value.asInt; } getUInt6()343 uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; } getUInt7()344 uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; } getUInt8()345 uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; } getUInt9()346 uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; } getUInt10()347 uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; } getUInt12()348 uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; } getUInt16()349 uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; } 350 isEncodedImm()351 bool isEncodedImm() { return m_type == TypeEncoded; } 352 353 private: 354 ThumbImmediateType m_type; 355 ThumbImmediateValue m_value; 356 }; 357 358 359 typedef enum { 360 SRType_LSL, 361 SRType_LSR, 362 SRType_ASR, 363 SRType_ROR, 364 365 SRType_RRX = SRType_ROR 366 } ARMShiftType; 367 368 class ARMv7Assembler; 369 class ShiftTypeAndAmount { 370 friend class ARMv7Assembler; 371 372 public: ShiftTypeAndAmount()373 ShiftTypeAndAmount() 374 { 375 m_u.type = (ARMShiftType)0; 376 m_u.amount = 0; 377 } 378 ShiftTypeAndAmount(ARMShiftType type,unsigned amount)379 ShiftTypeAndAmount(ARMShiftType type, unsigned amount) 380 { 381 m_u.type = type; 382 m_u.amount = amount & 31; 383 } 384 lo4()385 unsigned lo4() { return m_u.lo4; } hi4()386 unsigned hi4() { return m_u.hi4; } 387 388 private: 389 union { 390 struct { 391 unsigned lo4 : 4; 392 unsigned hi4 : 4; 393 }; 394 struct { 395 unsigned type : 2; 396 unsigned amount : 5; 397 }; 398 } m_u; 399 }; 400 401 402 /* 403 Some features of the Thumb instruction set are deprecated in ARMv7. Deprecated features affecting 404 instructions supported by ARMv7-M are as follows: 405 • use of the PC as <Rd> or <Rm> in a 16-bit ADD (SP plus register) instruction 406 • use of the SP as <Rm> in a 16-bit ADD (SP plus register) instruction 407 • use of the SP as <Rm> in a 16-bit CMP (register) instruction 408 • use of MOV (register) instructions in which <Rd> is the SP or PC and <Rm> is also the SP or PC. 409 • use of <Rn> as the lowest-numbered register in the register list of a 16-bit STM instruction with base 410 register writeback 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::FPRegisterID FPRegisterID; 422 423 // (HS, LO, HI, LS) -> (AE, B, A, BE) 424 // (VS, VC) -> (O, NO) 425 typedef enum { 426 ConditionEQ, 427 ConditionNE, 428 ConditionHS, 429 ConditionLO, 430 ConditionMI, 431 ConditionPL, 432 ConditionVS, 433 ConditionVC, 434 ConditionHI, 435 ConditionLS, 436 ConditionGE, 437 ConditionLT, 438 ConditionGT, 439 ConditionLE, 440 ConditionAL, 441 442 ConditionCS = ConditionHS, 443 ConditionCC = ConditionLO, 444 } Condition; 445 446 class JmpSrc { 447 friend class ARMv7Assembler; 448 friend class ARMInstructionFormatter; 449 public: JmpSrc()450 JmpSrc() 451 : m_offset(-1) 452 { 453 } 454 455 private: JmpSrc(int offset)456 JmpSrc(int offset) 457 : m_offset(offset) 458 { 459 } 460 461 int m_offset; 462 }; 463 464 class JmpDst { 465 friend class ARMv7Assembler; 466 friend class ARMInstructionFormatter; 467 public: JmpDst()468 JmpDst() 469 : m_offset(-1) 470 , m_used(false) 471 { 472 } 473 isUsed()474 bool isUsed() const { return m_used; } used()475 void used() { m_used = true; } 476 private: JmpDst(int offset)477 JmpDst(int offset) 478 : m_offset(offset) 479 , m_used(false) 480 { 481 ASSERT(m_offset == offset); 482 } 483 484 int m_offset : 31; 485 int m_used : 1; 486 }; 487 488 private: 489 490 struct LinkRecord { LinkRecordLinkRecord491 LinkRecord(intptr_t from, intptr_t to) 492 : from(from) 493 , to(to) 494 { 495 } 496 497 intptr_t from; 498 intptr_t to; 499 }; 500 501 // ARMv7, Appx-A.6.3 BadReg(RegisterID reg)502 bool BadReg(RegisterID reg) 503 { 504 return (reg == ARMRegisters::sp) || (reg == ARMRegisters::pc); 505 } 506 isSingleRegister(FPRegisterID reg)507 bool isSingleRegister(FPRegisterID reg) 508 { 509 // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc). 510 return !(reg & ~31); 511 } 512 isDoubleRegister(FPRegisterID reg)513 bool isDoubleRegister(FPRegisterID reg) 514 { 515 // Check that the high bit isn't set (q16+), and that the low bit isn't (s1, s3, etc). 516 return !(reg & ~(31 << 1)); 517 } 518 isQuadRegister(FPRegisterID reg)519 bool isQuadRegister(FPRegisterID reg) 520 { 521 return !(reg & ~(31 << 2)); 522 } 523 singleRegisterNum(FPRegisterID reg)524 uint32_t singleRegisterNum(FPRegisterID reg) 525 { 526 ASSERT(isSingleRegister(reg)); 527 return reg; 528 } 529 doubleRegisterNum(FPRegisterID reg)530 uint32_t doubleRegisterNum(FPRegisterID reg) 531 { 532 ASSERT(isDoubleRegister(reg)); 533 return reg >> 1; 534 } 535 quadRegisterNum(FPRegisterID reg)536 uint32_t quadRegisterNum(FPRegisterID reg) 537 { 538 ASSERT(isQuadRegister(reg)); 539 return reg >> 2; 540 } 541 singleRegisterMask(FPRegisterID rd,int highBitsShift,int lowBitShift)542 uint32_t singleRegisterMask(FPRegisterID rd, int highBitsShift, int lowBitShift) 543 { 544 uint32_t rdNum = singleRegisterNum(rd); 545 uint32_t rdMask = (rdNum >> 1) << highBitsShift; 546 if (rdNum & 1) 547 rdMask |= 1 << lowBitShift; 548 return rdMask; 549 } 550 doubleRegisterMask(FPRegisterID rd,int highBitShift,int lowBitsShift)551 uint32_t doubleRegisterMask(FPRegisterID rd, int highBitShift, int lowBitsShift) 552 { 553 uint32_t rdNum = doubleRegisterNum(rd); 554 uint32_t rdMask = (rdNum & 0xf) << lowBitsShift; 555 if (rdNum & 16) 556 rdMask |= 1 << highBitShift; 557 return rdMask; 558 } 559 560 typedef enum { 561 OP_ADD_reg_T1 = 0x1800, 562 OP_ADD_S_reg_T1 = 0x1800, 563 OP_SUB_reg_T1 = 0x1A00, 564 OP_SUB_S_reg_T1 = 0x1A00, 565 OP_ADD_imm_T1 = 0x1C00, 566 OP_ADD_S_imm_T1 = 0x1C00, 567 OP_SUB_imm_T1 = 0x1E00, 568 OP_SUB_S_imm_T1 = 0x1E00, 569 OP_MOV_imm_T1 = 0x2000, 570 OP_CMP_imm_T1 = 0x2800, 571 OP_ADD_imm_T2 = 0x3000, 572 OP_ADD_S_imm_T2 = 0x3000, 573 OP_SUB_imm_T2 = 0x3800, 574 OP_SUB_S_imm_T2 = 0x3800, 575 OP_AND_reg_T1 = 0x4000, 576 OP_EOR_reg_T1 = 0x4040, 577 OP_TST_reg_T1 = 0x4200, 578 OP_CMP_reg_T1 = 0x4280, 579 OP_ORR_reg_T1 = 0x4300, 580 OP_MVN_reg_T1 = 0x43C0, 581 OP_ADD_reg_T2 = 0x4400, 582 OP_MOV_reg_T1 = 0x4600, 583 OP_BLX = 0x4700, 584 OP_BX = 0x4700, 585 OP_LDRH_reg_T1 = 0x5A00, 586 OP_STR_reg_T1 = 0x5000, 587 OP_LDR_reg_T1 = 0x5800, 588 OP_STR_imm_T1 = 0x6000, 589 OP_LDR_imm_T1 = 0x6800, 590 OP_LDRH_imm_T1 = 0x8800, 591 OP_STR_imm_T2 = 0x9000, 592 OP_LDR_imm_T2 = 0x9800, 593 OP_ADD_SP_imm_T1 = 0xA800, 594 OP_ADD_SP_imm_T2 = 0xB000, 595 OP_SUB_SP_imm_T1 = 0xB080, 596 OP_BKPT = 0xBE00, 597 OP_IT = 0xBF00, 598 OP_NOP_T1 = 0xBF00, 599 } OpcodeID; 600 601 typedef enum { 602 OP_AND_reg_T2 = 0xEA00, 603 OP_TST_reg_T2 = 0xEA10, 604 OP_ORR_reg_T2 = 0xEA40, 605 OP_ASR_imm_T1 = 0xEA4F, 606 OP_LSL_imm_T1 = 0xEA4F, 607 OP_LSR_imm_T1 = 0xEA4F, 608 OP_ROR_imm_T1 = 0xEA4F, 609 OP_MVN_reg_T2 = 0xEA6F, 610 OP_EOR_reg_T2 = 0xEA80, 611 OP_ADD_reg_T3 = 0xEB00, 612 OP_ADD_S_reg_T3 = 0xEB10, 613 OP_SUB_reg_T2 = 0xEBA0, 614 OP_SUB_S_reg_T2 = 0xEBB0, 615 OP_CMP_reg_T2 = 0xEBB0, 616 OP_B_T4a = 0xF000, 617 OP_AND_imm_T1 = 0xF000, 618 OP_TST_imm = 0xF010, 619 OP_ORR_imm_T1 = 0xF040, 620 OP_MOV_imm_T2 = 0xF040, 621 OP_MVN_imm = 0xF060, 622 OP_EOR_imm_T1 = 0xF080, 623 OP_ADD_imm_T3 = 0xF100, 624 OP_ADD_S_imm_T3 = 0xF110, 625 OP_CMN_imm = 0xF110, 626 OP_SUB_imm_T3 = 0xF1A0, 627 OP_SUB_S_imm_T3 = 0xF1B0, 628 OP_CMP_imm_T2 = 0xF1B0, 629 OP_ADD_imm_T4 = 0xF200, 630 OP_MOV_imm_T3 = 0xF240, 631 OP_SUB_imm_T4 = 0xF2A0, 632 OP_MOVT = 0xF2C0, 633 OP_NOP_T2a = 0xF3AF, 634 OP_LDRH_reg_T2 = 0xF830, 635 OP_LDRH_imm_T3 = 0xF830, 636 OP_STR_imm_T4 = 0xF840, 637 OP_STR_reg_T2 = 0xF840, 638 OP_LDR_imm_T4 = 0xF850, 639 OP_LDR_reg_T2 = 0xF850, 640 OP_LDRH_imm_T2 = 0xF8B0, 641 OP_STR_imm_T3 = 0xF8C0, 642 OP_LDR_imm_T3 = 0xF8D0, 643 OP_LSL_reg_T2 = 0xFA00, 644 OP_LSR_reg_T2 = 0xFA20, 645 OP_ASR_reg_T2 = 0xFA40, 646 OP_ROR_reg_T2 = 0xFA60, 647 OP_SMULL_T1 = 0xFB80, 648 } OpcodeID1; 649 650 typedef enum { 651 OP_B_T4b = 0x9000, 652 OP_NOP_T2b = 0x8000, 653 } OpcodeID2; 654 655 struct FourFours { FourFoursFourFours656 FourFours(unsigned f3, unsigned f2, unsigned f1, unsigned f0) 657 { 658 m_u.f0 = f0; 659 m_u.f1 = f1; 660 m_u.f2 = f2; 661 m_u.f3 = f3; 662 } 663 664 union { 665 unsigned value; 666 struct { 667 unsigned f0 : 4; 668 unsigned f1 : 4; 669 unsigned f2 : 4; 670 unsigned f3 : 4; 671 }; 672 } m_u; 673 }; 674 675 class ARMInstructionFormatter; 676 677 // false means else! ifThenElseConditionBit(Condition condition,bool isIf)678 bool ifThenElseConditionBit(Condition condition, bool isIf) 679 { 680 return isIf ? (condition & 1) : !(condition & 1); 681 } ifThenElse(Condition condition,bool inst2if,bool inst3if,bool inst4if)682 uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if) 683 { 684 int mask = (ifThenElseConditionBit(condition, inst2if) << 3) 685 | (ifThenElseConditionBit(condition, inst3if) << 2) 686 | (ifThenElseConditionBit(condition, inst4if) << 1) 687 | 1; 688 ASSERT((condition != ConditionAL) || (mask & (mask - 1))); 689 return (condition << 4) | mask; 690 } ifThenElse(Condition condition,bool inst2if,bool inst3if)691 uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if) 692 { 693 int mask = (ifThenElseConditionBit(condition, inst2if) << 3) 694 | (ifThenElseConditionBit(condition, inst3if) << 2) 695 | 2; 696 ASSERT((condition != ConditionAL) || (mask & (mask - 1))); 697 return (condition << 4) | mask; 698 } ifThenElse(Condition condition,bool inst2if)699 uint8_t ifThenElse(Condition condition, bool inst2if) 700 { 701 int mask = (ifThenElseConditionBit(condition, inst2if) << 3) 702 | 4; 703 ASSERT((condition != ConditionAL) || (mask & (mask - 1))); 704 return (condition << 4) | mask; 705 } 706 ifThenElse(Condition condition)707 uint8_t ifThenElse(Condition condition) 708 { 709 int mask = 8; 710 ASSERT((condition != ConditionAL) || (mask & (mask - 1))); 711 return (condition << 4) | mask; 712 } 713 714 public: 715 add(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)716 void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 717 { 718 // Rd can only be SP if Rn is also SP. 719 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 720 ASSERT(rd != ARMRegisters::pc); 721 ASSERT(rn != ARMRegisters::pc); 722 ASSERT(imm.isValid()); 723 724 if (rn == ARMRegisters::sp) { 725 if (!(rd & 8) && imm.isUInt10()) { 726 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2); 727 return; 728 } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) { 729 m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2); 730 return; 731 } 732 } else if (!((rd | rn) & 8)) { 733 if (imm.isUInt3()) { 734 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 735 return; 736 } else if ((rd == rn) && imm.isUInt8()) { 737 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_imm_T2, rd, imm.getUInt8()); 738 return; 739 } 740 } 741 742 if (imm.isEncodedImm()) 743 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T3, rn, rd, imm); 744 else { 745 ASSERT(imm.isUInt12()); 746 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_imm_T4, rn, rd, imm); 747 } 748 } 749 add(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)750 void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 751 { 752 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 753 ASSERT(rd != ARMRegisters::pc); 754 ASSERT(rn != ARMRegisters::pc); 755 ASSERT(!BadReg(rm)); 756 m_formatter.twoWordOp12Reg4FourFours(OP_ADD_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 757 } 758 759 // NOTE: In an IT block, add doesn't modify the flags register. add(RegisterID rd,RegisterID rn,RegisterID rm)760 void add(RegisterID rd, RegisterID rn, RegisterID rm) 761 { 762 if (rd == rn) 763 m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd); 764 else if (rd == rm) 765 m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rn, rd); 766 else if (!((rd | rn | rm) & 8)) 767 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd); 768 else 769 add(rd, rn, rm, ShiftTypeAndAmount()); 770 } 771 772 // Not allowed in an IT (if then) block. add_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)773 void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 774 { 775 // Rd can only be SP if Rn is also SP. 776 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 777 ASSERT(rd != ARMRegisters::pc); 778 ASSERT(rn != ARMRegisters::pc); 779 ASSERT(imm.isEncodedImm()); 780 781 if (!((rd | rn) & 8)) { 782 if (imm.isUInt3()) { 783 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 784 return; 785 } else if ((rd == rn) && imm.isUInt8()) { 786 m_formatter.oneWordOp5Reg3Imm8(OP_ADD_S_imm_T2, rd, imm.getUInt8()); 787 return; 788 } 789 } 790 791 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ADD_S_imm_T3, rn, rd, imm); 792 } 793 794 // Not allowed in an IT (if then) block? add_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)795 void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 796 { 797 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 798 ASSERT(rd != ARMRegisters::pc); 799 ASSERT(rn != ARMRegisters::pc); 800 ASSERT(!BadReg(rm)); 801 m_formatter.twoWordOp12Reg4FourFours(OP_ADD_S_reg_T3, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 802 } 803 804 // Not allowed in an IT (if then) block. add_S(RegisterID rd,RegisterID rn,RegisterID rm)805 void add_S(RegisterID rd, RegisterID rn, RegisterID rm) 806 { 807 if (!((rd | rn | rm) & 8)) 808 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_S_reg_T1, rm, rn, rd); 809 else 810 add_S(rd, rn, rm, ShiftTypeAndAmount()); 811 } 812 ARM_and(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)813 void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 814 { 815 ASSERT(!BadReg(rd)); 816 ASSERT(!BadReg(rn)); 817 ASSERT(imm.isEncodedImm()); 818 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm); 819 } 820 ARM_and(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)821 void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 822 { 823 ASSERT(!BadReg(rd)); 824 ASSERT(!BadReg(rn)); 825 ASSERT(!BadReg(rm)); 826 m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 827 } 828 ARM_and(RegisterID rd,RegisterID rn,RegisterID rm)829 void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm) 830 { 831 if ((rd == rn) && !((rd | rm) & 8)) 832 m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd); 833 else if ((rd == rm) && !((rd | rn) & 8)) 834 m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rn, rd); 835 else 836 ARM_and(rd, rn, rm, ShiftTypeAndAmount()); 837 } 838 asr(RegisterID rd,RegisterID rm,int32_t shiftAmount)839 void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount) 840 { 841 ASSERT(!BadReg(rd)); 842 ASSERT(!BadReg(rm)); 843 ShiftTypeAndAmount shift(SRType_ASR, shiftAmount); 844 m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 845 } 846 asr(RegisterID rd,RegisterID rn,RegisterID rm)847 void asr(RegisterID rd, RegisterID rn, RegisterID rm) 848 { 849 ASSERT(!BadReg(rd)); 850 ASSERT(!BadReg(rn)); 851 ASSERT(!BadReg(rm)); 852 m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 853 } 854 855 // Only allowed in IT (if then) block if last instruction. b()856 JmpSrc b() 857 { 858 m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b); 859 return JmpSrc(m_formatter.size()); 860 } 861 862 // Only allowed in IT (if then) block if last instruction. blx(RegisterID rm)863 JmpSrc blx(RegisterID rm) 864 { 865 ASSERT(rm != ARMRegisters::pc); 866 m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8); 867 return JmpSrc(m_formatter.size()); 868 } 869 870 // Only allowed in IT (if then) block if last instruction. bx(RegisterID rm)871 JmpSrc bx(RegisterID rm) 872 { 873 m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0); 874 return JmpSrc(m_formatter.size()); 875 } 876 877 void bkpt(uint8_t imm=0) 878 { 879 m_formatter.oneWordOp8Imm8(OP_BKPT, imm); 880 } 881 cmn(RegisterID rn,ARMThumbImmediate imm)882 void cmn(RegisterID rn, ARMThumbImmediate imm) 883 { 884 ASSERT(rn != ARMRegisters::pc); 885 ASSERT(imm.isEncodedImm()); 886 887 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm); 888 } 889 cmp(RegisterID rn,ARMThumbImmediate imm)890 void cmp(RegisterID rn, ARMThumbImmediate imm) 891 { 892 ASSERT(rn != ARMRegisters::pc); 893 ASSERT(imm.isEncodedImm()); 894 895 if (!(rn & 8) && imm.isUInt8()) 896 m_formatter.oneWordOp5Reg3Imm8(OP_CMP_imm_T1, rn, imm.getUInt8()); 897 else 898 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm); 899 } 900 cmp(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)901 void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 902 { 903 ASSERT(rn != ARMRegisters::pc); 904 ASSERT(!BadReg(rm)); 905 m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm)); 906 } 907 cmp(RegisterID rn,RegisterID rm)908 void cmp(RegisterID rn, RegisterID rm) 909 { 910 if ((rn | rm) & 8) 911 cmp(rn, rm, ShiftTypeAndAmount()); 912 else 913 m_formatter.oneWordOp10Reg3Reg3(OP_CMP_reg_T1, rm, rn); 914 } 915 916 // xor is not spelled with an 'e'. :-( eor(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)917 void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 918 { 919 ASSERT(!BadReg(rd)); 920 ASSERT(!BadReg(rn)); 921 ASSERT(imm.isEncodedImm()); 922 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_EOR_imm_T1, rn, rd, imm); 923 } 924 925 // xor is not spelled with an 'e'. :-( eor(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)926 void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 927 { 928 ASSERT(!BadReg(rd)); 929 ASSERT(!BadReg(rn)); 930 ASSERT(!BadReg(rm)); 931 m_formatter.twoWordOp12Reg4FourFours(OP_EOR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 932 } 933 934 // xor is not spelled with an 'e'. :-( eor(RegisterID rd,RegisterID rn,RegisterID rm)935 void eor(RegisterID rd, RegisterID rn, RegisterID rm) 936 { 937 if ((rd == rn) && !((rd | rm) & 8)) 938 m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rm, rd); 939 else if ((rd == rm) && !((rd | rn) & 8)) 940 m_formatter.oneWordOp10Reg3Reg3(OP_EOR_reg_T1, rn, rd); 941 else 942 eor(rd, rn, rm, ShiftTypeAndAmount()); 943 } 944 it(Condition cond)945 void it(Condition cond) 946 { 947 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond)); 948 } 949 it(Condition cond,bool inst2if)950 void it(Condition cond, bool inst2if) 951 { 952 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if)); 953 } 954 it(Condition cond,bool inst2if,bool inst3if)955 void it(Condition cond, bool inst2if, bool inst3if) 956 { 957 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if)); 958 } 959 it(Condition cond,bool inst2if,bool inst3if,bool inst4if)960 void it(Condition cond, bool inst2if, bool inst3if, bool inst4if) 961 { 962 m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if)); 963 } 964 965 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. ldr(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)966 void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 967 { 968 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 969 ASSERT(imm.isUInt12()); 970 971 if (!((rt | rn) & 8) && imm.isUInt7()) 972 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt); 973 else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10()) 974 m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2); 975 else 976 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12()); 977 } 978 979 // If index is set, this is a regular offset or a pre-indexed load; 980 // if index is not set then is is a post-index load. 981 // 982 // If wback is set rn is updated - this is a pre or post index load, 983 // if wback is not set this is a regular offset memory access. 984 // 985 // (-255 <= offset <= 255) 986 // _reg = REG[rn] 987 // _tmp = _reg + offset 988 // MEM[index ? _tmp : _reg] = REG[rt] 989 // if (wback) REG[rn] = _tmp ldr(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)990 void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 991 { 992 ASSERT(rt != ARMRegisters::pc); 993 ASSERT(rn != ARMRegisters::pc); 994 ASSERT(index || wback); 995 ASSERT(!wback | (rt != rn)); 996 997 bool add = true; 998 if (offset < 0) { 999 add = false; 1000 offset = -offset; 1001 } 1002 ASSERT((offset & ~0xff) == 0); 1003 1004 offset |= (wback << 8); 1005 offset |= (add << 9); 1006 offset |= (index << 10); 1007 offset |= (1 << 11); 1008 1009 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T4, rn, rt, offset); 1010 } 1011 1012 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. 1013 void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0) 1014 { 1015 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1016 ASSERT(!BadReg(rm)); 1017 ASSERT(shift <= 3); 1018 1019 if (!shift && !((rt | rn | rm) & 8)) 1020 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDR_reg_T1, rm, rn, rt); 1021 else 1022 m_formatter.twoWordOp12Reg4FourFours(OP_LDR_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1023 } 1024 1025 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. ldrh(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1026 void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 1027 { 1028 ASSERT(rn != ARMRegisters::pc); // LDR (literal) 1029 ASSERT(imm.isUInt12()); 1030 1031 if (!((rt | rn) & 8) && imm.isUInt6()) 1032 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRH_imm_T1, imm.getUInt6() >> 2, rn, rt); 1033 else 1034 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T2, rn, rt, imm.getUInt12()); 1035 } 1036 1037 // If index is set, this is a regular offset or a pre-indexed load; 1038 // if index is not set then is is a post-index load. 1039 // 1040 // If wback is set rn is updated - this is a pre or post index load, 1041 // if wback is not set this is a regular offset memory access. 1042 // 1043 // (-255 <= offset <= 255) 1044 // _reg = REG[rn] 1045 // _tmp = _reg + offset 1046 // MEM[index ? _tmp : _reg] = REG[rt] 1047 // if (wback) REG[rn] = _tmp ldrh(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1048 void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 1049 { 1050 ASSERT(rt != ARMRegisters::pc); 1051 ASSERT(rn != ARMRegisters::pc); 1052 ASSERT(index || wback); 1053 ASSERT(!wback | (rt != rn)); 1054 1055 bool add = true; 1056 if (offset < 0) { 1057 add = false; 1058 offset = -offset; 1059 } 1060 ASSERT((offset & ~0xff) == 0); 1061 1062 offset |= (wback << 8); 1063 offset |= (add << 9); 1064 offset |= (index << 10); 1065 offset |= (1 << 11); 1066 1067 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset); 1068 } 1069 1070 void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0) 1071 { 1072 ASSERT(!BadReg(rt)); // Memory hint 1073 ASSERT(rn != ARMRegisters::pc); // LDRH (literal) 1074 ASSERT(!BadReg(rm)); 1075 ASSERT(shift <= 3); 1076 1077 if (!shift && !((rt | rn | rm) & 8)) 1078 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRH_reg_T1, rm, rn, rt); 1079 else 1080 m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1081 } 1082 lsl(RegisterID rd,RegisterID rm,int32_t shiftAmount)1083 void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount) 1084 { 1085 ASSERT(!BadReg(rd)); 1086 ASSERT(!BadReg(rm)); 1087 ShiftTypeAndAmount shift(SRType_LSL, shiftAmount); 1088 m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1089 } 1090 lsl(RegisterID rd,RegisterID rn,RegisterID rm)1091 void lsl(RegisterID rd, RegisterID rn, RegisterID rm) 1092 { 1093 ASSERT(!BadReg(rd)); 1094 ASSERT(!BadReg(rn)); 1095 ASSERT(!BadReg(rm)); 1096 m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 1097 } 1098 lsr(RegisterID rd,RegisterID rm,int32_t shiftAmount)1099 void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount) 1100 { 1101 ASSERT(!BadReg(rd)); 1102 ASSERT(!BadReg(rm)); 1103 ShiftTypeAndAmount shift(SRType_LSR, shiftAmount); 1104 m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1105 } 1106 lsr(RegisterID rd,RegisterID rn,RegisterID rm)1107 void lsr(RegisterID rd, RegisterID rn, RegisterID rm) 1108 { 1109 ASSERT(!BadReg(rd)); 1110 ASSERT(!BadReg(rn)); 1111 ASSERT(!BadReg(rm)); 1112 m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 1113 } 1114 movT3(RegisterID rd,ARMThumbImmediate imm)1115 void movT3(RegisterID rd, ARMThumbImmediate imm) 1116 { 1117 ASSERT(imm.isValid()); 1118 ASSERT(!imm.isEncodedImm()); 1119 ASSERT(!BadReg(rd)); 1120 1121 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm); 1122 } 1123 mov(RegisterID rd,ARMThumbImmediate imm)1124 void mov(RegisterID rd, ARMThumbImmediate imm) 1125 { 1126 ASSERT(imm.isValid()); 1127 ASSERT(!BadReg(rd)); 1128 1129 if ((rd < 8) && imm.isUInt8()) 1130 m_formatter.oneWordOp5Reg3Imm8(OP_MOV_imm_T1, rd, imm.getUInt8()); 1131 else if (imm.isEncodedImm()) 1132 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T2, 0xf, rd, imm); 1133 else 1134 movT3(rd, imm); 1135 } 1136 mov(RegisterID rd,RegisterID rm)1137 void mov(RegisterID rd, RegisterID rm) 1138 { 1139 m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd); 1140 } 1141 movt(RegisterID rd,ARMThumbImmediate imm)1142 void movt(RegisterID rd, ARMThumbImmediate imm) 1143 { 1144 ASSERT(imm.isUInt16()); 1145 ASSERT(!BadReg(rd)); 1146 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm); 1147 } 1148 mvn(RegisterID rd,ARMThumbImmediate imm)1149 void mvn(RegisterID rd, ARMThumbImmediate imm) 1150 { 1151 ASSERT(imm.isEncodedImm()); 1152 ASSERT(!BadReg(rd)); 1153 1154 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm); 1155 } 1156 mvn(RegisterID rd,RegisterID rm,ShiftTypeAndAmount shift)1157 void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift) 1158 { 1159 ASSERT(!BadReg(rd)); 1160 ASSERT(!BadReg(rm)); 1161 m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1162 } 1163 mvn(RegisterID rd,RegisterID rm)1164 void mvn(RegisterID rd, RegisterID rm) 1165 { 1166 if (!((rd | rm) & 8)) 1167 m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd); 1168 else 1169 mvn(rd, rm, ShiftTypeAndAmount()); 1170 } 1171 orr(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1172 void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 1173 { 1174 ASSERT(!BadReg(rd)); 1175 ASSERT(!BadReg(rn)); 1176 ASSERT(imm.isEncodedImm()); 1177 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm); 1178 } 1179 orr(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1180 void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1181 { 1182 ASSERT(!BadReg(rd)); 1183 ASSERT(!BadReg(rn)); 1184 ASSERT(!BadReg(rm)); 1185 m_formatter.twoWordOp12Reg4FourFours(OP_ORR_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1186 } 1187 orr(RegisterID rd,RegisterID rn,RegisterID rm)1188 void orr(RegisterID rd, RegisterID rn, RegisterID rm) 1189 { 1190 if ((rd == rn) && !((rd | rm) & 8)) 1191 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rm, rd); 1192 else if ((rd == rm) && !((rd | rn) & 8)) 1193 m_formatter.oneWordOp10Reg3Reg3(OP_ORR_reg_T1, rn, rd); 1194 else 1195 orr(rd, rn, rm, ShiftTypeAndAmount()); 1196 } 1197 ror(RegisterID rd,RegisterID rm,int32_t shiftAmount)1198 void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount) 1199 { 1200 ASSERT(!BadReg(rd)); 1201 ASSERT(!BadReg(rm)); 1202 ShiftTypeAndAmount shift(SRType_ROR, shiftAmount); 1203 m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1204 } 1205 ror(RegisterID rd,RegisterID rn,RegisterID rm)1206 void ror(RegisterID rd, RegisterID rn, RegisterID rm) 1207 { 1208 ASSERT(!BadReg(rd)); 1209 ASSERT(!BadReg(rn)); 1210 ASSERT(!BadReg(rm)); 1211 m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); 1212 } 1213 smull(RegisterID rdLo,RegisterID rdHi,RegisterID rn,RegisterID rm)1214 void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm) 1215 { 1216 ASSERT(!BadReg(rdLo)); 1217 ASSERT(!BadReg(rdHi)); 1218 ASSERT(!BadReg(rn)); 1219 ASSERT(!BadReg(rm)); 1220 ASSERT(rdLo != rdHi); 1221 m_formatter.twoWordOp12Reg4FourFours(OP_SMULL_T1, rn, FourFours(rdLo, rdHi, 0, rm)); 1222 } 1223 1224 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. str(RegisterID rt,RegisterID rn,ARMThumbImmediate imm)1225 void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) 1226 { 1227 ASSERT(rt != ARMRegisters::pc); 1228 ASSERT(rn != ARMRegisters::pc); 1229 ASSERT(imm.isUInt12()); 1230 1231 if (!((rt | rn) & 8) && imm.isUInt7()) 1232 m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt); 1233 else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10()) 1234 m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2); 1235 else 1236 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12()); 1237 } 1238 1239 // If index is set, this is a regular offset or a pre-indexed store; 1240 // if index is not set then is is a post-index store. 1241 // 1242 // If wback is set rn is updated - this is a pre or post index store, 1243 // if wback is not set this is a regular offset memory access. 1244 // 1245 // (-255 <= offset <= 255) 1246 // _reg = REG[rn] 1247 // _tmp = _reg + offset 1248 // MEM[index ? _tmp : _reg] = REG[rt] 1249 // if (wback) REG[rn] = _tmp str(RegisterID rt,RegisterID rn,int offset,bool index,bool wback)1250 void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) 1251 { 1252 ASSERT(rt != ARMRegisters::pc); 1253 ASSERT(rn != ARMRegisters::pc); 1254 ASSERT(index || wback); 1255 ASSERT(!wback | (rt != rn)); 1256 1257 bool add = true; 1258 if (offset < 0) { 1259 add = false; 1260 offset = -offset; 1261 } 1262 ASSERT((offset & ~0xff) == 0); 1263 1264 offset |= (wback << 8); 1265 offset |= (add << 9); 1266 offset |= (index << 10); 1267 offset |= (1 << 11); 1268 1269 m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T4, rn, rt, offset); 1270 } 1271 1272 // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block. 1273 void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0) 1274 { 1275 ASSERT(rn != ARMRegisters::pc); 1276 ASSERT(!BadReg(rm)); 1277 ASSERT(shift <= 3); 1278 1279 if (!shift && !((rt | rn | rm) & 8)) 1280 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_STR_reg_T1, rm, rn, rt); 1281 else 1282 m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm)); 1283 } 1284 sub(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1285 void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 1286 { 1287 // Rd can only be SP if Rn is also SP. 1288 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1289 ASSERT(rd != ARMRegisters::pc); 1290 ASSERT(rn != ARMRegisters::pc); 1291 ASSERT(imm.isValid()); 1292 1293 if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { 1294 m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2); 1295 return; 1296 } else if (!((rd | rn) & 8)) { 1297 if (imm.isUInt3()) { 1298 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 1299 return; 1300 } else if ((rd == rn) && imm.isUInt8()) { 1301 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_imm_T2, rd, imm.getUInt8()); 1302 return; 1303 } 1304 } 1305 1306 if (imm.isEncodedImm()) 1307 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T3, rn, rd, imm); 1308 else { 1309 ASSERT(imm.isUInt12()); 1310 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_imm_T4, rn, rd, imm); 1311 } 1312 } 1313 sub(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1314 void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1315 { 1316 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1317 ASSERT(rd != ARMRegisters::pc); 1318 ASSERT(rn != ARMRegisters::pc); 1319 ASSERT(!BadReg(rm)); 1320 m_formatter.twoWordOp12Reg4FourFours(OP_SUB_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1321 } 1322 1323 // NOTE: In an IT block, add doesn't modify the flags register. sub(RegisterID rd,RegisterID rn,RegisterID rm)1324 void sub(RegisterID rd, RegisterID rn, RegisterID rm) 1325 { 1326 if (!((rd | rn | rm) & 8)) 1327 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd); 1328 else 1329 sub(rd, rn, rm, ShiftTypeAndAmount()); 1330 } 1331 1332 // Not allowed in an IT (if then) block. sub_S(RegisterID rd,RegisterID rn,ARMThumbImmediate imm)1333 void sub_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm) 1334 { 1335 // Rd can only be SP if Rn is also SP. 1336 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1337 ASSERT(rd != ARMRegisters::pc); 1338 ASSERT(rn != ARMRegisters::pc); 1339 ASSERT(imm.isValid()); 1340 1341 if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { 1342 m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2); 1343 return; 1344 } else if (!((rd | rn) & 8)) { 1345 if (imm.isUInt3()) { 1346 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_imm_T1, (RegisterID)imm.getUInt3(), rn, rd); 1347 return; 1348 } else if ((rd == rn) && imm.isUInt8()) { 1349 m_formatter.oneWordOp5Reg3Imm8(OP_SUB_S_imm_T2, rd, imm.getUInt8()); 1350 return; 1351 } 1352 } 1353 1354 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_SUB_S_imm_T3, rn, rd, imm); 1355 } 1356 1357 // Not allowed in an IT (if then) block? sub_S(RegisterID rd,RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1358 void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1359 { 1360 ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp)); 1361 ASSERT(rd != ARMRegisters::pc); 1362 ASSERT(rn != ARMRegisters::pc); 1363 ASSERT(!BadReg(rm)); 1364 m_formatter.twoWordOp12Reg4FourFours(OP_SUB_S_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm)); 1365 } 1366 1367 // Not allowed in an IT (if then) block. sub_S(RegisterID rd,RegisterID rn,RegisterID rm)1368 void sub_S(RegisterID rd, RegisterID rn, RegisterID rm) 1369 { 1370 if (!((rd | rn | rm) & 8)) 1371 m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_S_reg_T1, rm, rn, rd); 1372 else 1373 sub_S(rd, rn, rm, ShiftTypeAndAmount()); 1374 } 1375 tst(RegisterID rn,ARMThumbImmediate imm)1376 void tst(RegisterID rn, ARMThumbImmediate imm) 1377 { 1378 ASSERT(!BadReg(rn)); 1379 ASSERT(imm.isEncodedImm()); 1380 1381 m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm); 1382 } 1383 tst(RegisterID rn,RegisterID rm,ShiftTypeAndAmount shift)1384 void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift) 1385 { 1386 ASSERT(!BadReg(rn)); 1387 ASSERT(!BadReg(rm)); 1388 m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm)); 1389 } 1390 tst(RegisterID rn,RegisterID rm)1391 void tst(RegisterID rn, RegisterID rm) 1392 { 1393 if ((rn | rm) & 8) 1394 tst(rn, rm, ShiftTypeAndAmount()); 1395 else 1396 m_formatter.oneWordOp10Reg3Reg3(OP_TST_reg_T1, rm, rn); 1397 } 1398 vadd_F64(FPRegisterID rd,FPRegisterID rn,FPRegisterID rm)1399 void vadd_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm) 1400 { 1401 m_formatter.vfpOp(0x0b00ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16)); 1402 } 1403 vcmp_F64(FPRegisterID rd,FPRegisterID rm)1404 void vcmp_F64(FPRegisterID rd, FPRegisterID rm) 1405 { 1406 m_formatter.vfpOp(0x0bc0eeb4 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rm, 21, 16)); 1407 } 1408 vcvt_F64_S32(FPRegisterID fd,FPRegisterID sm)1409 void vcvt_F64_S32(FPRegisterID fd, FPRegisterID sm) 1410 { 1411 m_formatter.vfpOp(0x0bc0eeb8 | doubleRegisterMask(fd, 6, 28) | singleRegisterMask(sm, 16, 21)); 1412 } 1413 vcvt_S32_F64(FPRegisterID sd,FPRegisterID fm)1414 void vcvt_S32_F64(FPRegisterID sd, FPRegisterID fm) 1415 { 1416 m_formatter.vfpOp(0x0bc0eebd | singleRegisterMask(sd, 28, 6) | doubleRegisterMask(fm, 21, 16)); 1417 } 1418 vldr(FPRegisterID rd,RegisterID rn,int32_t imm)1419 void vldr(FPRegisterID rd, RegisterID rn, int32_t imm) 1420 { 1421 vmem(rd, rn, imm, true); 1422 } 1423 vmov(RegisterID rd,FPRegisterID sn)1424 void vmov(RegisterID rd, FPRegisterID sn) 1425 { 1426 m_formatter.vfpOp(0x0a10ee10 | (rd << 28) | singleRegisterMask(sn, 0, 23)); 1427 } 1428 vmov(FPRegisterID sn,RegisterID rd)1429 void vmov(FPRegisterID sn, RegisterID rd) 1430 { 1431 m_formatter.vfpOp(0x0a10ee00 | (rd << 28) | singleRegisterMask(sn, 0, 23)); 1432 } 1433 1434 // move FPSCR flags to APSR. vmrs_APSR_nzcv_FPSCR()1435 void vmrs_APSR_nzcv_FPSCR() 1436 { 1437 m_formatter.vfpOp(0xfa10eef1); 1438 } 1439 vmul_F64(FPRegisterID rd,FPRegisterID rn,FPRegisterID rm)1440 void vmul_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm) 1441 { 1442 m_formatter.vfpOp(0x0b00ee20 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16)); 1443 } 1444 vstr(FPRegisterID rd,RegisterID rn,int32_t imm)1445 void vstr(FPRegisterID rd, RegisterID rn, int32_t imm) 1446 { 1447 vmem(rd, rn, imm, false); 1448 } 1449 vsub_F64(FPRegisterID rd,FPRegisterID rn,FPRegisterID rm)1450 void vsub_F64(FPRegisterID rd, FPRegisterID rn, FPRegisterID rm) 1451 { 1452 m_formatter.vfpOp(0x0b40ee30 | doubleRegisterMask(rd, 6, 28) | doubleRegisterMask(rn, 23, 0) | doubleRegisterMask(rm, 21, 16)); 1453 } 1454 1455 label()1456 JmpDst label() 1457 { 1458 return JmpDst(m_formatter.size()); 1459 } 1460 align(int alignment)1461 JmpDst align(int alignment) 1462 { 1463 while (!m_formatter.isAligned(alignment)) 1464 bkpt(); 1465 1466 return label(); 1467 } 1468 getRelocatedAddress(void * code,JmpSrc jump)1469 static void* getRelocatedAddress(void* code, JmpSrc jump) 1470 { 1471 ASSERT(jump.m_offset != -1); 1472 1473 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset); 1474 } 1475 getRelocatedAddress(void * code,JmpDst destination)1476 static void* getRelocatedAddress(void* code, JmpDst destination) 1477 { 1478 ASSERT(destination.m_offset != -1); 1479 1480 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset); 1481 } 1482 getDifferenceBetweenLabels(JmpDst src,JmpDst dst)1483 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst) 1484 { 1485 return dst.m_offset - src.m_offset; 1486 } 1487 getDifferenceBetweenLabels(JmpDst src,JmpSrc dst)1488 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst) 1489 { 1490 return dst.m_offset - src.m_offset; 1491 } 1492 getDifferenceBetweenLabels(JmpSrc src,JmpDst dst)1493 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst) 1494 { 1495 return dst.m_offset - src.m_offset; 1496 } 1497 1498 // Assembler admin methods: 1499 size()1500 size_t size() const 1501 { 1502 return m_formatter.size(); 1503 } 1504 executableCopy(ExecutablePool * allocator)1505 void* executableCopy(ExecutablePool* allocator) 1506 { 1507 void* copy = m_formatter.executableCopy(allocator); 1508 1509 unsigned jumpCount = m_jumpsToLink.size(); 1510 for (unsigned i = 0; i < jumpCount; ++i) { 1511 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from); 1512 uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to); 1513 linkJumpAbsolute(location, target); 1514 } 1515 m_jumpsToLink.clear(); 1516 1517 ASSERT(copy); 1518 return copy; 1519 } 1520 getCallReturnOffset(JmpSrc call)1521 static unsigned getCallReturnOffset(JmpSrc call) 1522 { 1523 ASSERT(call.m_offset >= 0); 1524 return call.m_offset; 1525 } 1526 1527 // Linking & patching: 1528 // 1529 // 'link' and 'patch' methods are for use on unprotected code - such as the code 1530 // within the AssemblerBuffer, and code being patched by the patch buffer. Once 1531 // code has been finalized it is (platform support permitting) within a non- 1532 // writable region of memory; to modify the code in an execute-only execuable 1533 // pool the 'repatch' and 'relink' methods should be used. 1534 linkJump(JmpSrc from,JmpDst to)1535 void linkJump(JmpSrc from, JmpDst to) 1536 { 1537 ASSERT(to.m_offset != -1); 1538 ASSERT(from.m_offset != -1); 1539 m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset)); 1540 } 1541 linkJump(void * code,JmpSrc from,void * to)1542 static void linkJump(void* code, JmpSrc from, void* to) 1543 { 1544 ASSERT(from.m_offset != -1); 1545 1546 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset); 1547 linkJumpAbsolute(location, to); 1548 } 1549 1550 // bah, this mathod should really be static, since it is used by the LinkBuffer. 1551 // return a bool saying whether the link was successful? linkCall(void * code,JmpSrc from,void * to)1552 static void linkCall(void* code, JmpSrc from, void* to) 1553 { 1554 ASSERT(!(reinterpret_cast<intptr_t>(code) & 1)); 1555 ASSERT(from.m_offset != -1); 1556 ASSERT(reinterpret_cast<intptr_t>(to) & 1); 1557 1558 setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to); 1559 } 1560 linkPointer(void * code,JmpDst where,void * value)1561 static void linkPointer(void* code, JmpDst where, void* value) 1562 { 1563 setPointer(reinterpret_cast<char*>(code) + where.m_offset, value); 1564 } 1565 relinkJump(void * from,void * to)1566 static void relinkJump(void* from, void* to) 1567 { 1568 ASSERT(!(reinterpret_cast<intptr_t>(from) & 1)); 1569 ASSERT(!(reinterpret_cast<intptr_t>(to) & 1)); 1570 1571 linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to); 1572 1573 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t)); 1574 } 1575 relinkCall(void * from,void * to)1576 static void relinkCall(void* from, void* to) 1577 { 1578 ASSERT(!(reinterpret_cast<intptr_t>(from) & 1)); 1579 ASSERT(reinterpret_cast<intptr_t>(to) & 1); 1580 1581 setPointer(reinterpret_cast<uint16_t*>(from) - 1, to); 1582 1583 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 4 * sizeof(uint16_t)); 1584 } 1585 repatchInt32(void * where,int32_t value)1586 static void repatchInt32(void* where, int32_t value) 1587 { 1588 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); 1589 1590 setInt32(where, value); 1591 1592 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t)); 1593 } 1594 repatchPointer(void * where,void * value)1595 static void repatchPointer(void* where, void* value) 1596 { 1597 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); 1598 1599 setPointer(where, value); 1600 1601 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(where) - 4, 4 * sizeof(uint16_t)); 1602 } 1603 repatchLoadPtrToLEA(void * where)1604 static void repatchLoadPtrToLEA(void* where) 1605 { 1606 ASSERT(!(reinterpret_cast<intptr_t>(where) & 1)); 1607 1608 uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4; 1609 ASSERT((*loadOp & 0xfff0) == OP_LDR_reg_T2); 1610 1611 *loadOp = OP_ADD_reg_T3 | (*loadOp & 0xf); 1612 ExecutableAllocator::cacheFlush(loadOp, sizeof(uint16_t)); 1613 } 1614 1615 private: 1616 1617 // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. 1618 // (i.e. +/-(0..255) 32-bit words) vmem(FPRegisterID rd,RegisterID rn,int32_t imm,bool isLoad)1619 void vmem(FPRegisterID rd, RegisterID rn, int32_t imm, bool isLoad) 1620 { 1621 bool up; 1622 uint32_t offset; 1623 if (imm < 0) { 1624 offset = -imm; 1625 up = false; 1626 } else { 1627 offset = imm; 1628 up = true; 1629 } 1630 1631 // offset is effectively leftshifted by 2 already (the bottom two bits are zero, and not 1632 // reperesented in the instruction. Left shift by 14, to mov it into position 0x00AA0000. 1633 ASSERT((offset & ~(0xff << 2)) == 0); 1634 offset <<= 14; 1635 1636 m_formatter.vfpOp(0x0b00ed00 | offset | (up << 7) | (isLoad << 4) | doubleRegisterMask(rd, 6, 28) | rn); 1637 } 1638 setInt32(void * code,uint32_t value)1639 static void setInt32(void* code, uint32_t value) 1640 { 1641 uint16_t* location = reinterpret_cast<uint16_t*>(code); 1642 ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2)); 1643 1644 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value)); 1645 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16)); 1646 location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 1647 location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16); 1648 location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 1649 location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); 1650 1651 ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t)); 1652 } 1653 setPointer(void * code,void * value)1654 static void setPointer(void* code, void* value) 1655 { 1656 setInt32(code, reinterpret_cast<uint32_t>(value)); 1657 } 1658 isB(void * address)1659 static bool isB(void* address) 1660 { 1661 uint16_t* instruction = static_cast<uint16_t*>(address); 1662 return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b); 1663 } 1664 isBX(void * address)1665 static bool isBX(void* address) 1666 { 1667 uint16_t* instruction = static_cast<uint16_t*>(address); 1668 return (instruction[0] & 0xff87) == OP_BX; 1669 } 1670 isMOV_imm_T3(void * address)1671 static bool isMOV_imm_T3(void* address) 1672 { 1673 uint16_t* instruction = static_cast<uint16_t*>(address); 1674 return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0); 1675 } 1676 isMOVT(void * address)1677 static bool isMOVT(void* address) 1678 { 1679 uint16_t* instruction = static_cast<uint16_t*>(address); 1680 return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0); 1681 } 1682 isNOP_T1(void * address)1683 static bool isNOP_T1(void* address) 1684 { 1685 uint16_t* instruction = static_cast<uint16_t*>(address); 1686 return instruction[0] == OP_NOP_T1; 1687 } 1688 isNOP_T2(void * address)1689 static bool isNOP_T2(void* address) 1690 { 1691 uint16_t* instruction = static_cast<uint16_t*>(address); 1692 return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b); 1693 } 1694 linkJumpAbsolute(uint16_t * instruction,void * target)1695 static void linkJumpAbsolute(uint16_t* instruction, void* target) 1696 { 1697 // FIMXE: this should be up in the MacroAssembler layer. :-( 1698 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; 1699 1700 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1701 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 1702 1703 ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) 1704 || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) ); 1705 1706 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 1707 if (((relative << 7) >> 7) == relative) { 1708 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 1709 if (relative >= 0) 1710 relative ^= 0xC00000; 1711 1712 // All branch offsets should be an even distance. 1713 ASSERT(!(relative & 1)); 1714 // There may be a better way to fix this, but right now put the NOPs first, since in the 1715 // case of an conditional branch this will be coming after an ITTT predicating *three* 1716 // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to 1717 // variable wdith encoding - the previous instruction might *look* like an ITTT but 1718 // actually be the second half of a 2-word op. 1719 instruction[-5] = OP_NOP_T1; 1720 instruction[-4] = OP_NOP_T2a; 1721 instruction[-3] = OP_NOP_T2b; 1722 instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 1723 instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 1724 } else { 1725 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); 1726 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); 1727 instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 1728 instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); 1729 instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 1730 instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); 1731 instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); 1732 } 1733 } 1734 twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op,ARMThumbImmediate imm)1735 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm) 1736 { 1737 return op | (imm.m_value.i << 10) | imm.m_value.imm4; 1738 } twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd,ARMThumbImmediate imm)1739 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm) 1740 { 1741 return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8; 1742 } 1743 1744 class ARMInstructionFormatter { 1745 public: oneWordOp5Reg3Imm8(OpcodeID op,RegisterID rd,uint8_t imm)1746 void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm) 1747 { 1748 m_buffer.putShort(op | (rd << 8) | imm); 1749 } 1750 oneWordOp5Imm5Reg3Reg3(OpcodeID op,uint8_t imm,RegisterID reg1,RegisterID reg2)1751 void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2) 1752 { 1753 m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2); 1754 } 1755 oneWordOp7Reg3Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2,RegisterID reg3)1756 void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3) 1757 { 1758 m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3); 1759 } 1760 oneWordOp8Imm8(OpcodeID op,uint8_t imm)1761 void oneWordOp8Imm8(OpcodeID op, uint8_t imm) 1762 { 1763 m_buffer.putShort(op | imm); 1764 } 1765 oneWordOp8RegReg143(OpcodeID op,RegisterID reg1,RegisterID reg2)1766 void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2) 1767 { 1768 m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7)); 1769 } oneWordOp9Imm7(OpcodeID op,uint8_t imm)1770 void oneWordOp9Imm7(OpcodeID op, uint8_t imm) 1771 { 1772 m_buffer.putShort(op | imm); 1773 } 1774 oneWordOp10Reg3Reg3(OpcodeID op,RegisterID reg1,RegisterID reg2)1775 void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2) 1776 { 1777 m_buffer.putShort(op | (reg1 << 3) | reg2); 1778 } 1779 twoWordOp12Reg4FourFours(OpcodeID1 op,RegisterID reg,FourFours ff)1780 void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff) 1781 { 1782 m_buffer.putShort(op | reg); 1783 m_buffer.putShort(ff.m_u.value); 1784 } 1785 twoWordOp16FourFours(OpcodeID1 op,FourFours ff)1786 void twoWordOp16FourFours(OpcodeID1 op, FourFours ff) 1787 { 1788 m_buffer.putShort(op); 1789 m_buffer.putShort(ff.m_u.value); 1790 } 1791 twoWordOp16Op16(OpcodeID1 op1,OpcodeID2 op2)1792 void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2) 1793 { 1794 m_buffer.putShort(op1); 1795 m_buffer.putShort(op2); 1796 } 1797 twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op,int imm4,RegisterID rd,ARMThumbImmediate imm)1798 void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm) 1799 { 1800 ARMThumbImmediate newImm = imm; 1801 newImm.m_value.imm4 = imm4; 1802 1803 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm)); 1804 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm)); 1805 } 1806 twoWordOp12Reg4Reg4Imm12(OpcodeID1 op,RegisterID reg1,RegisterID reg2,uint16_t imm)1807 void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm) 1808 { 1809 m_buffer.putShort(op | reg1); 1810 m_buffer.putShort((reg2 << 12) | imm); 1811 } 1812 vfpOp(int32_t op)1813 void vfpOp(int32_t op) 1814 { 1815 m_buffer.putInt(op); 1816 } 1817 1818 1819 // Administrative methods: 1820 size()1821 size_t size() const { return m_buffer.size(); } isAligned(int alignment)1822 bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } data()1823 void* data() const { return m_buffer.data(); } executableCopy(ExecutablePool * allocator)1824 void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); } 1825 1826 private: 1827 AssemblerBuffer m_buffer; 1828 } m_formatter; 1829 1830 Vector<LinkRecord> m_jumpsToLink; 1831 }; 1832 1833 } // namespace JSC 1834 1835 #endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) 1836 1837 #endif // ARMAssembler_h 1838