1 /* 2 * Copyright (C) 2009 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 #include <wtf/Platform.h> 31 32 #if ENABLE(ASSEMBLER) && PLATFORM(ARM) 33 34 #include "AssemblerBufferWithConstantPool.h" 35 #include <wtf/Assertions.h> 36 namespace JSC { 37 38 typedef uint32_t ARMWord; 39 40 namespace ARM { 41 typedef enum { 42 r0 = 0, 43 r1, 44 r2, 45 r3, 46 S0 = r3, 47 r4, 48 r5, 49 r6, 50 r7, 51 r8, 52 S1 = r8, 53 r9, 54 r10, 55 r11, 56 r12, 57 r13, 58 sp = r13, 59 r14, 60 lr = r14, 61 r15, 62 pc = r15 63 } RegisterID; 64 65 typedef enum { 66 d0, 67 d1, 68 d2, 69 d3, 70 SD0 = d3 71 } FPRegisterID; 72 73 } // namespace ARM 74 75 class ARMAssembler { 76 public: 77 typedef ARM::RegisterID RegisterID; 78 typedef ARM::FPRegisterID FPRegisterID; 79 typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer; 80 typedef WTF::SegmentedVector<int, 64> Jumps; 81 ARMAssembler()82 ARMAssembler() { } 83 84 // ARM conditional constants 85 typedef enum { 86 EQ = 0x00000000, // Zero 87 NE = 0x10000000, // Non-zero 88 CS = 0x20000000, 89 CC = 0x30000000, 90 MI = 0x40000000, 91 PL = 0x50000000, 92 VS = 0x60000000, 93 VC = 0x70000000, 94 HI = 0x80000000, 95 LS = 0x90000000, 96 GE = 0xa0000000, 97 LT = 0xb0000000, 98 GT = 0xc0000000, 99 LE = 0xd0000000, 100 AL = 0xe0000000 101 } Condition; 102 103 // ARM instruction constants 104 enum { 105 AND = (0x0 << 21), 106 EOR = (0x1 << 21), 107 SUB = (0x2 << 21), 108 RSB = (0x3 << 21), 109 ADD = (0x4 << 21), 110 ADC = (0x5 << 21), 111 SBC = (0x6 << 21), 112 RSC = (0x7 << 21), 113 TST = (0x8 << 21), 114 TEQ = (0x9 << 21), 115 CMP = (0xa << 21), 116 CMN = (0xb << 21), 117 ORR = (0xc << 21), 118 MOV = (0xd << 21), 119 BIC = (0xe << 21), 120 MVN = (0xf << 21), 121 MUL = 0x00000090, 122 MULL = 0x00c00090, 123 FADDD = 0x0e300b00, 124 FSUBD = 0x0e300b40, 125 FMULD = 0x0e200b00, 126 FCMPD = 0x0eb40b40, 127 DTR = 0x05000000, 128 LDRH = 0x00100090, 129 STRH = 0x00000090, 130 STMDB = 0x09200000, 131 LDMIA = 0x08b00000, 132 FDTR = 0x0d000b00, 133 B = 0x0a000000, 134 BL = 0x0b000000, 135 FMSR = 0x0e000a10, 136 FSITOD = 0x0eb80bc0, 137 FMSTAT = 0x0ef1fa10, 138 #if ARM_ARCH_VERSION >= 5 139 CLZ = 0x016f0f10, 140 BKPT = 0xe120070, 141 #endif 142 }; 143 144 enum { 145 OP2_IMM = (1 << 25), 146 OP2_IMMh = (1 << 22), 147 OP2_INV_IMM = (1 << 26), 148 SET_CC = (1 << 20), 149 OP2_OFSREG = (1 << 25), 150 DT_UP = (1 << 23), 151 DT_WB = (1 << 21), 152 // This flag is inlcuded in LDR and STR 153 DT_PRE = (1 << 24), 154 HDT_UH = (1 << 5), 155 DT_LOAD = (1 << 20), 156 }; 157 158 // Masks of ARM instructions 159 enum { 160 BRANCH_MASK = 0x00ffffff, 161 NONARM = 0xf0000000, 162 SDT_MASK = 0x0c000000, 163 SDT_OFFSET_MASK = 0xfff, 164 }; 165 166 enum { 167 BOFFSET_MIN = -0x00800000, 168 BOFFSET_MAX = 0x007fffff, 169 SDT = 0x04000000, 170 }; 171 172 enum { 173 padForAlign8 = 0x00, 174 padForAlign16 = 0x0000, 175 padForAlign32 = 0xee120070, 176 }; 177 178 class JmpSrc { 179 friend class ARMAssembler; 180 public: JmpSrc()181 JmpSrc() 182 : m_offset(-1) 183 , m_latePatch(false) 184 { 185 } 186 enableLatePatch()187 void enableLatePatch() { m_latePatch = true; } 188 private: JmpSrc(int offset)189 JmpSrc(int offset) 190 : m_offset(offset) 191 , m_latePatch(false) 192 { 193 } 194 195 int m_offset : 31; 196 int m_latePatch : 1; 197 }; 198 199 class JmpDst { 200 friend class ARMAssembler; 201 public: JmpDst()202 JmpDst() 203 : m_offset(-1) 204 , m_used(false) 205 { 206 } 207 isUsed()208 bool isUsed() const { return m_used; } used()209 void used() { m_used = true; } 210 private: JmpDst(int offset)211 JmpDst(int offset) 212 : m_offset(offset) 213 , m_used(false) 214 { 215 ASSERT(m_offset == offset); 216 } 217 218 int m_offset : 31; 219 int m_used : 1; 220 }; 221 222 // Instruction formating 223 emitInst(ARMWord op,int rd,int rn,ARMWord op2)224 void emitInst(ARMWord op, int rd, int rn, ARMWord op2) 225 { 226 ASSERT ( ((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff)) ); 227 m_buffer.putInt(op | RN(rn) | RD(rd) | op2); 228 } 229 230 void and_r(int rd, int rn, ARMWord op2, Condition cc = AL) 231 { 232 emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2); 233 } 234 235 void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL) 236 { 237 emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2); 238 } 239 240 void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL) 241 { 242 emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2); 243 } 244 245 void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL) 246 { 247 emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2); 248 } 249 250 void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL) 251 { 252 emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2); 253 } 254 255 void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 256 { 257 emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2); 258 } 259 260 void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL) 261 { 262 emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2); 263 } 264 265 void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 266 { 267 emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2); 268 } 269 270 void add_r(int rd, int rn, ARMWord op2, Condition cc = AL) 271 { 272 emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2); 273 } 274 275 void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL) 276 { 277 emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2); 278 } 279 280 void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 281 { 282 emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2); 283 } 284 285 void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 286 { 287 emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2); 288 } 289 290 void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 291 { 292 emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2); 293 } 294 295 void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 296 { 297 emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2); 298 } 299 300 void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL) 301 { 302 emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2); 303 } 304 305 void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 306 { 307 emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2); 308 } 309 310 void tst_r(int rn, ARMWord op2, Condition cc = AL) 311 { 312 emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2); 313 } 314 315 void teq_r(int rn, ARMWord op2, Condition cc = AL) 316 { 317 emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2); 318 } 319 320 void cmp_r(int rn, ARMWord op2, Condition cc = AL) 321 { 322 emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2); 323 } 324 325 void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL) 326 { 327 emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2); 328 } 329 330 void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL) 331 { 332 emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2); 333 } 334 335 void mov_r(int rd, ARMWord op2, Condition cc = AL) 336 { 337 emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARM::r0, op2); 338 } 339 340 void movs_r(int rd, ARMWord op2, Condition cc = AL) 341 { 342 emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARM::r0, op2); 343 } 344 345 void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL) 346 { 347 emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2); 348 } 349 350 void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL) 351 { 352 emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2); 353 } 354 355 void mvn_r(int rd, ARMWord op2, Condition cc = AL) 356 { 357 emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARM::r0, op2); 358 } 359 360 void mvns_r(int rd, ARMWord op2, Condition cc = AL) 361 { 362 emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARM::r0, op2); 363 } 364 365 void mul_r(int rd, int rn, int rm, Condition cc = AL) 366 { 367 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm)); 368 } 369 370 void muls_r(int rd, int rn, int rm, Condition cc = AL) 371 { 372 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm)); 373 } 374 375 void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL) 376 { 377 m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm)); 378 } 379 380 void faddd_r(int dd, int dn, int dm, Condition cc = AL) 381 { 382 emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm); 383 } 384 385 void fsubd_r(int dd, int dn, int dm, Condition cc = AL) 386 { 387 emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm); 388 } 389 390 void fmuld_r(int dd, int dn, int dm, Condition cc = AL) 391 { 392 emitInst(static_cast<ARMWord>(cc) | FMULD, dd, dn, dm); 393 } 394 395 void fcmpd_r(int dd, int dm, Condition cc = AL) 396 { 397 emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm); 398 } 399 400 void ldr_imm(int rd, ARMWord imm, Condition cc = AL) 401 { 402 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARM::pc) | RD(rd), imm, true); 403 } 404 405 void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL) 406 { 407 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARM::pc) | RD(rd), imm); 408 } 409 410 void dtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 411 { 412 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP, rd, rb, op2); 413 } 414 415 void dtr_ur(bool isLoad, int rd, int rb, int rm, Condition cc = AL) 416 { 417 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP | OP2_OFSREG, rd, rb, rm); 418 } 419 420 void dtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 421 { 422 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0), rd, rb, op2); 423 } 424 425 void dtr_dr(bool isLoad, int rd, int rb, int rm, Condition cc = AL) 426 { 427 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | OP2_OFSREG, rd, rb, rm); 428 } 429 430 void ldrh_r(int rd, int rn, int rm, Condition cc = AL) 431 { 432 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm); 433 } 434 435 void ldrh_d(int rd, int rb, ARMWord op2, Condition cc = AL) 436 { 437 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_PRE, rd, rb, op2); 438 } 439 440 void ldrh_u(int rd, int rb, ARMWord op2, Condition cc = AL) 441 { 442 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rb, op2); 443 } 444 445 void strh_r(int rn, int rm, int rd, Condition cc = AL) 446 { 447 emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm); 448 } 449 450 void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 451 { 452 ASSERT(op2 <= 0xff); 453 emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2); 454 } 455 456 void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL) 457 { 458 ASSERT(op2 <= 0xff); 459 emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2); 460 } 461 462 void push_r(int reg, Condition cc = AL) 463 { 464 ASSERT(ARMWord(reg) <= 0xf); 465 m_buffer.putInt(cc | DTR | DT_WB | RN(ARM::sp) | RD(reg) | 0x4); 466 } 467 468 void pop_r(int reg, Condition cc = AL) 469 { 470 ASSERT(ARMWord(reg) <= 0xf); 471 m_buffer.putInt(cc | (DTR ^ DT_PRE) | DT_LOAD | DT_UP | RN(ARM::sp) | RD(reg) | 0x4); 472 } 473 474 inline void poke_r(int reg, Condition cc = AL) 475 { 476 dtr_d(false, ARM::sp, 0, reg, cc); 477 } 478 479 inline void peek_r(int reg, Condition cc = AL) 480 { 481 dtr_u(true, reg, ARM::sp, 0, cc); 482 } 483 484 void fmsr_r(int dd, int rn, Condition cc = AL) 485 { 486 emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0); 487 } 488 489 void fsitod_r(int dd, int dm, Condition cc = AL) 490 { 491 emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm); 492 } 493 494 void fmstat(Condition cc = AL) 495 { 496 m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT); 497 } 498 499 #if ARM_ARCH_VERSION >= 5 500 void clz_r(int rd, int rm, Condition cc = AL) 501 { 502 m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm)); 503 } 504 #endif 505 bkpt(ARMWord value)506 void bkpt(ARMWord value) 507 { 508 #if ARM_ARCH_VERSION >= 5 509 m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf)); 510 #else 511 // Cannot access to Zero memory address 512 dtr_dr(true, ARM::S0, ARM::S0, ARM::S0); 513 #endif 514 } 515 lsl(int reg,ARMWord value)516 static ARMWord lsl(int reg, ARMWord value) 517 { 518 ASSERT(reg <= ARM::pc); 519 ASSERT(value <= 0x1f); 520 return reg | (value << 7) | 0x00; 521 } 522 lsr(int reg,ARMWord value)523 static ARMWord lsr(int reg, ARMWord value) 524 { 525 ASSERT(reg <= ARM::pc); 526 ASSERT(value <= 0x1f); 527 return reg | (value << 7) | 0x20; 528 } 529 asr(int reg,ARMWord value)530 static ARMWord asr(int reg, ARMWord value) 531 { 532 ASSERT(reg <= ARM::pc); 533 ASSERT(value <= 0x1f); 534 return reg | (value << 7) | 0x40; 535 } 536 lsl_r(int reg,int shiftReg)537 static ARMWord lsl_r(int reg, int shiftReg) 538 { 539 ASSERT(reg <= ARM::pc); 540 ASSERT(shiftReg <= ARM::pc); 541 return reg | (shiftReg << 8) | 0x10; 542 } 543 lsr_r(int reg,int shiftReg)544 static ARMWord lsr_r(int reg, int shiftReg) 545 { 546 ASSERT(reg <= ARM::pc); 547 ASSERT(shiftReg <= ARM::pc); 548 return reg | (shiftReg << 8) | 0x30; 549 } 550 asr_r(int reg,int shiftReg)551 static ARMWord asr_r(int reg, int shiftReg) 552 { 553 ASSERT(reg <= ARM::pc); 554 ASSERT(shiftReg <= ARM::pc); 555 return reg | (shiftReg << 8) | 0x50; 556 } 557 558 // General helpers 559 size()560 int size() 561 { 562 return m_buffer.size(); 563 } 564 ensureSpace(int insnSpace,int constSpace)565 void ensureSpace(int insnSpace, int constSpace) 566 { 567 m_buffer.ensureSpace(insnSpace, constSpace); 568 } 569 label()570 JmpDst label() 571 { 572 return JmpDst(m_buffer.size()); 573 } 574 align(int alignment)575 JmpDst align(int alignment) 576 { 577 while (!m_buffer.isAligned(alignment)) 578 mov_r(ARM::r0, ARM::r0); 579 580 return label(); 581 } 582 583 JmpSrc jmp(Condition cc = AL) 584 { 585 int s = size(); 586 ldr_un_imm(ARM::pc, 0xffffffff, cc); 587 m_jumps.append(s); 588 return JmpSrc(s); 589 } 590 591 void* executableCopy(ExecutablePool* allocator); 592 593 // Patching helpers 594 595 static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0); 596 static void linkBranch(void* code, JmpSrc from, void* to); 597 patchPointerInternal(intptr_t from,void * to)598 static void patchPointerInternal(intptr_t from, void* to) 599 { 600 ARMWord* insn = reinterpret_cast<ARMWord*>(from); 601 ARMWord* addr = getLdrImmAddress(insn); 602 *addr = reinterpret_cast<ARMWord>(to); 603 ExecutableAllocator::cacheFlush(addr, sizeof(ARMWord)); 604 } 605 patchConstantPoolLoad(ARMWord load,ARMWord value)606 static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value) 607 { 608 value = (value << 1) + 1; 609 ASSERT(!(value & ~0xfff)); 610 return (load & ~0xfff) | value; 611 } 612 613 static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr); 614 615 // Patch pointers 616 linkPointer(void * code,JmpDst from,void * to)617 static void linkPointer(void* code, JmpDst from, void* to) 618 { 619 patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to); 620 } 621 repatchInt32(void * from,int32_t to)622 static void repatchInt32(void* from, int32_t to) 623 { 624 patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to)); 625 } 626 repatchPointer(void * from,void * to)627 static void repatchPointer(void* from, void* to) 628 { 629 patchPointerInternal(reinterpret_cast<intptr_t>(from), to); 630 } 631 repatchLoadPtrToLEA(void * from)632 static void repatchLoadPtrToLEA(void* from) 633 { 634 // On arm, this is a patch from LDR to ADD. It is restricted conversion, 635 // from special case to special case, altough enough for its purpose 636 ARMWord* insn = reinterpret_cast<ARMWord*>(from); 637 ASSERT((*insn & 0x0ff00f00) == 0x05900000); 638 639 *insn = (*insn & 0xf00ff0ff) | 0x02800000; 640 ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord)); 641 } 642 643 // Linkers 644 linkJump(JmpSrc from,JmpDst to)645 void linkJump(JmpSrc from, JmpDst to) 646 { 647 ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord)); 648 *getLdrImmAddress(insn, m_buffer.poolAddress()) = static_cast<ARMWord>(to.m_offset); 649 } 650 linkJump(void * code,JmpSrc from,void * to)651 static void linkJump(void* code, JmpSrc from, void* to) 652 { 653 linkBranch(code, from, to); 654 } 655 relinkJump(void * from,void * to)656 static void relinkJump(void* from, void* to) 657 { 658 patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to); 659 } 660 linkCall(void * code,JmpSrc from,void * to)661 static void linkCall(void* code, JmpSrc from, void* to) 662 { 663 linkBranch(code, from, to); 664 } 665 relinkCall(void * from,void * to)666 static void relinkCall(void* from, void* to) 667 { 668 relinkJump(from, to); 669 } 670 671 // Address operations 672 getRelocatedAddress(void * code,JmpSrc jump)673 static void* getRelocatedAddress(void* code, JmpSrc jump) 674 { 675 return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + jump.m_offset / sizeof(ARMWord) + 1); 676 } 677 getRelocatedAddress(void * code,JmpDst label)678 static void* getRelocatedAddress(void* code, JmpDst label) 679 { 680 return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + label.m_offset / sizeof(ARMWord)); 681 } 682 683 // Address differences 684 getDifferenceBetweenLabels(JmpDst from,JmpSrc to)685 static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to) 686 { 687 return (to.m_offset + sizeof(ARMWord)) - from.m_offset; 688 } 689 getDifferenceBetweenLabels(JmpDst from,JmpDst to)690 static int getDifferenceBetweenLabels(JmpDst from, JmpDst to) 691 { 692 return to.m_offset - from.m_offset; 693 } 694 getCallReturnOffset(JmpSrc call)695 static unsigned getCallReturnOffset(JmpSrc call) 696 { 697 return call.m_offset + sizeof(ARMWord); 698 } 699 700 // Handle immediates 701 getOp2Byte(ARMWord imm)702 static ARMWord getOp2Byte(ARMWord imm) 703 { 704 ASSERT(imm <= 0xff); 705 return OP2_IMMh | (imm & 0x0f) | ((imm & 0xf0) << 4) ; 706 } 707 708 static ARMWord getOp2(ARMWord imm); 709 ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false); 710 void moveImm(ARMWord imm, int dest); 711 712 // Memory load/store helpers 713 714 void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset); 715 void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset); 716 void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset); 717 718 // Constant pool hnadlers 719 placeConstantPoolBarrier(int offset)720 static ARMWord placeConstantPoolBarrier(int offset) 721 { 722 offset = (offset - sizeof(ARMWord)) >> 2; 723 ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN)); 724 return AL | B | (offset & BRANCH_MASK); 725 } 726 727 private: RM(int reg)728 ARMWord RM(int reg) 729 { 730 ASSERT(reg <= ARM::pc); 731 return reg; 732 } 733 RS(int reg)734 ARMWord RS(int reg) 735 { 736 ASSERT(reg <= ARM::pc); 737 return reg << 8; 738 } 739 RD(int reg)740 ARMWord RD(int reg) 741 { 742 ASSERT(reg <= ARM::pc); 743 return reg << 12; 744 } 745 RN(int reg)746 ARMWord RN(int reg) 747 { 748 ASSERT(reg <= ARM::pc); 749 return reg << 16; 750 } 751 getConditionalField(ARMWord i)752 static ARMWord getConditionalField(ARMWord i) 753 { 754 return i & 0xf0000000; 755 } 756 757 int genInt(int reg, ARMWord imm, bool positive); 758 759 ARMBuffer m_buffer; 760 Jumps m_jumps; 761 }; 762 763 } // namespace JSC 764 765 #endif // ENABLE(ASSEMBLER) && PLATFORM(ARM) 766 767 #endif // ARMAssembler_h 768