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 VCVTR_S32_F64
= 0x0ebd0bc0,
165 VMRS_APSR
= 0x0ef1fa10,
166 #if WTF_ARM_ARCH_AT_LEAST(5)
172 #if WTF_ARM_ARCH_AT_LEAST(7)
180 OP2_IMMh
= (1 << 22),
181 OP2_INV_IMM
= (1 << 26),
183 OP2_OFSREG
= (1 << 25),
187 // This flag is inlcuded in LDR and STR
193 // Masks of ARM instructions
195 BRANCH_MASK
= 0x00ffffff,
197 SDT_MASK
= 0x0c000000,
198 SDT_OFFSET_MASK
= 0xfff,
202 BOFFSET_MIN
= -0x00800000,
203 BOFFSET_MAX
= 0x007fffff,
209 padForAlign16
= 0x0000,
210 padForAlign32
= 0xe12fff7f // 'bkpt 0xffff' instruction.
213 static const ARMWord INVALID_IMM
= 0xf0000000;
214 static const ARMWord InvalidBranchTarget
= 0xffffffff;
215 static const int DefaultPrefetching
= 2;
217 // Instruction formating
219 void emitInst(ARMWord op
, int rd
, int rn
, ARMWord op2
)
221 ASSERT(((op2
& ~OP2_IMM
) <= 0xfff) || (((op2
& ~OP2_IMMh
) <= 0xfff)));
222 m_buffer
.putInt(op
| RN(rn
) | RD(rd
) | op2
);
225 void emitDoublePrecisionInst(ARMWord op
, int dd
, int dn
, int dm
)
227 ASSERT((dd
>= 0 && dd
<= 31) && (dn
>= 0 && dn
<= 31) && (dm
>= 0 && dm
<= 31));
228 m_buffer
.putInt(op
| ((dd
& 0xf) << 12) | ((dd
& 0x10) << (22 - 4))
229 | ((dn
& 0xf) << 16) | ((dn
& 0x10) << (7 - 4))
230 | (dm
& 0xf) | ((dm
& 0x10) << (5 - 4)));
233 void emitSinglePrecisionInst(ARMWord op
, int sd
, int sn
, int sm
)
235 ASSERT((sd
>= 0 && sd
<= 31) && (sn
>= 0 && sn
<= 31) && (sm
>= 0 && sm
<= 31));
236 m_buffer
.putInt(op
| ((sd
>> 1) << 12) | ((sd
& 0x1) << 22)
237 | ((sn
>> 1) << 16) | ((sn
& 0x1) << 7)
238 | (sm
>> 1) | ((sm
& 0x1) << 5));
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 cmn_r(int rn
, ARMWord op2
, Condition cc
= AL
)
338 emitInst(static_cast<ARMWord
>(cc
) | CMN
| SET_CC
, 0, rn
, op2
);
341 void orr_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
343 emitInst(static_cast<ARMWord
>(cc
) | ORR
, rd
, rn
, op2
);
346 void orrs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
348 emitInst(static_cast<ARMWord
>(cc
) | ORR
| SET_CC
, rd
, rn
, op2
);
351 void mov_r(int rd
, ARMWord op2
, Condition cc
= AL
)
353 emitInst(static_cast<ARMWord
>(cc
) | MOV
, rd
, ARMRegisters::r0
, op2
);
356 #if WTF_ARM_ARCH_AT_LEAST(7)
357 void movw_r(int rd
, ARMWord op2
, Condition cc
= AL
)
359 ASSERT((op2
| 0xf0fff) == 0xf0fff);
360 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MOVW
| RD(rd
) | op2
);
363 void movt_r(int rd
, ARMWord op2
, Condition cc
= AL
)
365 ASSERT((op2
| 0xf0fff) == 0xf0fff);
366 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MOVT
| RD(rd
) | op2
);
370 void movs_r(int rd
, ARMWord op2
, Condition cc
= AL
)
372 emitInst(static_cast<ARMWord
>(cc
) | MOV
| SET_CC
, rd
, ARMRegisters::r0
, op2
);
375 void bic_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
377 emitInst(static_cast<ARMWord
>(cc
) | BIC
, rd
, rn
, op2
);
380 void bics_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
382 emitInst(static_cast<ARMWord
>(cc
) | BIC
| SET_CC
, rd
, rn
, op2
);
385 void mvn_r(int rd
, ARMWord op2
, Condition cc
= AL
)
387 emitInst(static_cast<ARMWord
>(cc
) | MVN
, rd
, ARMRegisters::r0
, op2
);
390 void mvns_r(int rd
, ARMWord op2
, Condition cc
= AL
)
392 emitInst(static_cast<ARMWord
>(cc
) | MVN
| SET_CC
, rd
, ARMRegisters::r0
, op2
);
395 void mul_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
397 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MUL
| RN(rd
) | RS(rn
) | RM(rm
));
400 void muls_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
402 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MUL
| SET_CC
| RN(rd
) | RS(rn
) | RM(rm
));
405 void mull_r(int rdhi
, int rdlo
, int rn
, int rm
, Condition cc
= AL
)
407 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MULL
| RN(rdhi
) | RD(rdlo
) | RS(rn
) | RM(rm
));
410 void vadd_f64_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
412 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VADD_F64
, dd
, dn
, dm
);
415 void vdiv_f64_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
417 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VDIV_F64
, dd
, dn
, dm
);
420 void vsub_f64_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
422 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VSUB_F64
, dd
, dn
, dm
);
425 void vmul_f64_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
427 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VMUL_F64
, dd
, dn
, dm
);
430 void vcmp_f64_r(int dd
, int dm
, Condition cc
= AL
)
432 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VCMP_F64
, dd
, 0, dm
);
435 void vsqrt_f64_r(int dd
, int dm
, Condition cc
= AL
)
437 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VSQRT_F64
, dd
, 0, dm
);
440 void ldr_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
, true);
445 void ldr_un_imm(int rd
, ARMWord imm
, Condition cc
= AL
)
447 m_buffer
.putIntWithConstantInt(static_cast<ARMWord
>(cc
) | DTR
| DT_LOAD
| DT_UP
| RN(ARMRegisters::pc
) | RD(rd
), imm
);
450 void dtr_u(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
452 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | DT_UP
, rd
, rb
, op2
);
455 void dtr_ur(bool isLoad
, int rd
, int rb
, int rm
, Condition cc
= AL
)
457 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | DT_UP
| OP2_OFSREG
, rd
, rb
, rm
);
460 void dtr_d(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
462 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
465 void dtr_dr(bool isLoad
, int rd
, int rb
, int rm
, Condition cc
= AL
)
467 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | OP2_OFSREG
, rd
, rb
, rm
);
470 void ldrh_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
472 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rn
, rm
);
475 void ldrh_d(int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
477 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_PRE
, rd
, rb
, op2
);
480 void ldrh_u(int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
482 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rb
, op2
);
485 void strh_r(int rn
, int rm
, int rd
, Condition cc
= AL
)
487 emitInst(static_cast<ARMWord
>(cc
) | STRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rn
, rm
);
490 void fdtr_u(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
493 emitInst(static_cast<ARMWord
>(cc
) | FDTR
| DT_UP
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
496 void fdtr_d(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
499 emitInst(static_cast<ARMWord
>(cc
) | FDTR
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
502 void push_r(int reg
, Condition cc
= AL
)
504 ASSERT(ARMWord(reg
) <= 0xf);
505 m_buffer
.putInt(cc
| DTR
| DT_WB
| RN(ARMRegisters::sp
) | RD(reg
) | 0x4);
508 void pop_r(int reg
, Condition cc
= AL
)
510 ASSERT(ARMWord(reg
) <= 0xf);
511 m_buffer
.putInt(cc
| (DTR
^ DT_PRE
) | DT_LOAD
| DT_UP
| RN(ARMRegisters::sp
) | RD(reg
) | 0x4);
514 inline void poke_r(int reg
, Condition cc
= AL
)
516 dtr_d(false, ARMRegisters::sp
, 0, reg
, cc
);
519 inline void peek_r(int reg
, Condition cc
= AL
)
521 dtr_u(true, reg
, ARMRegisters::sp
, 0, cc
);
524 void vmov_vfp_r(int sn
, int rt
, Condition cc
= AL
)
527 emitSinglePrecisionInst(static_cast<ARMWord
>(cc
) | VMOV_VFP
, rt
<< 1, sn
, 0);
530 void vmov_arm_r(int rt
, int sn
, Condition cc
= AL
)
533 emitSinglePrecisionInst(static_cast<ARMWord
>(cc
) | VMOV_ARM
, rt
<< 1, sn
, 0);
536 void vcvt_f64_s32_r(int dd
, int sm
, Condition cc
= AL
)
538 ASSERT(!(sm
& 0x1)); // sm must be divisible by 2
539 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VCVT_F64_S32
, dd
, 0, (sm
>> 1));
542 void vcvt_s32_f64_r(int sd
, int dm
, Condition cc
= AL
)
544 ASSERT(!(sd
& 0x1)); // sd must be divisible by 2
545 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VCVT_S32_F64
, (sd
>> 1), 0, dm
);
548 void vcvtr_s32_f64_r(int sd
, int dm
, Condition cc
= AL
)
550 ASSERT(!(sd
& 0x1)); // sd must be divisible by 2
551 emitDoublePrecisionInst(static_cast<ARMWord
>(cc
) | VCVTR_S32_F64
, (sd
>> 1), 0, dm
);
554 void vmrs_apsr(Condition cc
= AL
)
556 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | VMRS_APSR
);
559 #if WTF_ARM_ARCH_AT_LEAST(5)
560 void clz_r(int rd
, int rm
, Condition cc
= AL
)
562 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | CLZ
| RD(rd
) | RM(rm
));
566 void bkpt(ARMWord value
)
568 #if WTF_ARM_ARCH_AT_LEAST(5)
569 m_buffer
.putInt(BKPT
| ((value
& 0xff0) << 4) | (value
& 0xf));
571 // Cannot access to Zero memory address
572 dtr_dr(true, ARMRegisters::S0
, ARMRegisters::S0
, ARMRegisters::S0
);
578 m_buffer
.putInt(OP_NOP_T2
);
581 void bx(int rm
, Condition cc
= AL
)
583 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
584 emitInst(static_cast<ARMWord
>(cc
) | BX
, 0, 0, RM(rm
));
586 mov_r(ARMRegisters::pc
, RM(rm
), cc
);
590 AssemblerLabel
blx(int rm
, Condition cc
= AL
)
592 #if WTF_ARM_ARCH_AT_LEAST(5)
593 emitInst(static_cast<ARMWord
>(cc
) | BLX
, 0, 0, RM(rm
));
596 ensureSpace(2 * sizeof(ARMWord
), 0);
597 mov_r(ARMRegisters::lr
, ARMRegisters::pc
, cc
);
600 return m_buffer
.label();
603 static ARMWord
lsl(int reg
, ARMWord value
)
605 ASSERT(reg
<= ARMRegisters::pc
);
606 ASSERT(value
<= 0x1f);
607 return reg
| (value
<< 7) | 0x00;
610 static ARMWord
lsr(int reg
, ARMWord value
)
612 ASSERT(reg
<= ARMRegisters::pc
);
613 ASSERT(value
<= 0x1f);
614 return reg
| (value
<< 7) | 0x20;
617 static ARMWord
asr(int reg
, ARMWord value
)
619 ASSERT(reg
<= ARMRegisters::pc
);
620 ASSERT(value
<= 0x1f);
621 return reg
| (value
<< 7) | 0x40;
624 static ARMWord
lsl_r(int reg
, int shiftReg
)
626 ASSERT(reg
<= ARMRegisters::pc
);
627 ASSERT(shiftReg
<= ARMRegisters::pc
);
628 return reg
| (shiftReg
<< 8) | 0x10;
631 static ARMWord
lsr_r(int reg
, int shiftReg
)
633 ASSERT(reg
<= ARMRegisters::pc
);
634 ASSERT(shiftReg
<= ARMRegisters::pc
);
635 return reg
| (shiftReg
<< 8) | 0x30;
638 static ARMWord
asr_r(int reg
, int shiftReg
)
640 ASSERT(reg
<= ARMRegisters::pc
);
641 ASSERT(shiftReg
<= ARMRegisters::pc
);
642 return reg
| (shiftReg
<< 8) | 0x50;
647 size_t codeSize() const
649 return m_buffer
.codeSize();
652 void ensureSpace(int insnSpace
, int constSpace
)
654 m_buffer
.ensureSpace(insnSpace
, constSpace
);
657 int sizeOfConstantPool()
659 return m_buffer
.sizeOfConstantPool();
662 AssemblerLabel
label()
664 m_buffer
.ensureSpaceForAnyOneInstruction();
665 return m_buffer
.label();
668 AssemblerLabel
align(int alignment
)
670 while (!m_buffer
.isAligned(alignment
))
671 mov_r(ARMRegisters::r0
, ARMRegisters::r0
);
676 AssemblerLabel
loadBranchTarget(int rd
, Condition cc
= AL
, int useConstantPool
= 0)
678 ensureSpace(sizeof(ARMWord
), sizeof(ARMWord
));
679 m_jumps
.append(m_buffer
.codeSize() | (useConstantPool
& 0x1));
680 ldr_un_imm(rd
, InvalidBranchTarget
, cc
);
681 return m_buffer
.label();
684 AssemblerLabel
jmp(Condition cc
= AL
, int useConstantPool
= 0)
686 return loadBranchTarget(ARMRegisters::pc
, cc
, useConstantPool
);
689 void* executableCopy(JSGlobalData
&, ExecutablePool
* allocator
);
692 unsigned debugOffset() { return m_buffer
.debugOffset(); }
697 static ARMWord
* getLdrImmAddress(ARMWord
* insn
)
699 #if WTF_ARM_ARCH_AT_LEAST(5)
701 if ((*insn
& 0x0f7f0000) != 0x051f0000) {
703 ASSERT((*insn
& 0x012fff30) == 0x012fff30);
707 // Must be an ldr ..., [pc +/- imm]
708 ASSERT((*insn
& 0x0f7f0000) == 0x051f0000);
710 ARMWord addr
= reinterpret_cast<ARMWord
>(insn
) + DefaultPrefetching
* sizeof(ARMWord
);
712 return reinterpret_cast<ARMWord
*>(addr
+ (*insn
& SDT_OFFSET_MASK
));
713 return reinterpret_cast<ARMWord
*>(addr
- (*insn
& SDT_OFFSET_MASK
));
716 static ARMWord
* getLdrImmAddressOnPool(ARMWord
* insn
, uint32_t* constPool
)
718 // Must be an ldr ..., [pc +/- imm]
719 ASSERT((*insn
& 0x0f7f0000) == 0x051f0000);
722 return reinterpret_cast<ARMWord
*>(constPool
+ ((*insn
& SDT_OFFSET_MASK
) >> 1));
723 return getLdrImmAddress(insn
);
726 static void patchPointerInternal(intptr_t from
, void* to
)
728 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(from
);
729 ARMWord
* addr
= getLdrImmAddress(insn
);
730 *addr
= reinterpret_cast<ARMWord
>(to
);
733 static ARMWord
patchConstantPoolLoad(ARMWord load
, ARMWord value
)
735 value
= (value
<< 1) + 1;
736 ASSERT(!(value
& ~0xfff));
737 return (load
& ~0xfff) | value
;
740 static void patchConstantPoolLoad(void* loadAddr
, void* constPoolAddr
);
743 static void* readPointer(void* from
)
745 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(from
);
746 void* addr
= reinterpret_cast<void*>(getLdrImmAddress(insn
));
752 static void linkPointer(void* code
, AssemblerLabel from
, void* to
)
754 patchPointerInternal(reinterpret_cast<intptr_t>(code
) + from
.m_offset
, to
);
757 static void repatchInt32(void* from
, int32_t to
)
759 patchPointerInternal(reinterpret_cast<intptr_t>(from
), reinterpret_cast<void*>(to
));
762 static void repatchCompact(void* where
, int32_t value
)
764 repatchInt32(where
, value
);
767 static void repatchPointer(void* from
, void* to
)
769 patchPointerInternal(reinterpret_cast<intptr_t>(from
), to
);
773 static intptr_t getAbsoluteJumpAddress(void* base
, int offset
= 0)
775 return reinterpret_cast<intptr_t>(base
) + offset
- sizeof(ARMWord
);
778 void linkJump(AssemblerLabel from
, AssemblerLabel to
)
780 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(getAbsoluteJumpAddress(m_buffer
.data(), from
.m_offset
));
781 ARMWord
* addr
= getLdrImmAddressOnPool(insn
, m_buffer
.poolAddress());
782 *addr
= static_cast<ARMWord
>(to
.m_offset
);
785 static void linkJump(void* code
, AssemblerLabel from
, void* to
)
787 patchPointerInternal(getAbsoluteJumpAddress(code
, from
.m_offset
), to
);
790 static void relinkJump(void* from
, void* to
)
792 patchPointerInternal(getAbsoluteJumpAddress(from
), to
);
795 static void linkCall(void* code
, AssemblerLabel from
, void* to
)
797 patchPointerInternal(getAbsoluteJumpAddress(code
, from
.m_offset
), to
);
800 static void relinkCall(void* from
, void* to
)
802 patchPointerInternal(getAbsoluteJumpAddress(from
), to
);
805 // Address operations
807 static void* getRelocatedAddress(void* code
, AssemblerLabel label
)
809 return reinterpret_cast<void*>(reinterpret_cast<char*>(code
) + label
.m_offset
);
812 // Address differences
814 static int getDifferenceBetweenLabels(AssemblerLabel a
, AssemblerLabel b
)
816 return b
.m_offset
- a
.m_offset
;
819 static unsigned getCallReturnOffset(AssemblerLabel call
)
821 return call
.m_offset
;
826 static ARMWord
getOp2Byte(ARMWord imm
)
829 return OP2_IMMh
| (imm
& 0x0f) | ((imm
& 0xf0) << 4) ;
832 static ARMWord
getOp2(ARMWord imm
);
834 #if WTF_ARM_ARCH_AT_LEAST(7)
835 static ARMWord
getImm16Op2(ARMWord imm
)
838 return (imm
& 0xf000) << 4 | (imm
& 0xfff);
842 ARMWord
getImm(ARMWord imm
, int tmpReg
, bool invert
= false);
843 void moveImm(ARMWord imm
, int dest
);
844 ARMWord
encodeComplexImm(ARMWord imm
, int dest
);
846 ARMWord
getOffsetForHalfwordDataTransfer(ARMWord imm
, int tmpReg
)
848 // Encode immediate data in the instruction if it is possible
850 return getOp2Byte(imm
);
851 // Otherwise, store the data in a temporary register
852 return encodeComplexImm(imm
, tmpReg
);
855 // Memory load/store helpers
857 void dataTransfer32(bool isLoad
, RegisterID srcDst
, RegisterID base
, int32_t offset
, bool bytes
= false);
858 void baseIndexTransfer32(bool isLoad
, RegisterID srcDst
, RegisterID base
, RegisterID index
, int scale
, int32_t offset
);
859 void doubleTransfer(bool isLoad
, FPRegisterID srcDst
, RegisterID base
, int32_t offset
);
861 // Constant pool hnadlers
863 static ARMWord
placeConstantPoolBarrier(int offset
)
865 offset
= (offset
- sizeof(ARMWord
)) >> 2;
866 ASSERT((offset
<= BOFFSET_MAX
&& offset
>= BOFFSET_MIN
));
867 return AL
| B
| (offset
& BRANCH_MASK
);
873 ASSERT(reg
<= ARMRegisters::pc
);
879 ASSERT(reg
<= ARMRegisters::pc
);
885 ASSERT(reg
<= ARMRegisters::pc
);
891 ASSERT(reg
<= ARMRegisters::pc
);
895 static ARMWord
getConditionalField(ARMWord i
)
897 return i
& 0xf0000000;
900 int genInt(int reg
, ARMWord imm
, bool positive
);
908 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
910 #endif // ARMAssembler_h