1 /* 2 * Copyright (C) 2009, 2010 University of Szeged 3 * All rights reserved. 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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_TRADITIONAL) 31 32 #include "AssemblerBufferWithConstantPool.h" 33 #include <wtf/Assertions.h> 34 namespace JSC { 35 36 typedef uint32_t ARMWord; 37 38 namespace ARMRegisters { 39 typedef enum { 40 r0 = 0, 41 r1, 42 r2, 43 r3, S0 = r3, 44 r4, 45 r5, 46 r6, 47 r7, 48 r8, S1 = r8, 49 r9, 50 r10, 51 r11, 52 r12, 53 r13, sp = r13, 54 r14, lr = r14, 55 r15, pc = r15 56 } RegisterID; 57 58 typedef enum { 59 d0, 60 d1, 61 d2, 62 d3, SD0 = d3, 63 d4, 64 d5, 65 d6, 66 d7, 67 d8, 68 d9, 69 d10, 70 d11, 71 d12, 72 d13, 73 d14, 74 d15, 75 d16, 76 d17, 77 d18, 78 d19, 79 d20, 80 d21, 81 d22, 82 d23, 83 d24, 84 d25, 85 d26, 86 d27, 87 d28, 88 d29, 89 d30, 90 d31 91 } FPRegisterID; 92 93 } // namespace ARMRegisters 94 95 class ARMAssembler { 96 public: 97 typedef ARMRegisters::RegisterID RegisterID; 98 typedef ARMRegisters::FPRegisterID FPRegisterID; 99 typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer; 100 typedef SegmentedVector<int, 64> Jumps; 101 ARMAssembler()102 ARMAssembler() { } 103 104 // ARM conditional constants 105 typedef enum { 106 EQ = 0x00000000, // Zero 107 NE = 0x10000000, // Non-zero 108 CS = 0x20000000, 109 CC = 0x30000000, 110 MI = 0x40000000, 111 PL = 0x50000000, 112 VS = 0x60000000, 113 VC = 0x70000000, 114 HI = 0x80000000, 115 LS = 0x90000000, 116 GE = 0xa0000000, 117 LT = 0xb0000000, 118 GT = 0xc0000000, 119 LE = 0xd0000000, 120 AL = 0xe0000000 121 } Condition; 122 123 // ARM instruction constants 124 enum { 125 AND = (0x0 << 21), 126 EOR = (0x1 << 21), 127 SUB = (0x2 << 21), 128 RSB = (0x3 << 21), 129 ADD = (0x4 << 21), 130 ADC = (0x5 << 21), 131 SBC = (0x6 << 21), 132 RSC = (0x7 << 21), 133 TST = (0x8 << 21), 134 TEQ = (0x9 << 21), 135 CMP = (0xa << 21), 136 CMN = (0xb << 21), 137 ORR = (0xc << 21), 138 MOV = (0xd << 21), 139 BIC = (0xe << 21), 140 MVN = (0xf << 21), 141 MUL = 0x00000090, 142 MULL = 0x00c00090, 143 VADD_F64 = 0x0e300b00, 144 VDIV_F64 = 0x0e800b00, 145 VSUB_F64 = 0x0e300b40, 146 VMUL_F64 = 0x0e200b00, 147 VCMP_F64 = 0x0eb40b40, 148 VSQRT_F64 = 0x0eb10bc0, 149 DTR = 0x05000000, 150 LDRH = 0x00100090, 151 STRH = 0x00000090, 152 STMDB = 0x09200000, 153 LDMIA = 0x08b00000, 154 FDTR = 0x0d000b00, 155 B = 0x0a000000, 156 BL = 0x0b000000, 157 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__) 158 BX = 0x012fff10, 159 #endif 160 VMOV_VFP = 0x0e000a10, 161 VMOV_ARM = 0x0e100a10, 162 VCVT_F64_S32 = 0x0eb80bc0, 163 VCVT_S32_F64 = 0x0ebd0b40, 164 VCVTR_S32_F64 = 0x0ebd0bc0, 165 VMRS_APSR = 0x0ef1fa10, 166 #if WTF_ARM_ARCH_AT_LEAST(5) 167 CLZ = 0x016f0f10, 168 BKPT = 0xe1200070, 169 BLX = 0x012fff30, 170 #endif 171 #if WTF_ARM_ARCH_AT_LEAST(7) 172 MOVW = 0x03000000, 173 MOVT = 0x03400000, 174 #endif 175 }; 176 177 enum { 178 OP2_IMM = (1 << 25), 179 OP2_IMMh = (1 << 22), 180 OP2_INV_IMM = (1 << 26), 181 SET_CC = (1 << 20), 182 OP2_OFSREG = (1 << 25), 183 DT_UP = (1 << 23), 184 DT_BYTE = (1 << 22), 185 DT_WB = (1 << 21), 186 // This flag is inlcuded in LDR and STR 187 DT_PRE = (1 << 24), 188 HDT_UH = (1 << 5), 189 DT_LOAD = (1 << 20), 190 }; 191 192 // Masks of ARM instructions 193 enum { 194 BRANCH_MASK = 0x00ffffff, 195 NONARM = 0xf0000000, 196 SDT_MASK = 0x0c000000, 197 SDT_OFFSET_MASK = 0xfff, 198 }; 199 200 enum { 201 BOFFSET_MIN = -0x00800000, 202 BOFFSET_MAX = 0x007fffff, 203 SDT = 0x04000000, 204 }; 205 206 enum { 207 padForAlign8 = 0x00, 208 padForAlign16 = 0x0000, 209 padForAlign32 = 0xe12fff7f // 'bkpt 0xffff' instruction. 210 }; 211 212 static const ARMWord INVALID_IMM = 0xf0000000; 213 static const ARMWord InvalidBranchTarget = 0xffffffff; 214 static const int DefaultPrefetching = 2; 215 216 class JmpSrc { 217 friend class ARMAssembler; 218 public: JmpSrc()219 JmpSrc() 220 : m_offset(-1) 221 { 222 } 223 224 private: JmpSrc(int offset)225 JmpSrc(int offset) 226 : m_offset(offset) 227 { 228 } 229 230 int m_offset; 231 }; 232 233 class JmpDst { 234 friend class ARMAssembler; 235 public: JmpDst()236 JmpDst() 237 : m_offset(-1) 238 , m_used(false) 239 { 240 } 241 isUsed()242 bool isUsed() const { return m_used; } isSet()243 bool isSet() const { return (m_offset != -1); } used()244 void used() { m_used = true; } 245 private: JmpDst(int offset)246 JmpDst(int offset) 247 : m_offset(offset) 248 , m_used(false) 249 { 250 ASSERT(m_offset == offset); 251 } 252 253 signed int m_offset : 31; 254 int m_used : 1; 255 }; 256 257 // Instruction formating 258 emitInst(ARMWord op,int rd,int rn,ARMWord op2)259 void emitInst(ARMWord op, int rd, int rn, ARMWord op2) 260 { 261 ASSERT(((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff))); 262 m_buffer.putInt(op | RN(rn) | RD(rd) | op2); 263 } 264 emitDoublePrecisionInst(ARMWord op,int dd,int dn,int dm)265 void emitDoublePrecisionInst(ARMWord op, int dd, int dn, int dm) 266 { 267 ASSERT((dd >= 0 && dd <= 31) && (dn >= 0 && dn <= 31) && (dm >= 0 && dm <= 31)); 268 m_buffer.putInt(op | ((dd & 0xf) << 12) | ((dd & 0x10) << (22 - 4)) 269 | ((dn & 0xf) << 16) | ((dn & 0x10) << (7 - 4)) 270 | (dm & 0xf) | ((dm & 0x10) << (5 - 4))); 271 } 272 emitSinglePrecisionInst(ARMWord op,int sd,int sn,int sm)273 void emitSinglePrecisionInst(ARMWord op, int sd, int sn, int sm) 274 { 275 ASSERT((sd >= 0 && sd <= 31) && (sn >= 0 && sn <= 31) && (sm >= 0 && sm <= 31)); 276 m_buffer.putInt(op | ((sd >> 1) << 12) | ((sd & 0x1) << 22) 277 | ((sn >> 1) << 16) | ((sn & 0x1) << 7) 278 | (sm >> 1) | ((sm & 0x1) << 5)); 279 } 280 281 void and_r(int rd, int rn, ARMWord op2, Condition cc = AL) 282 { 283 emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2); 284 } 285 286 void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL) 287 { 288 emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2); 289 } 290 291 void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL) 292 { 293 emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2); 294 } 295 296 void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL) 297 { 298 emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2); 299 } 300 301 void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL) 302 { 303 emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2); 304 } 305 306 void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 307 { 308 emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2); 309 } 310 311 void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL) 312 { 313 emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2); 314 } 315 316 void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 317 { 318 emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2); 319 } 320 321 void add_r(int rd, int rn, ARMWord op2, Condition cc = AL) 322 { 323 emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2); 324 } 325 326 void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL) 327 { 328 emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2); 329 } 330 331 void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 332 { 333 emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2); 334 } 335 336 void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 337 { 338 emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2); 339 } 340 341 void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 342 { 343 emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2); 344 } 345 346 void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 347 { 348 emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2); 349 } 350 351 void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 352 { 353 emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2); 354 } 355 356 void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 357 { 358 emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2); 359 } 360 361 void tst_r(int rn, ARMWord op2, Condition cc = AL) 362 { 363 emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2); 364 } 365 366 void teq_r(int rn, ARMWord op2, Condition cc = AL) 367 { 368 emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2); 369 } 370 371 void cmp_r(int rn, ARMWord op2, Condition cc = AL) 372 { 373 emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2); 374 } 375 376 void cmn_r(int rn, ARMWord op2, Condition cc = AL) 377 { 378 emitInst(static_cast<ARMWord>(cc) | CMN | SET_CC, 0, rn, op2); 379 } 380 381 void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL) 382 { 383 emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2); 384 } 385 386 void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 387 { 388 emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2); 389 } 390 391 void mov_r(int rd, ARMWord op2, Condition cc = AL) 392 { 393 emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARMRegisters::r0, op2); 394 } 395 396 #if WTF_ARM_ARCH_AT_LEAST(7) 397 void movw_r(int rd, ARMWord op2, Condition cc = AL) 398 { 399 ASSERT((op2 | 0xf0fff) == 0xf0fff); 400 m_buffer.putInt(static_cast<ARMWord>(cc) | MOVW | RD(rd) | op2); 401 } 402 403 void movt_r(int rd, ARMWord op2, Condition cc = AL) 404 { 405 ASSERT((op2 | 0xf0fff) == 0xf0fff); 406 m_buffer.putInt(static_cast<ARMWord>(cc) | MOVT | RD(rd) | op2); 407 } 408 #endif 409 410 void movs_r(int rd, ARMWord op2, Condition cc = AL) 411 { 412 emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARMRegisters::r0, op2); 413 } 414 415 void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL) 416 { 417 emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2); 418 } 419 420 void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL) 421 { 422 emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2); 423 } 424 425 void mvn_r(int rd, ARMWord op2, Condition cc = AL) 426 { 427 emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARMRegisters::r0, op2); 428 } 429 430 void mvns_r(int rd, ARMWord op2, Condition cc = AL) 431 { 432 emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARMRegisters::r0, op2); 433 } 434 435 void mul_r(int rd, int rn, int rm, Condition cc = AL) 436 { 437 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm)); 438 } 439 440 void muls_r(int rd, int rn, int rm, Condition cc = AL) 441 { 442 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm)); 443 } 444 445 void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL) 446 { 447 m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm)); 448 } 449 450 void vadd_f64_r(int dd, int dn, int dm, Condition cc = AL) 451 { 452 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VADD_F64, dd, dn, dm); 453 } 454 455 void vdiv_f64_r(int dd, int dn, int dm, Condition cc = AL) 456 { 457 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VDIV_F64, dd, dn, dm); 458 } 459 460 void vsub_f64_r(int dd, int dn, int dm, Condition cc = AL) 461 { 462 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSUB_F64, dd, dn, dm); 463 } 464 465 void vmul_f64_r(int dd, int dn, int dm, Condition cc = AL) 466 { 467 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VMUL_F64, dd, dn, dm); 468 } 469 470 void vcmp_f64_r(int dd, int dm, Condition cc = AL) 471 { 472 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCMP_F64, dd, 0, dm); 473 } 474 475 void vsqrt_f64_r(int dd, int dm, Condition cc = AL) 476 { 477 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSQRT_F64, dd, 0, dm); 478 } 479 480 void ldr_imm(int rd, ARMWord imm, Condition cc = AL) 481 { 482 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm, true); 483 } 484 485 void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL) 486 { 487 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm); 488 } 489 490 void dtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 491 { 492 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP, rd, rb, op2); 493 } 494 495 void dtr_ur(bool isLoad, int rd, int rb, int rm, Condition cc = AL) 496 { 497 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP | OP2_OFSREG, rd, rb, rm); 498 } 499 500 void dtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 501 { 502 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0), rd, rb, op2); 503 } 504 505 void dtr_dr(bool isLoad, int rd, int rb, int rm, Condition cc = AL) 506 { 507 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | OP2_OFSREG, rd, rb, rm); 508 } 509 510 void ldrh_r(int rd, int rn, int rm, Condition cc = AL) 511 { 512 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm); 513 } 514 515 void ldrh_d(int rd, int rb, ARMWord op2, Condition cc = AL) 516 { 517 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_PRE, rd, rb, op2); 518 } 519 520 void ldrh_u(int rd, int rb, ARMWord op2, Condition cc = AL) 521 { 522 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rb, op2); 523 } 524 525 void strh_r(int rn, int rm, int rd, Condition cc = AL) 526 { 527 emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm); 528 } 529 530 void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 531 { 532 ASSERT(op2 <= 0xff); 533 emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2); 534 } 535 536 void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 537 { 538 ASSERT(op2 <= 0xff); 539 emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2); 540 } 541 542 void push_r(int reg, Condition cc = AL) 543 { 544 ASSERT(ARMWord(reg) <= 0xf); 545 m_buffer.putInt(cc | DTR | DT_WB | RN(ARMRegisters::sp) | RD(reg) | 0x4); 546 } 547 548 void pop_r(int reg, Condition cc = AL) 549 { 550 ASSERT(ARMWord(reg) <= 0xf); 551 m_buffer.putInt(cc | (DTR ^ DT_PRE) | DT_LOAD | DT_UP | RN(ARMRegisters::sp) | RD(reg) | 0x4); 552 } 553 554 inline void poke_r(int reg, Condition cc = AL) 555 { 556 dtr_d(false, ARMRegisters::sp, 0, reg, cc); 557 } 558 559 inline void peek_r(int reg, Condition cc = AL) 560 { 561 dtr_u(true, reg, ARMRegisters::sp, 0, cc); 562 } 563 564 void vmov_vfp_r(int sn, int rt, Condition cc = AL) 565 { 566 ASSERT(rt <= 15); 567 emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_VFP, rt << 1, sn, 0); 568 } 569 570 void vmov_arm_r(int rt, int sn, Condition cc = AL) 571 { 572 ASSERT(rt <= 15); 573 emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_ARM, rt << 1, sn, 0); 574 } 575 576 void vcvt_f64_s32_r(int dd, int sm, Condition cc = AL) 577 { 578 ASSERT(!(sm & 0x1)); // sm must be divisible by 2 579 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_F64_S32, dd, 0, (sm >> 1)); 580 } 581 582 void vcvt_s32_f64_r(int sd, int dm, Condition cc = AL) 583 { 584 ASSERT(!(sd & 0x1)); // sd must be divisible by 2 585 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_S32_F64, (sd >> 1), 0, dm); 586 } 587 588 void vcvtr_s32_f64_r(int sd, int dm, Condition cc = AL) 589 { 590 ASSERT(!(sd & 0x1)); // sd must be divisible by 2 591 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVTR_S32_F64, (sd >> 1), 0, dm); 592 } 593 594 void vmrs_apsr(Condition cc = AL) 595 { 596 m_buffer.putInt(static_cast<ARMWord>(cc) | VMRS_APSR); 597 } 598 599 #if WTF_ARM_ARCH_AT_LEAST(5) 600 void clz_r(int rd, int rm, Condition cc = AL) 601 { 602 m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm)); 603 } 604 #endif 605 bkpt(ARMWord value)606 void bkpt(ARMWord value) 607 { 608 #if WTF_ARM_ARCH_AT_LEAST(5) 609 m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf)); 610 #else 611 // Cannot access to Zero memory address 612 dtr_dr(true, ARMRegisters::S0, ARMRegisters::S0, ARMRegisters::S0); 613 #endif 614 } 615 616 void bx(int rm, Condition cc = AL) 617 { 618 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__) 619 emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm)); 620 #else 621 mov_r(ARMRegisters::pc, RM(rm), cc); 622 #endif 623 } 624 625 JmpSrc blx(int rm, Condition cc = AL) 626 { 627 #if WTF_ARM_ARCH_AT_LEAST(5) 628 emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm)); 629 #else 630 ASSERT(rm != 14); 631 ensureSpace(2 * sizeof(ARMWord), 0); 632 mov_r(ARMRegisters::lr, ARMRegisters::pc, cc); 633 bx(rm, cc); 634 #endif 635 return JmpSrc(m_buffer.uncheckedSize()); 636 } 637 lsl(int reg,ARMWord value)638 static ARMWord lsl(int reg, ARMWord value) 639 { 640 ASSERT(reg <= ARMRegisters::pc); 641 ASSERT(value <= 0x1f); 642 return reg | (value << 7) | 0x00; 643 } 644 lsr(int reg,ARMWord value)645 static ARMWord lsr(int reg, ARMWord value) 646 { 647 ASSERT(reg <= ARMRegisters::pc); 648 ASSERT(value <= 0x1f); 649 return reg | (value << 7) | 0x20; 650 } 651 asr(int reg,ARMWord value)652 static ARMWord asr(int reg, ARMWord value) 653 { 654 ASSERT(reg <= ARMRegisters::pc); 655 ASSERT(value <= 0x1f); 656 return reg | (value << 7) | 0x40; 657 } 658 lsl_r(int reg,int shiftReg)659 static ARMWord lsl_r(int reg, int shiftReg) 660 { 661 ASSERT(reg <= ARMRegisters::pc); 662 ASSERT(shiftReg <= ARMRegisters::pc); 663 return reg | (shiftReg << 8) | 0x10; 664 } 665 lsr_r(int reg,int shiftReg)666 static ARMWord lsr_r(int reg, int shiftReg) 667 { 668 ASSERT(reg <= ARMRegisters::pc); 669 ASSERT(shiftReg <= ARMRegisters::pc); 670 return reg | (shiftReg << 8) | 0x30; 671 } 672 asr_r(int reg,int shiftReg)673 static ARMWord asr_r(int reg, int shiftReg) 674 { 675 ASSERT(reg <= ARMRegisters::pc); 676 ASSERT(shiftReg <= ARMRegisters::pc); 677 return reg | (shiftReg << 8) | 0x50; 678 } 679 680 // General helpers 681 size()682 int size() 683 { 684 return m_buffer.size(); 685 } 686 ensureSpace(int insnSpace,int constSpace)687 void ensureSpace(int insnSpace, int constSpace) 688 { 689 m_buffer.ensureSpace(insnSpace, constSpace); 690 } 691 sizeOfConstantPool()692 int sizeOfConstantPool() 693 { 694 return m_buffer.sizeOfConstantPool(); 695 } 696 label()697 JmpDst label() 698 { 699 return JmpDst(m_buffer.size()); 700 } 701 align(int alignment)702 JmpDst align(int alignment) 703 { 704 while (!m_buffer.isAligned(alignment)) 705 mov_r(ARMRegisters::r0, ARMRegisters::r0); 706 707 return label(); 708 } 709 710 JmpSrc loadBranchTarget(int rd, Condition cc = AL, int useConstantPool = 0) 711 { 712 ensureSpace(sizeof(ARMWord), sizeof(ARMWord)); 713 m_jumps.append(m_buffer.uncheckedSize() | (useConstantPool & 0x1)); 714 ldr_un_imm(rd, InvalidBranchTarget, cc); 715 return JmpSrc(m_buffer.uncheckedSize()); 716 } 717 718 JmpSrc jmp(Condition cc = AL, int useConstantPool = 0) 719 { 720 return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool); 721 } 722 723 void* executableCopy(ExecutablePool* allocator); 724 725 #ifndef NDEBUG debugOffset()726 unsigned debugOffset() { return m_formatter.debugOffset(); } 727 #endif 728 729 // Patching helpers 730 getLdrImmAddress(ARMWord * insn)731 static ARMWord* getLdrImmAddress(ARMWord* insn) 732 { 733 #if WTF_ARM_ARCH_AT_LEAST(5) 734 // Check for call 735 if ((*insn & 0x0f7f0000) != 0x051f0000) { 736 // Must be BLX 737 ASSERT((*insn & 0x012fff30) == 0x012fff30); 738 insn--; 739 } 740 #endif 741 // Must be an ldr ..., [pc +/- imm] 742 ASSERT((*insn & 0x0f7f0000) == 0x051f0000); 743 744 ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetching * sizeof(ARMWord); 745 if (*insn & DT_UP) 746 return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK)); 747 return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK)); 748 } 749 getLdrImmAddressOnPool(ARMWord * insn,uint32_t * constPool)750 static ARMWord* getLdrImmAddressOnPool(ARMWord* insn, uint32_t* constPool) 751 { 752 // Must be an ldr ..., [pc +/- imm] 753 ASSERT((*insn & 0x0f7f0000) == 0x051f0000); 754 755 if (*insn & 0x1) 756 return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1)); 757 return getLdrImmAddress(insn); 758 } 759 patchPointerInternal(intptr_t from,void * to)760 static void patchPointerInternal(intptr_t from, void* to) 761 { 762 ARMWord* insn = reinterpret_cast<ARMWord*>(from); 763 ARMWord* addr = getLdrImmAddress(insn); 764 *addr = reinterpret_cast<ARMWord>(to); 765 } 766 patchConstantPoolLoad(ARMWord load,ARMWord value)767 static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value) 768 { 769 value = (value << 1) + 1; 770 ASSERT(!(value & ~0xfff)); 771 return (load & ~0xfff) | value; 772 } 773 774 static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr); 775 776 // Patch pointers 777 linkPointer(void * code,JmpDst from,void * to)778 static void linkPointer(void* code, JmpDst from, void* to) 779 { 780 patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to); 781 } 782 repatchInt32(void * from,int32_t to)783 static void repatchInt32(void* from, int32_t to) 784 { 785 patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to)); 786 } 787 repatchPointer(void * from,void * to)788 static void repatchPointer(void* from, void* to) 789 { 790 patchPointerInternal(reinterpret_cast<intptr_t>(from), to); 791 } 792 793 // Linkers 794 static intptr_t getAbsoluteJumpAddress(void* base, int offset = 0) 795 { 796 return reinterpret_cast<intptr_t>(base) + offset - sizeof(ARMWord); 797 } 798 linkJump(JmpSrc from,JmpDst to)799 void linkJump(JmpSrc from, JmpDst to) 800 { 801 ARMWord* insn = reinterpret_cast<ARMWord*>(getAbsoluteJumpAddress(m_buffer.data(), from.m_offset)); 802 ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress()); 803 *addr = static_cast<ARMWord>(to.m_offset); 804 } 805 linkJump(void * code,JmpSrc from,void * to)806 static void linkJump(void* code, JmpSrc from, void* to) 807 { 808 patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to); 809 } 810 relinkJump(void * from,void * to)811 static void relinkJump(void* from, void* to) 812 { 813 patchPointerInternal(getAbsoluteJumpAddress(from), to); 814 } 815 linkCall(void * code,JmpSrc from,void * to)816 static void linkCall(void* code, JmpSrc from, void* to) 817 { 818 patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to); 819 } 820 relinkCall(void * from,void * to)821 static void relinkCall(void* from, void* to) 822 { 823 patchPointerInternal(getAbsoluteJumpAddress(from), to); 824 } 825 826 // Address operations 827 getRelocatedAddress(void * code,JmpSrc jump)828 static void* getRelocatedAddress(void* code, JmpSrc jump) 829 { 830 return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + jump.m_offset); 831 } 832 getRelocatedAddress(void * code,JmpDst label)833 static void* getRelocatedAddress(void* code, JmpDst label) 834 { 835 return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset); 836 } 837 838 // Address differences 839 getDifferenceBetweenLabels(JmpDst from,JmpSrc to)840 static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to) 841 { 842 return to.m_offset - from.m_offset; 843 } 844 getDifferenceBetweenLabels(JmpDst from,JmpDst to)845 static int getDifferenceBetweenLabels(JmpDst from, JmpDst to) 846 { 847 return to.m_offset - from.m_offset; 848 } 849 getCallReturnOffset(JmpSrc call)850 static unsigned getCallReturnOffset(JmpSrc call) 851 { 852 return call.m_offset; 853 } 854 855 // Handle immediates 856 getOp2Byte(ARMWord imm)857 static ARMWord getOp2Byte(ARMWord imm) 858 { 859 ASSERT(imm <= 0xff); 860 return OP2_IMMh | (imm & 0x0f) | ((imm & 0xf0) << 4) ; 861 } 862 863 static ARMWord getOp2(ARMWord imm); 864 865 #if WTF_ARM_ARCH_AT_LEAST(7) getImm16Op2(ARMWord imm)866 static ARMWord getImm16Op2(ARMWord imm) 867 { 868 if (imm <= 0xffff) 869 return (imm & 0xf000) << 4 | (imm & 0xfff); 870 return INVALID_IMM; 871 } 872 #endif 873 ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false); 874 void moveImm(ARMWord imm, int dest); 875 ARMWord encodeComplexImm(ARMWord imm, int dest); 876 getOffsetForHalfwordDataTransfer(ARMWord imm,int tmpReg)877 ARMWord getOffsetForHalfwordDataTransfer(ARMWord imm, int tmpReg) 878 { 879 // Encode immediate data in the instruction if it is possible 880 if (imm <= 0xff) 881 return getOp2Byte(imm); 882 // Otherwise, store the data in a temporary register 883 return encodeComplexImm(imm, tmpReg); 884 } 885 886 // Memory load/store helpers 887 888 void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes = false); 889 void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset); 890 void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset); 891 892 // Constant pool hnadlers 893 placeConstantPoolBarrier(int offset)894 static ARMWord placeConstantPoolBarrier(int offset) 895 { 896 offset = (offset - sizeof(ARMWord)) >> 2; 897 ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN)); 898 return AL | B | (offset & BRANCH_MASK); 899 } 900 901 private: RM(int reg)902 ARMWord RM(int reg) 903 { 904 ASSERT(reg <= ARMRegisters::pc); 905 return reg; 906 } 907 RS(int reg)908 ARMWord RS(int reg) 909 { 910 ASSERT(reg <= ARMRegisters::pc); 911 return reg << 8; 912 } 913 RD(int reg)914 ARMWord RD(int reg) 915 { 916 ASSERT(reg <= ARMRegisters::pc); 917 return reg << 12; 918 } 919 RN(int reg)920 ARMWord RN(int reg) 921 { 922 ASSERT(reg <= ARMRegisters::pc); 923 return reg << 16; 924 } 925 getConditionalField(ARMWord i)926 static ARMWord getConditionalField(ARMWord i) 927 { 928 return i & 0xf0000000; 929 } 930 931 int genInt(int reg, ARMWord imm, bool positive); 932 933 ARMBuffer m_buffer; 934 Jumps m_jumps; 935 }; 936 937 } // namespace JSC 938 939 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) 940 941 #endif // ARMAssembler_h 942