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
{
71 } // namespace ARMRegisters
75 typedef ARMRegisters::RegisterID RegisterID
;
76 typedef ARMRegisters::FPRegisterID FPRegisterID
;
77 typedef AssemblerBufferWithConstantPool
<2048, 4, 4, ARMAssembler
> ARMBuffer
;
78 typedef SegmentedVector
<int, 64> Jumps
;
82 // ARM conditional constants
84 EQ
= 0x00000000, // Zero
85 NE
= 0x10000000, // Non-zero
101 // ARM instruction constants
135 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
143 #if WTF_ARM_ARCH_AT_LEAST(5)
148 #if WTF_ARM_ARCH_AT_LEAST(7)
156 OP2_IMMh
= (1 << 22),
157 OP2_INV_IMM
= (1 << 26),
159 OP2_OFSREG
= (1 << 25),
163 // This flag is inlcuded in LDR and STR
169 // Masks of ARM instructions
171 BRANCH_MASK
= 0x00ffffff,
173 SDT_MASK
= 0x0c000000,
174 SDT_OFFSET_MASK
= 0xfff,
178 BOFFSET_MIN
= -0x00800000,
179 BOFFSET_MAX
= 0x007fffff,
185 padForAlign16
= 0x0000,
186 padForAlign32
= 0xee120070,
189 static const ARMWord INVALID_IMM
= 0xf0000000;
190 static const ARMWord InvalidBranchTarget
= 0xffffffff;
191 static const int DefaultPrefetching
= 2;
194 friend class ARMAssembler
;
211 friend class ARMAssembler
;
219 bool isUsed() const { return m_used
; }
220 void used() { m_used
= true; }
226 ASSERT(m_offset
== offset
);
233 // Instruction formating
235 void emitInst(ARMWord op
, int rd
, int rn
, ARMWord op2
)
237 ASSERT ( ((op2
& ~OP2_IMM
) <= 0xfff) || (((op2
& ~OP2_IMMh
) <= 0xfff)) );
238 m_buffer
.putInt(op
| RN(rn
) | RD(rd
) | op2
);
241 void and_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
243 emitInst(static_cast<ARMWord
>(cc
) | AND
, rd
, rn
, op2
);
246 void ands_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
248 emitInst(static_cast<ARMWord
>(cc
) | AND
| SET_CC
, rd
, rn
, op2
);
251 void eor_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
253 emitInst(static_cast<ARMWord
>(cc
) | EOR
, rd
, rn
, op2
);
256 void eors_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
258 emitInst(static_cast<ARMWord
>(cc
) | EOR
| SET_CC
, rd
, rn
, op2
);
261 void sub_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
263 emitInst(static_cast<ARMWord
>(cc
) | SUB
, rd
, rn
, op2
);
266 void subs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
268 emitInst(static_cast<ARMWord
>(cc
) | SUB
| SET_CC
, rd
, rn
, op2
);
271 void rsb_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
273 emitInst(static_cast<ARMWord
>(cc
) | RSB
, rd
, rn
, op2
);
276 void rsbs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
278 emitInst(static_cast<ARMWord
>(cc
) | RSB
| SET_CC
, rd
, rn
, op2
);
281 void add_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
283 emitInst(static_cast<ARMWord
>(cc
) | ADD
, rd
, rn
, op2
);
286 void adds_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
288 emitInst(static_cast<ARMWord
>(cc
) | ADD
| SET_CC
, rd
, rn
, op2
);
291 void adc_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
293 emitInst(static_cast<ARMWord
>(cc
) | ADC
, rd
, rn
, op2
);
296 void adcs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
298 emitInst(static_cast<ARMWord
>(cc
) | ADC
| SET_CC
, rd
, rn
, op2
);
301 void sbc_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
303 emitInst(static_cast<ARMWord
>(cc
) | SBC
, rd
, rn
, op2
);
306 void sbcs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
308 emitInst(static_cast<ARMWord
>(cc
) | SBC
| SET_CC
, rd
, rn
, op2
);
311 void rsc_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
313 emitInst(static_cast<ARMWord
>(cc
) | RSC
, rd
, rn
, op2
);
316 void rscs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
318 emitInst(static_cast<ARMWord
>(cc
) | RSC
| SET_CC
, rd
, rn
, op2
);
321 void tst_r(int rn
, ARMWord op2
, Condition cc
= AL
)
323 emitInst(static_cast<ARMWord
>(cc
) | TST
| SET_CC
, 0, rn
, op2
);
326 void teq_r(int rn
, ARMWord op2
, Condition cc
= AL
)
328 emitInst(static_cast<ARMWord
>(cc
) | TEQ
| SET_CC
, 0, rn
, op2
);
331 void cmp_r(int rn
, ARMWord op2
, Condition cc
= AL
)
333 emitInst(static_cast<ARMWord
>(cc
) | CMP
| SET_CC
, 0, rn
, op2
);
336 void orr_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
338 emitInst(static_cast<ARMWord
>(cc
) | ORR
, rd
, rn
, op2
);
341 void orrs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
343 emitInst(static_cast<ARMWord
>(cc
) | ORR
| SET_CC
, rd
, rn
, op2
);
346 void mov_r(int rd
, ARMWord op2
, Condition cc
= AL
)
348 emitInst(static_cast<ARMWord
>(cc
) | MOV
, rd
, ARMRegisters::r0
, op2
);
351 #if WTF_ARM_ARCH_AT_LEAST(7)
352 void movw_r(int rd
, ARMWord op2
, Condition cc
= AL
)
354 ASSERT((op2
| 0xf0fff) == 0xf0fff);
355 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MOVW
| RD(rd
) | op2
);
358 void movt_r(int rd
, ARMWord op2
, Condition cc
= AL
)
360 ASSERT((op2
| 0xf0fff) == 0xf0fff);
361 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MOVT
| RD(rd
) | op2
);
365 void movs_r(int rd
, ARMWord op2
, Condition cc
= AL
)
367 emitInst(static_cast<ARMWord
>(cc
) | MOV
| SET_CC
, rd
, ARMRegisters::r0
, op2
);
370 void bic_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
372 emitInst(static_cast<ARMWord
>(cc
) | BIC
, rd
, rn
, op2
);
375 void bics_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
377 emitInst(static_cast<ARMWord
>(cc
) | BIC
| SET_CC
, rd
, rn
, op2
);
380 void mvn_r(int rd
, ARMWord op2
, Condition cc
= AL
)
382 emitInst(static_cast<ARMWord
>(cc
) | MVN
, rd
, ARMRegisters::r0
, op2
);
385 void mvns_r(int rd
, ARMWord op2
, Condition cc
= AL
)
387 emitInst(static_cast<ARMWord
>(cc
) | MVN
| SET_CC
, rd
, ARMRegisters::r0
, op2
);
390 void mul_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
392 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MUL
| RN(rd
) | RS(rn
) | RM(rm
));
395 void muls_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
397 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MUL
| SET_CC
| RN(rd
) | RS(rn
) | RM(rm
));
400 void mull_r(int rdhi
, int rdlo
, int rn
, int rm
, Condition cc
= AL
)
402 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MULL
| RN(rdhi
) | RD(rdlo
) | RS(rn
) | RM(rm
));
405 void faddd_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
407 emitInst(static_cast<ARMWord
>(cc
) | FADDD
, dd
, dn
, dm
);
410 void fdivd_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
412 emitInst(static_cast<ARMWord
>(cc
) | FDIVD
, dd
, dn
, dm
);
415 void fsubd_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
417 emitInst(static_cast<ARMWord
>(cc
) | FSUBD
, dd
, dn
, dm
);
420 void fmuld_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
422 emitInst(static_cast<ARMWord
>(cc
) | FMULD
, dd
, dn
, dm
);
425 void fcmpd_r(int dd
, int dm
, Condition cc
= AL
)
427 emitInst(static_cast<ARMWord
>(cc
) | FCMPD
, dd
, 0, dm
);
430 void fsqrtd_r(int dd
, int dm
, Condition cc
= AL
)
432 emitInst(static_cast<ARMWord
>(cc
) | FSQRTD
, dd
, 0, dm
);
435 void ldr_imm(int rd
, ARMWord imm
, Condition cc
= AL
)
437 m_buffer
.putIntWithConstantInt(static_cast<ARMWord
>(cc
) | DTR
| DT_LOAD
| DT_UP
| RN(ARMRegisters::pc
) | RD(rd
), imm
, true);
440 void ldr_un_imm(int rd
, ARMWord imm
, Condition cc
= AL
)
442 m_buffer
.putIntWithConstantInt(static_cast<ARMWord
>(cc
) | DTR
| DT_LOAD
| DT_UP
| RN(ARMRegisters::pc
) | RD(rd
), imm
);
445 void dtr_u(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
447 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | DT_UP
, rd
, rb
, op2
);
450 void dtr_ur(bool isLoad
, int rd
, int rb
, int rm
, Condition cc
= AL
)
452 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | DT_UP
| OP2_OFSREG
, rd
, rb
, rm
);
455 void dtr_d(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
457 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
460 void dtr_dr(bool isLoad
, int rd
, int rb
, int rm
, Condition cc
= AL
)
462 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | OP2_OFSREG
, rd
, rb
, rm
);
465 void ldrh_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
467 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rn
, rm
);
470 void ldrh_d(int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
472 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_PRE
, rd
, rb
, op2
);
475 void ldrh_u(int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
477 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rb
, op2
);
480 void strh_r(int rn
, int rm
, int rd
, Condition cc
= AL
)
482 emitInst(static_cast<ARMWord
>(cc
) | STRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rn
, rm
);
485 void fdtr_u(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
488 emitInst(static_cast<ARMWord
>(cc
) | FDTR
| DT_UP
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
491 void fdtr_d(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
494 emitInst(static_cast<ARMWord
>(cc
) | FDTR
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
497 void push_r(int reg
, Condition cc
= AL
)
499 ASSERT(ARMWord(reg
) <= 0xf);
500 m_buffer
.putInt(cc
| DTR
| DT_WB
| RN(ARMRegisters::sp
) | RD(reg
) | 0x4);
503 void pop_r(int reg
, Condition cc
= AL
)
505 ASSERT(ARMWord(reg
) <= 0xf);
506 m_buffer
.putInt(cc
| (DTR
^ DT_PRE
) | DT_LOAD
| DT_UP
| RN(ARMRegisters::sp
) | RD(reg
) | 0x4);
509 inline void poke_r(int reg
, Condition cc
= AL
)
511 dtr_d(false, ARMRegisters::sp
, 0, reg
, cc
);
514 inline void peek_r(int reg
, Condition cc
= AL
)
516 dtr_u(true, reg
, ARMRegisters::sp
, 0, cc
);
519 void fmsr_r(int dd
, int rn
, Condition cc
= AL
)
521 emitInst(static_cast<ARMWord
>(cc
) | FMSR
, rn
, dd
, 0);
524 void fmrs_r(int rd
, int dn
, Condition cc
= AL
)
526 emitInst(static_cast<ARMWord
>(cc
) | FMRS
, rd
, dn
, 0);
529 void fsitod_r(int dd
, int dm
, Condition cc
= AL
)
531 emitInst(static_cast<ARMWord
>(cc
) | FSITOD
, dd
, 0, dm
);
534 void ftosid_r(int fd
, int dm
, Condition cc
= AL
)
536 emitInst(static_cast<ARMWord
>(cc
) | FTOSID
, fd
, 0, dm
);
539 void fmstat(Condition cc
= AL
)
541 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | FMSTAT
);
544 #if WTF_ARM_ARCH_AT_LEAST(5)
545 void clz_r(int rd
, int rm
, Condition cc
= AL
)
547 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | CLZ
| RD(rd
) | RM(rm
));
551 void bkpt(ARMWord value
)
553 #if WTF_ARM_ARCH_AT_LEAST(5)
554 m_buffer
.putInt(BKPT
| ((value
& 0xff0) << 4) | (value
& 0xf));
556 // Cannot access to Zero memory address
557 dtr_dr(true, ARMRegisters::S0
, ARMRegisters::S0
, ARMRegisters::S0
);
561 void bx(int rm
, Condition cc
= AL
)
563 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
564 emitInst(static_cast<ARMWord
>(cc
) | BX
, 0, 0, RM(rm
));
566 mov_r(ARMRegisters::pc
, RM(rm
), cc
);
570 JmpSrc
blx(int rm
, Condition cc
= AL
)
572 #if WTF_ARM_ARCH_AT_LEAST(5)
573 int s
= m_buffer
.uncheckedSize();
574 emitInst(static_cast<ARMWord
>(cc
) | BLX
, 0, 0, RM(rm
));
577 ensureSpace(2 * sizeof(ARMWord
), 0);
578 mov_r(ARMRegisters::lr
, ARMRegisters::pc
, cc
);
579 int s
= m_buffer
.uncheckedSize();
585 static ARMWord
lsl(int reg
, ARMWord value
)
587 ASSERT(reg
<= ARMRegisters::pc
);
588 ASSERT(value
<= 0x1f);
589 return reg
| (value
<< 7) | 0x00;
592 static ARMWord
lsr(int reg
, ARMWord value
)
594 ASSERT(reg
<= ARMRegisters::pc
);
595 ASSERT(value
<= 0x1f);
596 return reg
| (value
<< 7) | 0x20;
599 static ARMWord
asr(int reg
, ARMWord value
)
601 ASSERT(reg
<= ARMRegisters::pc
);
602 ASSERT(value
<= 0x1f);
603 return reg
| (value
<< 7) | 0x40;
606 static ARMWord
lsl_r(int reg
, int shiftReg
)
608 ASSERT(reg
<= ARMRegisters::pc
);
609 ASSERT(shiftReg
<= ARMRegisters::pc
);
610 return reg
| (shiftReg
<< 8) | 0x10;
613 static ARMWord
lsr_r(int reg
, int shiftReg
)
615 ASSERT(reg
<= ARMRegisters::pc
);
616 ASSERT(shiftReg
<= ARMRegisters::pc
);
617 return reg
| (shiftReg
<< 8) | 0x30;
620 static ARMWord
asr_r(int reg
, int shiftReg
)
622 ASSERT(reg
<= ARMRegisters::pc
);
623 ASSERT(shiftReg
<= ARMRegisters::pc
);
624 return reg
| (shiftReg
<< 8) | 0x50;
631 return m_buffer
.size();
634 void ensureSpace(int insnSpace
, int constSpace
)
636 m_buffer
.ensureSpace(insnSpace
, constSpace
);
639 int sizeOfConstantPool()
641 return m_buffer
.sizeOfConstantPool();
646 return JmpDst(m_buffer
.size());
649 JmpDst
align(int alignment
)
651 while (!m_buffer
.isAligned(alignment
))
652 mov_r(ARMRegisters::r0
, ARMRegisters::r0
);
657 JmpSrc
loadBranchTarget(int rd
, Condition cc
= AL
, int useConstantPool
= 0)
659 ensureSpace(sizeof(ARMWord
), sizeof(ARMWord
));
660 int s
= m_buffer
.uncheckedSize();
661 ldr_un_imm(rd
, InvalidBranchTarget
, cc
);
662 m_jumps
.append(s
| (useConstantPool
& 0x1));
666 JmpSrc
jmp(Condition cc
= AL
, int useConstantPool
= 0)
668 return loadBranchTarget(ARMRegisters::pc
, cc
, useConstantPool
);
671 void* executableCopy(ExecutablePool
* allocator
);
675 static ARMWord
* getLdrImmAddress(ARMWord
* insn
)
677 #if WTF_ARM_ARCH_AT_LEAST(5)
679 if ((*insn
& 0x0f7f0000) != 0x051f0000) {
681 ASSERT((*insn
& 0x012fff30) == 0x012fff30);
685 // Must be an ldr ..., [pc +/- imm]
686 ASSERT((*insn
& 0x0f7f0000) == 0x051f0000);
688 ARMWord addr
= reinterpret_cast<ARMWord
>(insn
) + DefaultPrefetching
* sizeof(ARMWord
);
690 return reinterpret_cast<ARMWord
*>(addr
+ (*insn
& SDT_OFFSET_MASK
));
691 return reinterpret_cast<ARMWord
*>(addr
- (*insn
& SDT_OFFSET_MASK
));
694 static ARMWord
* getLdrImmAddressOnPool(ARMWord
* insn
, uint32_t* constPool
)
696 // Must be an ldr ..., [pc +/- imm]
697 ASSERT((*insn
& 0x0f7f0000) == 0x051f0000);
700 return reinterpret_cast<ARMWord
*>(constPool
+ ((*insn
& SDT_OFFSET_MASK
) >> 1));
701 return getLdrImmAddress(insn
);
704 static void patchPointerInternal(intptr_t from
, void* to
)
706 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(from
);
707 ARMWord
* addr
= getLdrImmAddress(insn
);
708 *addr
= reinterpret_cast<ARMWord
>(to
);
711 static ARMWord
patchConstantPoolLoad(ARMWord load
, ARMWord value
)
713 value
= (value
<< 1) + 1;
714 ASSERT(!(value
& ~0xfff));
715 return (load
& ~0xfff) | value
;
718 static void patchConstantPoolLoad(void* loadAddr
, void* constPoolAddr
);
722 static void linkPointer(void* code
, JmpDst from
, void* to
)
724 patchPointerInternal(reinterpret_cast<intptr_t>(code
) + from
.m_offset
, to
);
727 static void repatchInt32(void* from
, int32_t to
)
729 patchPointerInternal(reinterpret_cast<intptr_t>(from
), reinterpret_cast<void*>(to
));
732 static void repatchPointer(void* from
, void* to
)
734 patchPointerInternal(reinterpret_cast<intptr_t>(from
), to
);
737 static void repatchLoadPtrToLEA(void* from
)
739 // On arm, this is a patch from LDR to ADD. It is restricted conversion,
740 // from special case to special case, altough enough for its purpose
741 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(from
);
742 ASSERT((*insn
& 0x0ff00f00) == 0x05900000);
744 *insn
= (*insn
& 0xf00ff0ff) | 0x02800000;
745 ExecutableAllocator::cacheFlush(insn
, sizeof(ARMWord
));
750 void linkJump(JmpSrc from
, JmpDst to
)
752 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(m_buffer
.data()) + (from
.m_offset
/ sizeof(ARMWord
));
753 ARMWord
* addr
= getLdrImmAddressOnPool(insn
, m_buffer
.poolAddress());
754 *addr
= static_cast<ARMWord
>(to
.m_offset
);
757 static void linkJump(void* code
, JmpSrc from
, void* to
)
759 patchPointerInternal(reinterpret_cast<intptr_t>(code
) + from
.m_offset
, to
);
762 static void relinkJump(void* from
, void* to
)
764 patchPointerInternal(reinterpret_cast<intptr_t>(from
) - sizeof(ARMWord
), to
);
767 static void linkCall(void* code
, JmpSrc from
, void* to
)
769 patchPointerInternal(reinterpret_cast<intptr_t>(code
) + from
.m_offset
, to
);
772 static void relinkCall(void* from
, void* to
)
774 patchPointerInternal(reinterpret_cast<intptr_t>(from
) - sizeof(ARMWord
), to
);
777 // Address operations
779 static void* getRelocatedAddress(void* code
, JmpSrc jump
)
781 return reinterpret_cast<void*>(reinterpret_cast<ARMWord
*>(code
) + jump
.m_offset
/ sizeof(ARMWord
) + 1);
784 static void* getRelocatedAddress(void* code
, JmpDst label
)
786 return reinterpret_cast<void*>(reinterpret_cast<ARMWord
*>(code
) + label
.m_offset
/ sizeof(ARMWord
));
789 // Address differences
791 static int getDifferenceBetweenLabels(JmpDst from
, JmpSrc to
)
793 return (to
.m_offset
+ sizeof(ARMWord
)) - from
.m_offset
;
796 static int getDifferenceBetweenLabels(JmpDst from
, JmpDst to
)
798 return to
.m_offset
- from
.m_offset
;
801 static unsigned getCallReturnOffset(JmpSrc call
)
803 return call
.m_offset
+ sizeof(ARMWord
);
808 static ARMWord
getOp2Byte(ARMWord imm
)
811 return OP2_IMMh
| (imm
& 0x0f) | ((imm
& 0xf0) << 4) ;
814 static ARMWord
getOp2(ARMWord imm
);
816 #if WTF_ARM_ARCH_AT_LEAST(7)
817 static ARMWord
getImm16Op2(ARMWord imm
)
820 return (imm
& 0xf000) << 4 | (imm
& 0xfff);
824 ARMWord
getImm(ARMWord imm
, int tmpReg
, bool invert
= false);
825 void moveImm(ARMWord imm
, int dest
);
826 ARMWord
encodeComplexImm(ARMWord imm
, int dest
);
828 // Memory load/store helpers
830 void dataTransfer32(bool isLoad
, RegisterID srcDst
, RegisterID base
, int32_t offset
, bool bytes
= false);
831 void baseIndexTransfer32(bool isLoad
, RegisterID srcDst
, RegisterID base
, RegisterID index
, int scale
, int32_t offset
);
832 void doubleTransfer(bool isLoad
, FPRegisterID srcDst
, RegisterID base
, int32_t offset
);
834 // Constant pool hnadlers
836 static ARMWord
placeConstantPoolBarrier(int offset
)
838 offset
= (offset
- sizeof(ARMWord
)) >> 2;
839 ASSERT((offset
<= BOFFSET_MAX
&& offset
>= BOFFSET_MIN
));
840 return AL
| B
| (offset
& BRANCH_MASK
);
846 ASSERT(reg
<= ARMRegisters::pc
);
852 ASSERT(reg
<= ARMRegisters::pc
);
858 ASSERT(reg
<= ARMRegisters::pc
);
864 ASSERT(reg
<= ARMRegisters::pc
);
868 static ARMWord
getConditionalField(ARMWord i
)
870 return i
& 0xf0000000;
873 int genInt(int reg
, ARMWord imm
, bool positive
);
881 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
883 #endif // ARMAssembler_h