2 * Copyright (C) 2009, 2010 University of Szeged
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #ifndef ARMAssembler_h
28 #define ARMAssembler_h
30 #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
32 #include "AssemblerBufferWithConstantPool.h"
33 #include <wtf/Assertions.h>
36 typedef uint32_t ARMWord;
38 namespace ARMRegisters {
93 } // namespace ARMRegisters
97 typedef ARMRegisters::RegisterID RegisterID;
98 typedef ARMRegisters::FPRegisterID FPRegisterID;
99 typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
100 typedef SegmentedVector<AssemblerLabel, 64> Jumps;
104 // ARM conditional constants
106 EQ = 0x00000000, // Zero
107 NE = 0x10000000, // Non-zero
123 // ARM instruction constants
143 VADD_F64 = 0x0e300b00,
144 VDIV_F64 = 0x0e800b00,
145 VSUB_F64 = 0x0e300b40,
146 VMUL_F64 = 0x0e200b00,
147 VCMP_F64 = 0x0eb40b40,
148 VSQRT_F64 = 0x0eb10bc0,
157 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
160 VMOV_VFP = 0x0e000a10,
161 VMOV_ARM = 0x0e100a10,
162 VCVT_F64_S32 = 0x0eb80bc0,
163 VCVT_S32_F64 = 0x0ebd0b40,
164 VMRS_APSR = 0x0ef1fa10,
165 #if WTF_ARM_ARCH_AT_LEAST(5)
170 #if WTF_ARM_ARCH_AT_LEAST(7)
179 OP2_IMMh = (1 << 22),
180 OP2_INV_IMM = (1 << 26),
182 OP2_OFSREG = (1 << 25),
186 // This flag is inlcuded in LDR and STR
192 // Masks of ARM instructions
194 BRANCH_MASK = 0x00ffffff,
196 SDT_MASK = 0x0c000000,
197 SDT_OFFSET_MASK = 0xfff,
201 BOFFSET_MIN = -0x00800000,
202 BOFFSET_MAX = 0x007fffff,
208 padForAlign16 = 0x0000,
209 padForAlign32 = 0xe12fff7f // 'bkpt 0xffff' instruction.
212 static const ARMWord INVALID_IMM = 0xf0000000;
213 static const ARMWord InvalidBranchTarget = 0xffffffff;
214 static const int DefaultPrefetching = 2;
216 // Instruction formating
218 void emitInst(ARMWord op, int rd, int rn, ARMWord op2)
220 ASSERT(((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff)));
221 m_buffer.putInt(op | RN(rn) | RD(rd) | op2);
224 void emitDoublePrecisionInst(ARMWord op, int dd, int dn, int dm)
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)));
232 void emitSinglePrecisionInst(ARMWord op, int sd, int sn, int sm)
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));
240 void and_r(int rd, int rn, ARMWord op2, Condition cc = AL)
242 emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2);
245 void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL)
247 emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2);
250 void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL)
252 emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2);
255 void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL)
257 emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2);
260 void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL)
262 emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2);
265 void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
267 emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2);
270 void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL)
272 emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2);
275 void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
277 emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2);
280 void add_r(int rd, int rn, ARMWord op2, Condition cc = AL)
282 emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2);
285 void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL)
287 emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2);
290 void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
292 emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2);
295 void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
297 emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2);
300 void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
302 emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2);
305 void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
307 emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2);
310 void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
312 emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2);
315 void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
317 emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2);
320 void tst_r(int rn, ARMWord op2, Condition cc = AL)
322 emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2);
325 void teq_r(int rn, ARMWord op2, Condition cc = AL)
327 emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2);
330 void cmp_r(int rn, ARMWord op2, Condition cc = AL)
332 emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2);
335 void cmn_r(int rn, ARMWord op2, Condition cc = AL)
337 emitInst(static_cast<ARMWord>(cc) | CMN | SET_CC, 0, rn, op2);
340 void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
342 emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2);
345 void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
347 emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2);
350 void mov_r(int rd, ARMWord op2, Condition cc = AL)
352 emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARMRegisters::r0, op2);
355 #if WTF_ARM_ARCH_AT_LEAST(7)
356 void movw_r(int rd, ARMWord op2, Condition cc = AL)
358 ASSERT((op2 | 0xf0fff) == 0xf0fff);
359 m_buffer.putInt(static_cast<ARMWord>(cc) | MOVW | RD(rd) | op2);
362 void movt_r(int rd, ARMWord op2, Condition cc = AL)
364 ASSERT((op2 | 0xf0fff) == 0xf0fff);
365 m_buffer.putInt(static_cast<ARMWord>(cc) | MOVT | RD(rd) | op2);
369 void movs_r(int rd, ARMWord op2, Condition cc = AL)
371 emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARMRegisters::r0, op2);
374 void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL)
376 emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2);
379 void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL)
381 emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2);
384 void mvn_r(int rd, ARMWord op2, Condition cc = AL)
386 emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARMRegisters::r0, op2);
389 void mvns_r(int rd, ARMWord op2, Condition cc = AL)
391 emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARMRegisters::r0, op2);
394 void mul_r(int rd, int rn, int rm, Condition cc = AL)
396 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm));
399 void muls_r(int rd, int rn, int rm, Condition cc = AL)
401 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm));
404 void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL)
406 m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm));
409 void vadd_f64_r(int dd, int dn, int dm, Condition cc = AL)
411 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VADD_F64, dd, dn, dm);
414 void vdiv_f64_r(int dd, int dn, int dm, Condition cc = AL)
416 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VDIV_F64, dd, dn, dm);
419 void vsub_f64_r(int dd, int dn, int dm, Condition cc = AL)
421 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSUB_F64, dd, dn, dm);
424 void vmul_f64_r(int dd, int dn, int dm, Condition cc = AL)
426 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VMUL_F64, dd, dn, dm);
429 void vcmp_f64_r(int dd, int dm, Condition cc = AL)
431 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCMP_F64, dd, 0, dm);
434 void vsqrt_f64_r(int dd, int dm, Condition cc = AL)
436 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSQRT_F64, dd, 0, dm);
439 void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
441 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm, true);
444 void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL)
446 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARMRegisters::pc) | RD(rd), imm);
449 void dtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
451 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP, rd, rb, op2);
454 void dtr_ur(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
456 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP | OP2_OFSREG, rd, rb, rm);
459 void dtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
461 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
464 void dtr_dr(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
466 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | OP2_OFSREG, rd, rb, rm);
469 void ldrh_r(int rd, int rn, int rm, Condition cc = AL)
471 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
474 void ldrh_d(int rd, int rb, ARMWord op2, Condition cc = AL)
476 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_PRE, rd, rb, op2);
479 void ldrh_u(int rd, int rb, ARMWord op2, Condition cc = AL)
481 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rb, op2);
484 void strh_r(int rn, int rm, int rd, Condition cc = AL)
486 emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
489 void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
492 emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2);
495 void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
498 emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
501 void push_r(int reg, Condition cc = AL)
503 ASSERT(ARMWord(reg) <= 0xf);
504 m_buffer.putInt(cc | DTR | DT_WB | RN(ARMRegisters::sp) | RD(reg) | 0x4);
507 void pop_r(int reg, Condition cc = AL)
509 ASSERT(ARMWord(reg) <= 0xf);
510 m_buffer.putInt(cc | (DTR ^ DT_PRE) | DT_LOAD | DT_UP | RN(ARMRegisters::sp) | RD(reg) | 0x4);
513 inline void poke_r(int reg, Condition cc = AL)
515 dtr_d(false, ARMRegisters::sp, 0, reg, cc);
518 inline void peek_r(int reg, Condition cc = AL)
520 dtr_u(true, reg, ARMRegisters::sp, 0, cc);
523 void vmov_vfp_r(int sn, int rt, Condition cc = AL)
526 emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_VFP, rt << 1, sn, 0);
529 void vmov_arm_r(int rt, int sn, Condition cc = AL)
532 emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_ARM, rt << 1, sn, 0);
535 void vcvt_f64_s32_r(int dd, int sm, Condition cc = AL)
537 ASSERT(!(sm & 0x1)); // sm must be divisible by 2
538 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_F64_S32, dd, 0, (sm >> 1));
541 void vcvt_s32_f64_r(int sd, int dm, Condition cc = AL)
543 ASSERT(!(sd & 0x1)); // sd must be divisible by 2
544 emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_S32_F64, (sd >> 1), 0, dm);
547 void vmrs_apsr(Condition cc = AL)
549 m_buffer.putInt(static_cast<ARMWord>(cc) | VMRS_APSR);
552 #if WTF_ARM_ARCH_AT_LEAST(5)
553 void clz_r(int rd, int rm, Condition cc = AL)
555 m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm));
559 void bkpt(ARMWord value)
561 #if WTF_ARM_ARCH_AT_LEAST(5)
562 m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf));
564 // Cannot access to Zero memory address
565 dtr_dr(true, ARMRegisters::S0, ARMRegisters::S0, ARMRegisters::S0);
571 m_buffer.putInt(NOP);
574 void bx(int rm, Condition cc = AL)
576 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
577 emitInst(static_cast<ARMWord>(cc) | BX, 0, 0, RM(rm));
579 mov_r(ARMRegisters::pc, RM(rm), cc);
583 AssemblerLabel blx(int rm, Condition cc = AL)
585 #if WTF_ARM_ARCH_AT_LEAST(5)
586 emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm));
589 ensureSpace(2 * sizeof(ARMWord), 0);
590 mov_r(ARMRegisters::lr, ARMRegisters::pc, cc);
593 return m_buffer.label();
596 static ARMWord lsl(int reg, ARMWord value)
598 ASSERT(reg <= ARMRegisters::pc);
599 ASSERT(value <= 0x1f);
600 return reg | (value << 7) | 0x00;
603 static ARMWord lsr(int reg, ARMWord value)
605 ASSERT(reg <= ARMRegisters::pc);
606 ASSERT(value <= 0x1f);
607 return reg | (value << 7) | 0x20;
610 static ARMWord asr(int reg, ARMWord value)
612 ASSERT(reg <= ARMRegisters::pc);
613 ASSERT(value <= 0x1f);
614 return reg | (value << 7) | 0x40;
617 static ARMWord lsl_r(int reg, int shiftReg)
619 ASSERT(reg <= ARMRegisters::pc);
620 ASSERT(shiftReg <= ARMRegisters::pc);
621 return reg | (shiftReg << 8) | 0x10;
624 static ARMWord lsr_r(int reg, int shiftReg)
626 ASSERT(reg <= ARMRegisters::pc);
627 ASSERT(shiftReg <= ARMRegisters::pc);
628 return reg | (shiftReg << 8) | 0x30;
631 static ARMWord asr_r(int reg, int shiftReg)
633 ASSERT(reg <= ARMRegisters::pc);
634 ASSERT(shiftReg <= ARMRegisters::pc);
635 return reg | (shiftReg << 8) | 0x50;
640 size_t codeSize() const
642 return m_buffer.codeSize();
645 void ensureSpace(int insnSpace, int constSpace)
647 m_buffer.ensureSpace(insnSpace, constSpace);
650 int sizeOfConstantPool()
652 return m_buffer.sizeOfConstantPool();
655 AssemblerLabel label()
657 m_buffer.ensureSpaceForAnyOneInstruction();
658 return m_buffer.label();
661 AssemblerLabel align(int alignment)
663 while (!m_buffer.isAligned(alignment))
664 mov_r(ARMRegisters::r0, ARMRegisters::r0);
669 AssemblerLabel loadBranchTarget(int rd, Condition cc = AL, int useConstantPool = 0)
671 ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
672 m_jumps.append(m_buffer.codeSize() | (useConstantPool & 0x1));
673 ldr_un_imm(rd, InvalidBranchTarget, cc);
674 return m_buffer.label();
677 AssemblerLabel jmp(Condition cc = AL, int useConstantPool = 0)
679 return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool);
682 PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData&);
685 unsigned debugOffset() { return m_buffer.debugOffset(); }
690 static ARMWord* getLdrImmAddress(ARMWord* insn)
692 #if WTF_ARM_ARCH_AT_LEAST(5)
694 if ((*insn & 0x0f7f0000) != 0x051f0000) {
696 ASSERT((*insn & 0x012fff30) == 0x012fff30);
700 // Must be an ldr ..., [pc +/- imm]
701 ASSERT((*insn & 0x0f7f0000) == 0x051f0000);
703 ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetching * sizeof(ARMWord);
705 return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK));
706 return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK));
709 static ARMWord* getLdrImmAddressOnPool(ARMWord* insn, uint32_t* constPool)
711 // Must be an ldr ..., [pc +/- imm]
712 ASSERT((*insn & 0x0f7f0000) == 0x051f0000);
715 return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1));
716 return getLdrImmAddress(insn);
719 static void patchPointerInternal(intptr_t from, void* to)
721 ARMWord* insn = reinterpret_cast<ARMWord*>(from);
722 ARMWord* addr = getLdrImmAddress(insn);
723 *addr = reinterpret_cast<ARMWord>(to);
726 static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value)
728 value = (value << 1) + 1;
729 ASSERT(!(value & ~0xfff));
730 return (load & ~0xfff) | value;
733 static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr);
736 static void* readPointer(void* from)
738 ARMWord* insn = reinterpret_cast<ARMWord*>(from);
739 ARMWord* addr = getLdrImmAddress(insn);
740 return *reinterpret_cast<void**>(addr);
745 static void linkPointer(void* code, AssemblerLabel from, void* to)
747 patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
750 static void repatchInt32(void* from, int32_t to)
752 patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to));
755 static void repatchCompact(void* where, int32_t value)
757 repatchInt32(where, value);
760 static void repatchPointer(void* from, void* to)
762 patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
766 static intptr_t getAbsoluteJumpAddress(void* base, int offset = 0)
768 return reinterpret_cast<intptr_t>(base) + offset - sizeof(ARMWord);
771 void linkJump(AssemblerLabel from, AssemblerLabel to)
773 ARMWord* insn = reinterpret_cast<ARMWord*>(getAbsoluteJumpAddress(m_buffer.data(), from.m_offset));
774 ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress());
775 *addr = static_cast<ARMWord>(to.m_offset);
778 static void linkJump(void* code, AssemblerLabel from, void* to)
780 patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to);
783 static void relinkJump(void* from, void* to)
785 patchPointerInternal(getAbsoluteJumpAddress(from), to);
788 static void linkCall(void* code, AssemblerLabel from, void* to)
790 patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to);
793 static void relinkCall(void* from, void* to)
795 patchPointerInternal(getAbsoluteJumpAddress(from), to);
798 // Address operations
800 static void* getRelocatedAddress(void* code, AssemblerLabel label)
802 return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
805 // Address differences
807 static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
809 return b.m_offset - a.m_offset;
812 static unsigned getCallReturnOffset(AssemblerLabel call)
814 return call.m_offset;
819 static ARMWord getOp2Byte(ARMWord imm)
822 return OP2_IMMh | (imm & 0x0f) | ((imm & 0xf0) << 4) ;
825 static ARMWord getOp2(ARMWord imm);
827 #if WTF_ARM_ARCH_AT_LEAST(7)
828 static ARMWord getImm16Op2(ARMWord imm)
831 return (imm & 0xf000) << 4 | (imm & 0xfff);
835 ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false);
836 void moveImm(ARMWord imm, int dest);
837 ARMWord encodeComplexImm(ARMWord imm, int dest);
839 ARMWord getOffsetForHalfwordDataTransfer(ARMWord imm, int tmpReg)
841 // Encode immediate data in the instruction if it is possible
843 return getOp2Byte(imm);
844 // Otherwise, store the data in a temporary register
845 return encodeComplexImm(imm, tmpReg);
848 // Memory load/store helpers
850 void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes = false);
851 void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset, bool bytes = false);
852 void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset);
854 // Constant pool hnadlers
856 static ARMWord placeConstantPoolBarrier(int offset)
858 offset = (offset - sizeof(ARMWord)) >> 2;
859 ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN));
860 return AL | B | (offset & BRANCH_MASK);
866 ASSERT(reg <= ARMRegisters::pc);
872 ASSERT(reg <= ARMRegisters::pc);
878 ASSERT(reg <= ARMRegisters::pc);
884 ASSERT(reg <= ARMRegisters::pc);
888 static ARMWord getConditionalField(ARMWord i)
890 return i & 0xf0000000;
893 int genInt(int reg, ARMWord imm, bool positive);
901 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
903 #endif // ARMAssembler_h