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<AssemblerLabel, 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 // Instruction formating 217 emitInst(ARMWord op,int rd,int rn,ARMWord op2)218 void emitInst(ARMWord op, int rd, int rn, ARMWord op2) 219 { 220 ASSERT(((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff))); 221 m_buffer.putInt(op | RN(rn) | RD(rd) | op2); 222 } 223 emitDoublePrecisionInst(ARMWord op,int dd,int dn,int dm)224 void emitDoublePrecisionInst(ARMWord op, int dd, int dn, int dm) 225 { 226 ASSERT((dd >= 0 && dd <= 31) && (dn >= 0 && dn <= 31) && (dm >= 0 && dm <= 31)); 227 m_buffer.putInt(op | ((dd & 0xf) << 12) | ((dd & 0x10) << (22 - 4)) 228 | ((dn & 0xf) << 16) | ((dn & 0x10) << (7 - 4)) 229 | (dm & 0xf) | ((dm & 0x10) << (5 - 4))); 230 } 231 emitSinglePrecisionInst(ARMWord op,int sd,int sn,int sm)232 void emitSinglePrecisionInst(ARMWord op, int sd, int sn, int sm) 233 { 234 ASSERT((sd >= 0 && sd <= 31) && (sn >= 0 && sn <= 31) && (sm >= 0 && sm <= 31)); 235 m_buffer.putInt(op | ((sd >> 1) << 12) | ((sd & 0x1) << 22) 236 | ((sn >> 1) << 16) | ((sn & 0x1) << 7) 237 | (sm >> 1) | ((sm & 0x1) << 5)); 238 } 239 240 void and_r(int rd, int rn, ARMWord op2, Condition cc = AL) 241 { 242 emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2); 243 } 244 245 void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL) 246 { 247 emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2); 248 } 249 250 void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL) 251 { 252 emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2); 253 } 254 255 void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL) 256 { 257 emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2); 258 } 259 260 void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL) 261 { 262 emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2); 263 } 264 265 void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 266 { 267 emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2); 268 } 269 270 void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL) 271 { 272 emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2); 273 } 274 275 void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 276 { 277 emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2); 278 } 279 280 void add_r(int rd, int rn, ARMWord op2, Condition cc = AL) 281 { 282 emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2); 283 } 284 285 void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL) 286 { 287 emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2); 288 } 289 290 void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 291 { 292 emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2); 293 } 294 295 void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 296 { 297 emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2); 298 } 299 300 void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 301 { 302 emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2); 303 } 304 305 void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 306 { 307 emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2); 308 } 309 310 void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 311 { 312 emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2); 313 } 314 315 void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 316 { 317 emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2); 318 } 319 320 void tst_r(int rn, ARMWord op2, Condition cc = AL) 321 { 322 emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2); 323 } 324 325 void teq_r(int rn, ARMWord op2, Condition cc = AL) 326 { 327 emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2); 328 } 329 330 void cmp_r(int rn, ARMWord op2, Condition cc = AL) 331 { 332 emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2); 333 } 334 335 void cmn_r(int rn, ARMWord op2, Condition cc = AL) 336 { 337 emitInst(static_cast<ARMWord>(cc) | CMN | SET_CC, 0, rn, op2); 338 } 339 340 void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL) 341 { 342 emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2); 343 } 344 345 void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 346 { 347 emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2); 348 } 349 350 void mov_r(int rd, ARMWord op2, Condition cc = AL) 351 { 352 emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARMRegisters::r0, op2); 353 } 354 355 #if WTF_ARM_ARCH_AT_LEAST(7) 356 void movw_r(int rd, ARMWord op2, Condition cc = AL) 357 { 358 ASSERT((op2 | 0xf0fff) == 0xf0fff); 359 m_buffer.putInt(static_cast<ARMWord>(cc) | MOVW | RD(rd) | op2); 360 } 361 362 void movt_r(int rd, ARMWord op2, Condition cc = AL) 363 { 364 ASSERT((op2 | 0xf0fff) == 0xf0fff); 365 m_buffer.putInt(static_cast<ARMWord>(cc) | MOVT | RD(rd) | op2); 366 } 367 #endif 368 369 void movs_r(int rd, ARMWord op2, Condition cc = AL) 370 { 371 emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARMRegisters::r0, op2); 372 } 373 374 void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL) 375 { 376 emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2); 377 } 378 379 void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL) 380 { 381 emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2); 382 } 383 384 void mvn_r(int rd, ARMWord op2, Condition cc = AL) 385 { 386 emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARMRegisters::r0, op2); 387 } 388 389 void mvns_r(int rd, ARMWord op2, Condition cc = AL) 390 { 391 emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARMRegisters::r0, op2); 392 } 393 394 void mul_r(int rd, int rn, int rm, Condition cc = AL) 395 { 396 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm)); 397 } 398 399 void muls_r(int rd, int rn, int rm, Condition cc = AL) 400 { 401 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm)); 402 } 403 404 void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL) 405 { 406 m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm)); 407 } 408 409 void vadd_f64_r(int dd, int dn, int dm, Condition cc = AL) 410 { 411 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VADD_F64, dd, dn, dm); 412 } 413 414 void vdiv_f64_r(int dd, int dn, int dm, Condition cc = AL) 415 { 416 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VDIV_F64, dd, dn, dm); 417 } 418 419 void vsub_f64_r(int dd, int dn, int dm, Condition cc = AL) 420 { 421 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSUB_F64, dd, dn, dm); 422 } 423 424 void vmul_f64_r(int dd, int dn, int dm, Condition cc = AL) 425 { 426 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VMUL_F64, dd, dn, dm); 427 } 428 429 void vcmp_f64_r(int dd, int dm, Condition cc = AL) 430 { 431 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCMP_F64, dd, 0, dm); 432 } 433 434 void vsqrt_f64_r(int dd, int dm, Condition cc = AL) 435 { 436 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSQRT_F64, dd, 0, dm); 437 } 438 439 void ldr_imm(int rd, ARMWord imm, Condition cc = AL) 440 { 441 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm, true); 442 } 443 444 void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL) 445 { 446 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm); 447 } 448 449 void dtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 450 { 451 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP, rd, rb, op2); 452 } 453 454 void dtr_ur(bool isLoad, int rd, int rb, int rm, Condition cc = AL) 455 { 456 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP | OP2_OFSREG, rd, rb, rm); 457 } 458 459 void dtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 460 { 461 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0), rd, rb, op2); 462 } 463 464 void dtr_dr(bool isLoad, int rd, int rb, int rm, Condition cc = AL) 465 { 466 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | OP2_OFSREG, rd, rb, rm); 467 } 468 469 void ldrh_r(int rd, int rn, int rm, Condition cc = AL) 470 { 471 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm); 472 } 473 474 void ldrh_d(int rd, int rb, ARMWord op2, Condition cc = AL) 475 { 476 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_PRE, rd, rb, op2); 477 } 478 479 void ldrh_u(int rd, int rb, ARMWord op2, Condition cc = AL) 480 { 481 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rb, op2); 482 } 483 484 void strh_r(int rn, int rm, int rd, Condition cc = AL) 485 { 486 emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm); 487 } 488 489 void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 490 { 491 ASSERT(op2 <= 0xff); 492 emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2); 493 } 494 495 void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 496 { 497 ASSERT(op2 <= 0xff); 498 emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2); 499 } 500 501 void push_r(int reg, Condition cc = AL) 502 { 503 ASSERT(ARMWord(reg) <= 0xf); 504 m_buffer.putInt(cc | DTR | DT_WB | RN(ARMRegisters::sp) | RD(reg) | 0x4); 505 } 506 507 void pop_r(int reg, Condition cc = AL) 508 { 509 ASSERT(ARMWord(reg) <= 0xf); 510 m_buffer.putInt(cc | (DTR ^ DT_PRE) | DT_LOAD | DT_UP | RN(ARMRegisters::sp) | RD(reg) | 0x4); 511 } 512 513 inline void poke_r(int reg, Condition cc = AL) 514 { 515 dtr_d(false, ARMRegisters::sp, 0, reg, cc); 516 } 517 518 inline void peek_r(int reg, Condition cc = AL) 519 { 520 dtr_u(true, reg, ARMRegisters::sp, 0, cc); 521 } 522 523 void vmov_vfp_r(int sn, int rt, Condition cc = AL) 524 { 525 ASSERT(rt <= 15); 526 emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_VFP, rt << 1, sn, 0); 527 } 528 529 void vmov_arm_r(int rt, int sn, Condition cc = AL) 530 { 531 ASSERT(rt <= 15); 532 emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_ARM, rt << 1, sn, 0); 533 } 534 535 void vcvt_f64_s32_r(int dd, int sm, Condition cc = AL) 536 { 537 ASSERT(!(sm & 0x1)); // sm must be divisible by 2 538 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_F64_S32, dd, 0, (sm >> 1)); 539 } 540 541 void vcvt_s32_f64_r(int sd, int dm, Condition cc = AL) 542 { 543 ASSERT(!(sd & 0x1)); // sd must be divisible by 2 544 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_S32_F64, (sd >> 1), 0, dm); 545 } 546 547 void vcvtr_s32_f64_r(int sd, int dm, Condition cc = AL) 548 { 549 ASSERT(!(sd & 0x1)); // sd must be divisible by 2 550 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVTR_S32_F64, (sd >> 1), 0, dm); 551 } 552 553 void vmrs_apsr(Condition cc = AL) 554 { 555 m_buffer.putInt(static_cast<ARMWord>(cc) | VMRS_APSR); 556 } 557 558 #if WTF_ARM_ARCH_AT_LEAST(5) 559 void clz_r(int rd, int rm, Condition cc = AL) 560 { 561 m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm)); 562 } 563 #endif 564 bkpt(ARMWord value)565 void bkpt(ARMWord value) 566 { 567 #if WTF_ARM_ARCH_AT_LEAST(5) 568 m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf)); 569 #else 570 // Cannot access to Zero memory address 571 dtr_dr(true, ARMRegisters::S0, ARMRegisters::S0, ARMRegisters::S0); 572 #endif 573 } 574 575 void bx(int rm, Condition cc = AL) 576 { 577 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__) 578 emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm)); 579 #else 580 mov_r(ARMRegisters::pc, RM(rm), cc); 581 #endif 582 } 583 584 AssemblerLabel blx(int rm, Condition cc = AL) 585 { 586 #if WTF_ARM_ARCH_AT_LEAST(5) 587 emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm)); 588 #else 589 ASSERT(rm != 14); 590 ensureSpace(2 * sizeof(ARMWord), 0); 591 mov_r(ARMRegisters::lr, ARMRegisters::pc, cc); 592 bx(rm, cc); 593 #endif 594 return m_buffer.label(); 595 } 596 lsl(int reg,ARMWord value)597 static ARMWord lsl(int reg, ARMWord value) 598 { 599 ASSERT(reg <= ARMRegisters::pc); 600 ASSERT(value <= 0x1f); 601 return reg | (value << 7) | 0x00; 602 } 603 lsr(int reg,ARMWord value)604 static ARMWord lsr(int reg, ARMWord value) 605 { 606 ASSERT(reg <= ARMRegisters::pc); 607 ASSERT(value <= 0x1f); 608 return reg | (value << 7) | 0x20; 609 } 610 asr(int reg,ARMWord value)611 static ARMWord asr(int reg, ARMWord value) 612 { 613 ASSERT(reg <= ARMRegisters::pc); 614 ASSERT(value <= 0x1f); 615 return reg | (value << 7) | 0x40; 616 } 617 lsl_r(int reg,int shiftReg)618 static ARMWord lsl_r(int reg, int shiftReg) 619 { 620 ASSERT(reg <= ARMRegisters::pc); 621 ASSERT(shiftReg <= ARMRegisters::pc); 622 return reg | (shiftReg << 8) | 0x10; 623 } 624 lsr_r(int reg,int shiftReg)625 static ARMWord lsr_r(int reg, int shiftReg) 626 { 627 ASSERT(reg <= ARMRegisters::pc); 628 ASSERT(shiftReg <= ARMRegisters::pc); 629 return reg | (shiftReg << 8) | 0x30; 630 } 631 asr_r(int reg,int shiftReg)632 static ARMWord asr_r(int reg, int shiftReg) 633 { 634 ASSERT(reg <= ARMRegisters::pc); 635 ASSERT(shiftReg <= ARMRegisters::pc); 636 return reg | (shiftReg << 8) | 0x50; 637 } 638 639 // General helpers 640 codeSize()641 size_t codeSize() const 642 { 643 return m_buffer.codeSize(); 644 } 645 ensureSpace(int insnSpace,int constSpace)646 void ensureSpace(int insnSpace, int constSpace) 647 { 648 m_buffer.ensureSpace(insnSpace, constSpace); 649 } 650 sizeOfConstantPool()651 int sizeOfConstantPool() 652 { 653 return m_buffer.sizeOfConstantPool(); 654 } 655 label()656 AssemblerLabel label() 657 { 658 m_buffer.ensureSpaceForAnyOneInstruction(); 659 return m_buffer.label(); 660 } 661 align(int alignment)662 AssemblerLabel align(int alignment) 663 { 664 while (!m_buffer.isAligned(alignment)) 665 mov_r(ARMRegisters::r0, ARMRegisters::r0); 666 667 return label(); 668 } 669 670 AssemblerLabel loadBranchTarget(int rd, Condition cc = AL, int useConstantPool = 0) 671 { 672 ensureSpace(sizeof(ARMWord), sizeof(ARMWord)); 673 m_jumps.append(m_buffer.codeSize() | (useConstantPool & 0x1)); 674 ldr_un_imm(rd, InvalidBranchTarget, cc); 675 return m_buffer.label(); 676 } 677 678 AssemblerLabel jmp(Condition cc = AL, int useConstantPool = 0) 679 { 680 return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool); 681 } 682 683 void* executableCopy(ExecutablePool* allocator); 684 685 #ifndef NDEBUG debugOffset()686 unsigned debugOffset() { return m_buffer.debugOffset(); } 687 #endif 688 689 // Patching helpers 690 getLdrImmAddress(ARMWord * insn)691 static ARMWord* getLdrImmAddress(ARMWord* insn) 692 { 693 #if WTF_ARM_ARCH_AT_LEAST(5) 694 // Check for call 695 if ((*insn & 0x0f7f0000) != 0x051f0000) { 696 // Must be BLX 697 ASSERT((*insn & 0x012fff30) == 0x012fff30); 698 insn--; 699 } 700 #endif 701 // Must be an ldr ..., [pc +/- imm] 702 ASSERT((*insn & 0x0f7f0000) == 0x051f0000); 703 704 ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetching * sizeof(ARMWord); 705 if (*insn & DT_UP) 706 return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK)); 707 return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK)); 708 } 709 getLdrImmAddressOnPool(ARMWord * insn,uint32_t * constPool)710 static ARMWord* getLdrImmAddressOnPool(ARMWord* insn, uint32_t* constPool) 711 { 712 // Must be an ldr ..., [pc +/- imm] 713 ASSERT((*insn & 0x0f7f0000) == 0x051f0000); 714 715 if (*insn & 0x1) 716 return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1)); 717 return getLdrImmAddress(insn); 718 } 719 patchPointerInternal(intptr_t from,void * to)720 static void patchPointerInternal(intptr_t from, void* to) 721 { 722 ARMWord* insn = reinterpret_cast<ARMWord*>(from); 723 ARMWord* addr = getLdrImmAddress(insn); 724 *addr = reinterpret_cast<ARMWord>(to); 725 } 726 patchConstantPoolLoad(ARMWord load,ARMWord value)727 static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value) 728 { 729 value = (value << 1) + 1; 730 ASSERT(!(value & ~0xfff)); 731 return (load & ~0xfff) | value; 732 } 733 734 static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr); 735 736 // Patch pointers 737 linkPointer(void * code,AssemblerLabel from,void * to)738 static void linkPointer(void* code, AssemblerLabel from, void* to) 739 { 740 patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to); 741 } 742 repatchInt32(void * from,int32_t to)743 static void repatchInt32(void* from, int32_t to) 744 { 745 patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to)); 746 } 747 repatchPointer(void * from,void * to)748 static void repatchPointer(void* from, void* to) 749 { 750 patchPointerInternal(reinterpret_cast<intptr_t>(from), to); 751 } 752 753 // Linkers 754 static intptr_t getAbsoluteJumpAddress(void* base, int offset = 0) 755 { 756 return reinterpret_cast<intptr_t>(base) + offset - sizeof(ARMWord); 757 } 758 linkJump(AssemblerLabel from,AssemblerLabel to)759 void linkJump(AssemblerLabel from, AssemblerLabel to) 760 { 761 ARMWord* insn = reinterpret_cast<ARMWord*>(getAbsoluteJumpAddress(m_buffer.data(), from.m_offset)); 762 ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress()); 763 *addr = static_cast<ARMWord>(to.m_offset); 764 } 765 linkJump(void * code,AssemblerLabel from,void * to)766 static void linkJump(void* code, AssemblerLabel from, void* to) 767 { 768 patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to); 769 } 770 relinkJump(void * from,void * to)771 static void relinkJump(void* from, void* to) 772 { 773 patchPointerInternal(getAbsoluteJumpAddress(from), to); 774 } 775 linkCall(void * code,AssemblerLabel from,void * to)776 static void linkCall(void* code, AssemblerLabel from, void* to) 777 { 778 patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to); 779 } 780 relinkCall(void * from,void * to)781 static void relinkCall(void* from, void* to) 782 { 783 patchPointerInternal(getAbsoluteJumpAddress(from), to); 784 } 785 786 // Address operations 787 getRelocatedAddress(void * code,AssemblerLabel label)788 static void* getRelocatedAddress(void* code, AssemblerLabel label) 789 { 790 return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset); 791 } 792 793 // Address differences 794 getDifferenceBetweenLabels(AssemblerLabel a,AssemblerLabel b)795 static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b) 796 { 797 return b.m_offset - a.m_offset; 798 } 799 getCallReturnOffset(AssemblerLabel call)800 static unsigned getCallReturnOffset(AssemblerLabel call) 801 { 802 return call.m_offset; 803 } 804 805 // Handle immediates 806 getOp2Byte(ARMWord imm)807 static ARMWord getOp2Byte(ARMWord imm) 808 { 809 ASSERT(imm <= 0xff); 810 return OP2_IMMh | (imm & 0x0f) | ((imm & 0xf0) << 4) ; 811 } 812 813 static ARMWord getOp2(ARMWord imm); 814 815 #if WTF_ARM_ARCH_AT_LEAST(7) getImm16Op2(ARMWord imm)816 static ARMWord getImm16Op2(ARMWord imm) 817 { 818 if (imm <= 0xffff) 819 return (imm & 0xf000) << 4 | (imm & 0xfff); 820 return INVALID_IMM; 821 } 822 #endif 823 ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false); 824 void moveImm(ARMWord imm, int dest); 825 ARMWord encodeComplexImm(ARMWord imm, int dest); 826 getOffsetForHalfwordDataTransfer(ARMWord imm,int tmpReg)827 ARMWord getOffsetForHalfwordDataTransfer(ARMWord imm, int tmpReg) 828 { 829 // Encode immediate data in the instruction if it is possible 830 if (imm <= 0xff) 831 return getOp2Byte(imm); 832 // Otherwise, store the data in a temporary register 833 return encodeComplexImm(imm, tmpReg); 834 } 835 836 // Memory load/store helpers 837 838 void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes = false); 839 void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset); 840 void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset); 841 842 // Constant pool hnadlers 843 placeConstantPoolBarrier(int offset)844 static ARMWord placeConstantPoolBarrier(int offset) 845 { 846 offset = (offset - sizeof(ARMWord)) >> 2; 847 ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN)); 848 return AL | B | (offset & BRANCH_MASK); 849 } 850 851 private: RM(int reg)852 ARMWord RM(int reg) 853 { 854 ASSERT(reg <= ARMRegisters::pc); 855 return reg; 856 } 857 RS(int reg)858 ARMWord RS(int reg) 859 { 860 ASSERT(reg <= ARMRegisters::pc); 861 return reg << 8; 862 } 863 RD(int reg)864 ARMWord RD(int reg) 865 { 866 ASSERT(reg <= ARMRegisters::pc); 867 return reg << 12; 868 } 869 RN(int reg)870 ARMWord RN(int reg) 871 { 872 ASSERT(reg <= ARMRegisters::pc); 873 return reg << 16; 874 } 875 getConditionalField(ARMWord i)876 static ARMWord getConditionalField(ARMWord i) 877 { 878 return i & 0xf0000000; 879 } 880 881 int genInt(int reg, ARMWord imm, bool positive); 882 883 ARMBuffer m_buffer; 884 Jumps m_jumps; 885 }; 886 887 } // namespace JSC 888 889 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) 890 891 #endif // ARMAssembler_h 892