2 * Copyright (C) 2009 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 #include <wtf/Platform.h>
32 #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
34 #include "AssemblerBufferWithConstantPool.h"
35 #include <wtf/Assertions.h>
38 typedef uint32_t ARMWord
;
40 namespace ARMRegisters
{
73 } // namespace ARMRegisters
77 typedef ARMRegisters::RegisterID RegisterID
;
78 typedef ARMRegisters::FPRegisterID FPRegisterID
;
79 typedef AssemblerBufferWithConstantPool
<2048, 4, 4, ARMAssembler
> ARMBuffer
;
80 typedef SegmentedVector
<int, 64> Jumps
;
84 // ARM conditional constants
86 EQ
= 0x00000000, // Zero
87 NE
= 0x10000000, // Non-zero
103 // ARM instruction constants
141 #if WTF_ARM_ARCH_AT_LEAST(5)
145 #if WTF_ARM_ARCH_AT_LEAST(7)
153 OP2_IMMh
= (1 << 22),
154 OP2_INV_IMM
= (1 << 26),
156 OP2_OFSREG
= (1 << 25),
159 // This flag is inlcuded in LDR and STR
165 // Masks of ARM instructions
167 BRANCH_MASK
= 0x00ffffff,
169 SDT_MASK
= 0x0c000000,
170 SDT_OFFSET_MASK
= 0xfff,
174 BOFFSET_MIN
= -0x00800000,
175 BOFFSET_MAX
= 0x007fffff,
181 padForAlign16
= 0x0000,
182 padForAlign32
= 0xee120070,
185 static const ARMWord INVALID_IMM
= 0xf0000000;
186 static const int DefaultPrefetching
= 2;
189 friend class ARMAssembler
;
206 friend class ARMAssembler
;
214 bool isUsed() const { return m_used
; }
215 void used() { m_used
= true; }
221 ASSERT(m_offset
== offset
);
228 // Instruction formating
230 void emitInst(ARMWord op
, int rd
, int rn
, ARMWord op2
)
232 ASSERT ( ((op2
& ~OP2_IMM
) <= 0xfff) || (((op2
& ~OP2_IMMh
) <= 0xfff)) );
233 m_buffer
.putInt(op
| RN(rn
) | RD(rd
) | op2
);
236 void and_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
238 emitInst(static_cast<ARMWord
>(cc
) | AND
, rd
, rn
, op2
);
241 void ands_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
243 emitInst(static_cast<ARMWord
>(cc
) | AND
| SET_CC
, rd
, rn
, op2
);
246 void eor_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
248 emitInst(static_cast<ARMWord
>(cc
) | EOR
, rd
, rn
, op2
);
251 void eors_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
253 emitInst(static_cast<ARMWord
>(cc
) | EOR
| SET_CC
, rd
, rn
, op2
);
256 void sub_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
258 emitInst(static_cast<ARMWord
>(cc
) | SUB
, rd
, rn
, op2
);
261 void subs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
263 emitInst(static_cast<ARMWord
>(cc
) | SUB
| SET_CC
, rd
, rn
, op2
);
266 void rsb_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
268 emitInst(static_cast<ARMWord
>(cc
) | RSB
, rd
, rn
, op2
);
271 void rsbs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
273 emitInst(static_cast<ARMWord
>(cc
) | RSB
| SET_CC
, rd
, rn
, op2
);
276 void add_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
278 emitInst(static_cast<ARMWord
>(cc
) | ADD
, rd
, rn
, op2
);
281 void adds_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
283 emitInst(static_cast<ARMWord
>(cc
) | ADD
| SET_CC
, rd
, rn
, op2
);
286 void adc_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
288 emitInst(static_cast<ARMWord
>(cc
) | ADC
, rd
, rn
, op2
);
291 void adcs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
293 emitInst(static_cast<ARMWord
>(cc
) | ADC
| SET_CC
, rd
, rn
, op2
);
296 void sbc_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
298 emitInst(static_cast<ARMWord
>(cc
) | SBC
, rd
, rn
, op2
);
301 void sbcs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
303 emitInst(static_cast<ARMWord
>(cc
) | SBC
| SET_CC
, rd
, rn
, op2
);
306 void rsc_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
308 emitInst(static_cast<ARMWord
>(cc
) | RSC
, rd
, rn
, op2
);
311 void rscs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
313 emitInst(static_cast<ARMWord
>(cc
) | RSC
| SET_CC
, rd
, rn
, op2
);
316 void tst_r(int rn
, ARMWord op2
, Condition cc
= AL
)
318 emitInst(static_cast<ARMWord
>(cc
) | TST
| SET_CC
, 0, rn
, op2
);
321 void teq_r(int rn
, ARMWord op2
, Condition cc
= AL
)
323 emitInst(static_cast<ARMWord
>(cc
) | TEQ
| SET_CC
, 0, rn
, op2
);
326 void cmp_r(int rn
, ARMWord op2
, Condition cc
= AL
)
328 emitInst(static_cast<ARMWord
>(cc
) | CMP
| SET_CC
, 0, rn
, op2
);
331 void orr_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
333 emitInst(static_cast<ARMWord
>(cc
) | ORR
, rd
, rn
, op2
);
336 void orrs_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
338 emitInst(static_cast<ARMWord
>(cc
) | ORR
| SET_CC
, rd
, rn
, op2
);
341 void mov_r(int rd
, ARMWord op2
, Condition cc
= AL
)
343 emitInst(static_cast<ARMWord
>(cc
) | MOV
, rd
, ARMRegisters::r0
, op2
);
346 #if WTF_ARM_ARCH_AT_LEAST(7)
347 void movw_r(int rd
, ARMWord op2
, Condition cc
= AL
)
349 ASSERT((op2
| 0xf0fff) == 0xf0fff);
350 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MOVW
| RD(rd
) | op2
);
353 void movt_r(int rd
, ARMWord op2
, Condition cc
= AL
)
355 ASSERT((op2
| 0xf0fff) == 0xf0fff);
356 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MOVT
| RD(rd
) | op2
);
360 void movs_r(int rd
, ARMWord op2
, Condition cc
= AL
)
362 emitInst(static_cast<ARMWord
>(cc
) | MOV
| SET_CC
, rd
, ARMRegisters::r0
, op2
);
365 void bic_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
367 emitInst(static_cast<ARMWord
>(cc
) | BIC
, rd
, rn
, op2
);
370 void bics_r(int rd
, int rn
, ARMWord op2
, Condition cc
= AL
)
372 emitInst(static_cast<ARMWord
>(cc
) | BIC
| SET_CC
, rd
, rn
, op2
);
375 void mvn_r(int rd
, ARMWord op2
, Condition cc
= AL
)
377 emitInst(static_cast<ARMWord
>(cc
) | MVN
, rd
, ARMRegisters::r0
, op2
);
380 void mvns_r(int rd
, ARMWord op2
, Condition cc
= AL
)
382 emitInst(static_cast<ARMWord
>(cc
) | MVN
| SET_CC
, rd
, ARMRegisters::r0
, op2
);
385 void mul_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
387 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MUL
| RN(rd
) | RS(rn
) | RM(rm
));
390 void muls_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
392 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MUL
| SET_CC
| RN(rd
) | RS(rn
) | RM(rm
));
395 void mull_r(int rdhi
, int rdlo
, int rn
, int rm
, Condition cc
= AL
)
397 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | MULL
| RN(rdhi
) | RD(rdlo
) | RS(rn
) | RM(rm
));
400 void faddd_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
402 emitInst(static_cast<ARMWord
>(cc
) | FADDD
, dd
, dn
, dm
);
405 void fdivd_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
407 emitInst(static_cast<ARMWord
>(cc
) | FDIVD
, dd
, dn
, dm
);
410 void fsubd_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
412 emitInst(static_cast<ARMWord
>(cc
) | FSUBD
, dd
, dn
, dm
);
415 void fmuld_r(int dd
, int dn
, int dm
, Condition cc
= AL
)
417 emitInst(static_cast<ARMWord
>(cc
) | FMULD
, dd
, dn
, dm
);
420 void fcmpd_r(int dd
, int dm
, Condition cc
= AL
)
422 emitInst(static_cast<ARMWord
>(cc
) | FCMPD
, dd
, 0, dm
);
425 void ldr_imm(int rd
, ARMWord imm
, Condition cc
= AL
)
427 m_buffer
.putIntWithConstantInt(static_cast<ARMWord
>(cc
) | DTR
| DT_LOAD
| DT_UP
| RN(ARMRegisters::pc
) | RD(rd
), imm
, true);
430 void ldr_un_imm(int rd
, ARMWord imm
, Condition cc
= AL
)
432 m_buffer
.putIntWithConstantInt(static_cast<ARMWord
>(cc
) | DTR
| DT_LOAD
| DT_UP
| RN(ARMRegisters::pc
) | RD(rd
), imm
);
435 void dtr_u(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
437 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | DT_UP
, rd
, rb
, op2
);
440 void dtr_ur(bool isLoad
, int rd
, int rb
, int rm
, Condition cc
= AL
)
442 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | DT_UP
| OP2_OFSREG
, rd
, rb
, rm
);
445 void dtr_d(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
447 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
450 void dtr_dr(bool isLoad
, int rd
, int rb
, int rm
, Condition cc
= AL
)
452 emitInst(static_cast<ARMWord
>(cc
) | DTR
| (isLoad
? DT_LOAD
: 0) | OP2_OFSREG
, rd
, rb
, rm
);
455 void ldrh_r(int rd
, int rn
, int rm
, Condition cc
= AL
)
457 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rn
, rm
);
460 void ldrh_d(int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
462 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_PRE
, rd
, rb
, op2
);
465 void ldrh_u(int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
467 emitInst(static_cast<ARMWord
>(cc
) | LDRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rb
, op2
);
470 void strh_r(int rn
, int rm
, int rd
, Condition cc
= AL
)
472 emitInst(static_cast<ARMWord
>(cc
) | STRH
| HDT_UH
| DT_UP
| DT_PRE
, rd
, rn
, rm
);
475 void fdtr_u(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
478 emitInst(static_cast<ARMWord
>(cc
) | FDTR
| DT_UP
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
481 void fdtr_d(bool isLoad
, int rd
, int rb
, ARMWord op2
, Condition cc
= AL
)
484 emitInst(static_cast<ARMWord
>(cc
) | FDTR
| (isLoad
? DT_LOAD
: 0), rd
, rb
, op2
);
487 void push_r(int reg
, Condition cc
= AL
)
489 ASSERT(ARMWord(reg
) <= 0xf);
490 m_buffer
.putInt(cc
| DTR
| DT_WB
| RN(ARMRegisters::sp
) | RD(reg
) | 0x4);
493 void pop_r(int reg
, Condition cc
= AL
)
495 ASSERT(ARMWord(reg
) <= 0xf);
496 m_buffer
.putInt(cc
| (DTR
^ DT_PRE
) | DT_LOAD
| DT_UP
| RN(ARMRegisters::sp
) | RD(reg
) | 0x4);
499 inline void poke_r(int reg
, Condition cc
= AL
)
501 dtr_d(false, ARMRegisters::sp
, 0, reg
, cc
);
504 inline void peek_r(int reg
, Condition cc
= AL
)
506 dtr_u(true, reg
, ARMRegisters::sp
, 0, cc
);
509 void fmsr_r(int dd
, int rn
, Condition cc
= AL
)
511 emitInst(static_cast<ARMWord
>(cc
) | FMSR
, rn
, dd
, 0);
514 void fmrs_r(int rd
, int dn
, Condition cc
= AL
)
516 emitInst(static_cast<ARMWord
>(cc
) | FMRS
, rd
, dn
, 0);
519 void fsitod_r(int dd
, int dm
, Condition cc
= AL
)
521 emitInst(static_cast<ARMWord
>(cc
) | FSITOD
, dd
, 0, dm
);
524 void ftosid_r(int fd
, int dm
, Condition cc
= AL
)
526 emitInst(static_cast<ARMWord
>(cc
) | FTOSID
, fd
, 0, dm
);
529 void fmstat(Condition cc
= AL
)
531 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | FMSTAT
);
534 #if WTF_ARM_ARCH_AT_LEAST(5)
535 void clz_r(int rd
, int rm
, Condition cc
= AL
)
537 m_buffer
.putInt(static_cast<ARMWord
>(cc
) | CLZ
| RD(rd
) | RM(rm
));
541 void bkpt(ARMWord value
)
543 #if WTF_ARM_ARCH_AT_LEAST(5)
544 m_buffer
.putInt(BKPT
| ((value
& 0xff0) << 4) | (value
& 0xf));
546 // Cannot access to Zero memory address
547 dtr_dr(true, ARMRegisters::S0
, ARMRegisters::S0
, ARMRegisters::S0
);
551 static ARMWord
lsl(int reg
, ARMWord value
)
553 ASSERT(reg
<= ARMRegisters::pc
);
554 ASSERT(value
<= 0x1f);
555 return reg
| (value
<< 7) | 0x00;
558 static ARMWord
lsr(int reg
, ARMWord value
)
560 ASSERT(reg
<= ARMRegisters::pc
);
561 ASSERT(value
<= 0x1f);
562 return reg
| (value
<< 7) | 0x20;
565 static ARMWord
asr(int reg
, ARMWord value
)
567 ASSERT(reg
<= ARMRegisters::pc
);
568 ASSERT(value
<= 0x1f);
569 return reg
| (value
<< 7) | 0x40;
572 static ARMWord
lsl_r(int reg
, int shiftReg
)
574 ASSERT(reg
<= ARMRegisters::pc
);
575 ASSERT(shiftReg
<= ARMRegisters::pc
);
576 return reg
| (shiftReg
<< 8) | 0x10;
579 static ARMWord
lsr_r(int reg
, int shiftReg
)
581 ASSERT(reg
<= ARMRegisters::pc
);
582 ASSERT(shiftReg
<= ARMRegisters::pc
);
583 return reg
| (shiftReg
<< 8) | 0x30;
586 static ARMWord
asr_r(int reg
, int shiftReg
)
588 ASSERT(reg
<= ARMRegisters::pc
);
589 ASSERT(shiftReg
<= ARMRegisters::pc
);
590 return reg
| (shiftReg
<< 8) | 0x50;
597 return m_buffer
.size();
600 void ensureSpace(int insnSpace
, int constSpace
)
602 m_buffer
.ensureSpace(insnSpace
, constSpace
);
605 int sizeOfConstantPool()
607 return m_buffer
.sizeOfConstantPool();
612 return JmpDst(m_buffer
.size());
615 JmpDst
align(int alignment
)
617 while (!m_buffer
.isAligned(alignment
))
618 mov_r(ARMRegisters::r0
, ARMRegisters::r0
);
623 JmpSrc
jmp(Condition cc
= AL
, int useConstantPool
= 0)
625 ensureSpace(sizeof(ARMWord
), sizeof(ARMWord
));
626 int s
= m_buffer
.uncheckedSize();
627 ldr_un_imm(ARMRegisters::pc
, 0xffffffff, cc
);
628 m_jumps
.append(s
| (useConstantPool
& 0x1));
632 void* executableCopy(ExecutablePool
* allocator
);
636 static ARMWord
* getLdrImmAddress(ARMWord
* insn
)
638 // Must be an ldr ..., [pc +/- imm]
639 ASSERT((*insn
& 0x0f7f0000) == 0x051f0000);
641 ARMWord addr
= reinterpret_cast<ARMWord
>(insn
) + DefaultPrefetching
* sizeof(ARMWord
);
643 return reinterpret_cast<ARMWord
*>(addr
+ (*insn
& SDT_OFFSET_MASK
));
644 return reinterpret_cast<ARMWord
*>(addr
- (*insn
& SDT_OFFSET_MASK
));
647 static ARMWord
* getLdrImmAddressOnPool(ARMWord
* insn
, uint32_t* constPool
)
649 // Must be an ldr ..., [pc +/- imm]
650 ASSERT((*insn
& 0x0f7f0000) == 0x051f0000);
653 return reinterpret_cast<ARMWord
*>(constPool
+ ((*insn
& SDT_OFFSET_MASK
) >> 1));
654 return getLdrImmAddress(insn
);
657 static void patchPointerInternal(intptr_t from
, void* to
)
659 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(from
);
660 ARMWord
* addr
= getLdrImmAddress(insn
);
661 *addr
= reinterpret_cast<ARMWord
>(to
);
664 static ARMWord
patchConstantPoolLoad(ARMWord load
, ARMWord value
)
666 value
= (value
<< 1) + 1;
667 ASSERT(!(value
& ~0xfff));
668 return (load
& ~0xfff) | value
;
671 static void patchConstantPoolLoad(void* loadAddr
, void* constPoolAddr
);
675 static void linkPointer(void* code
, JmpDst from
, void* to
)
677 patchPointerInternal(reinterpret_cast<intptr_t>(code
) + from
.m_offset
, to
);
680 static void repatchInt32(void* from
, int32_t to
)
682 patchPointerInternal(reinterpret_cast<intptr_t>(from
), reinterpret_cast<void*>(to
));
685 static void repatchPointer(void* from
, void* to
)
687 patchPointerInternal(reinterpret_cast<intptr_t>(from
), to
);
690 static void repatchLoadPtrToLEA(void* from
)
692 // On arm, this is a patch from LDR to ADD. It is restricted conversion,
693 // from special case to special case, altough enough for its purpose
694 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(from
);
695 ASSERT((*insn
& 0x0ff00f00) == 0x05900000);
697 *insn
= (*insn
& 0xf00ff0ff) | 0x02800000;
698 ExecutableAllocator::cacheFlush(insn
, sizeof(ARMWord
));
703 void linkJump(JmpSrc from
, JmpDst to
)
705 ARMWord
* insn
= reinterpret_cast<ARMWord
*>(m_buffer
.data()) + (from
.m_offset
/ sizeof(ARMWord
));
706 ARMWord
* addr
= getLdrImmAddressOnPool(insn
, m_buffer
.poolAddress());
707 *addr
= static_cast<ARMWord
>(to
.m_offset
);
710 static void linkJump(void* code
, JmpSrc from
, void* to
)
712 patchPointerInternal(reinterpret_cast<intptr_t>(code
) + from
.m_offset
, to
);
715 static void relinkJump(void* from
, void* to
)
717 patchPointerInternal(reinterpret_cast<intptr_t>(from
) - sizeof(ARMWord
), to
);
720 static void linkCall(void* code
, JmpSrc from
, void* to
)
722 patchPointerInternal(reinterpret_cast<intptr_t>(code
) + from
.m_offset
, to
);
725 static void relinkCall(void* from
, void* to
)
727 patchPointerInternal(reinterpret_cast<intptr_t>(from
) - sizeof(ARMWord
), to
);
730 // Address operations
732 static void* getRelocatedAddress(void* code
, JmpSrc jump
)
734 return reinterpret_cast<void*>(reinterpret_cast<ARMWord
*>(code
) + jump
.m_offset
/ sizeof(ARMWord
) + 1);
737 static void* getRelocatedAddress(void* code
, JmpDst label
)
739 return reinterpret_cast<void*>(reinterpret_cast<ARMWord
*>(code
) + label
.m_offset
/ sizeof(ARMWord
));
742 // Address differences
744 static int getDifferenceBetweenLabels(JmpDst from
, JmpSrc to
)
746 return (to
.m_offset
+ sizeof(ARMWord
)) - from
.m_offset
;
749 static int getDifferenceBetweenLabels(JmpDst from
, JmpDst to
)
751 return to
.m_offset
- from
.m_offset
;
754 static unsigned getCallReturnOffset(JmpSrc call
)
756 return call
.m_offset
+ sizeof(ARMWord
);
761 static ARMWord
getOp2Byte(ARMWord imm
)
764 return OP2_IMMh
| (imm
& 0x0f) | ((imm
& 0xf0) << 4) ;
767 static ARMWord
getOp2(ARMWord imm
);
769 #if WTF_ARM_ARCH_AT_LEAST(7)
770 static ARMWord
getImm16Op2(ARMWord imm
)
773 return (imm
& 0xf000) << 4 | (imm
& 0xfff);
777 ARMWord
getImm(ARMWord imm
, int tmpReg
, bool invert
= false);
778 void moveImm(ARMWord imm
, int dest
);
779 ARMWord
encodeComplexImm(ARMWord imm
, int dest
);
781 // Memory load/store helpers
783 void dataTransfer32(bool isLoad
, RegisterID srcDst
, RegisterID base
, int32_t offset
);
784 void baseIndexTransfer32(bool isLoad
, RegisterID srcDst
, RegisterID base
, RegisterID index
, int scale
, int32_t offset
);
785 void doubleTransfer(bool isLoad
, FPRegisterID srcDst
, RegisterID base
, int32_t offset
);
787 // Constant pool hnadlers
789 static ARMWord
placeConstantPoolBarrier(int offset
)
791 offset
= (offset
- sizeof(ARMWord
)) >> 2;
792 ASSERT((offset
<= BOFFSET_MAX
&& offset
>= BOFFSET_MIN
));
793 return AL
| B
| (offset
& BRANCH_MASK
);
799 ASSERT(reg
<= ARMRegisters::pc
);
805 ASSERT(reg
<= ARMRegisters::pc
);
811 ASSERT(reg
<= ARMRegisters::pc
);
817 ASSERT(reg
<= ARMRegisters::pc
);
821 static ARMWord
getConditionalField(ARMWord i
)
823 return i
& 0xf0000000;
826 int genInt(int reg
, ARMWord imm
, bool positive
);
834 #endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
836 #endif // ARMAssembler_h