2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Andrzej Zaborowski
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "tcg-pool.inc.c"
28 int arm_arch
= __ARM_ARCH
;
30 #ifndef use_idiv_instructions
31 bool use_idiv_instructions
;
34 /* ??? Ought to think about changing CONFIG_SOFTMMU to always defined. */
36 # define USING_SOFTMMU 1
38 # define USING_SOFTMMU 0
41 #ifdef CONFIG_DEBUG_TCG
42 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
62 static const int tcg_target_reg_alloc_order
[] = {
80 static const int tcg_target_call_iarg_regs
[4] = {
81 TCG_REG_R0
, TCG_REG_R1
, TCG_REG_R2
, TCG_REG_R3
83 static const int tcg_target_call_oarg_regs
[2] = {
84 TCG_REG_R0
, TCG_REG_R1
87 #define TCG_REG_TMP TCG_REG_R12
89 enum arm_cond_code_e
{
92 COND_CS
= 0x2, /* Unsigned greater or equal */
93 COND_CC
= 0x3, /* Unsigned less than */
94 COND_MI
= 0x4, /* Negative */
95 COND_PL
= 0x5, /* Zero or greater */
96 COND_VS
= 0x6, /* Overflow */
97 COND_VC
= 0x7, /* No overflow */
98 COND_HI
= 0x8, /* Unsigned greater than */
99 COND_LS
= 0x9, /* Unsigned less or equal */
107 #define TO_CPSR (1 << 20)
109 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
110 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
111 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
112 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
113 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
114 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
115 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
116 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
119 ARITH_AND
= 0x0 << 21,
120 ARITH_EOR
= 0x1 << 21,
121 ARITH_SUB
= 0x2 << 21,
122 ARITH_RSB
= 0x3 << 21,
123 ARITH_ADD
= 0x4 << 21,
124 ARITH_ADC
= 0x5 << 21,
125 ARITH_SBC
= 0x6 << 21,
126 ARITH_RSC
= 0x7 << 21,
127 ARITH_TST
= 0x8 << 21 | TO_CPSR
,
128 ARITH_CMP
= 0xa << 21 | TO_CPSR
,
129 ARITH_CMN
= 0xb << 21 | TO_CPSR
,
130 ARITH_ORR
= 0xc << 21,
131 ARITH_MOV
= 0xd << 21,
132 ARITH_BIC
= 0xe << 21,
133 ARITH_MVN
= 0xf << 21,
135 INSN_CLZ
= 0x016f0f10,
136 INSN_RBIT
= 0x06ff0f30,
138 INSN_LDR_IMM
= 0x04100000,
139 INSN_LDR_REG
= 0x06100000,
140 INSN_STR_IMM
= 0x04000000,
141 INSN_STR_REG
= 0x06000000,
143 INSN_LDRH_IMM
= 0x005000b0,
144 INSN_LDRH_REG
= 0x001000b0,
145 INSN_LDRSH_IMM
= 0x005000f0,
146 INSN_LDRSH_REG
= 0x001000f0,
147 INSN_STRH_IMM
= 0x004000b0,
148 INSN_STRH_REG
= 0x000000b0,
150 INSN_LDRB_IMM
= 0x04500000,
151 INSN_LDRB_REG
= 0x06500000,
152 INSN_LDRSB_IMM
= 0x005000d0,
153 INSN_LDRSB_REG
= 0x001000d0,
154 INSN_STRB_IMM
= 0x04400000,
155 INSN_STRB_REG
= 0x06400000,
157 INSN_LDRD_IMM
= 0x004000d0,
158 INSN_LDRD_REG
= 0x000000d0,
159 INSN_STRD_IMM
= 0x004000f0,
160 INSN_STRD_REG
= 0x000000f0,
162 INSN_DMB_ISH
= 0xf57ff05b,
163 INSN_DMB_MCR
= 0xee070fba,
165 /* Architected nop introduced in v6k. */
166 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
167 also Just So Happened to do nothing on pre-v6k so that we
168 don't need to conditionalize it? */
169 INSN_NOP_v6k
= 0xe320f000,
170 /* Otherwise the assembler uses mov r0,r0 */
171 INSN_NOP_v4
= (COND_AL
<< 28) | ARITH_MOV
,
174 #define INSN_NOP (use_armv7_instructions ? INSN_NOP_v6k : INSN_NOP_v4)
176 static const uint8_t tcg_cond_to_arm_cond
[] = {
177 [TCG_COND_EQ
] = COND_EQ
,
178 [TCG_COND_NE
] = COND_NE
,
179 [TCG_COND_LT
] = COND_LT
,
180 [TCG_COND_GE
] = COND_GE
,
181 [TCG_COND_LE
] = COND_LE
,
182 [TCG_COND_GT
] = COND_GT
,
184 [TCG_COND_LTU
] = COND_CC
,
185 [TCG_COND_GEU
] = COND_CS
,
186 [TCG_COND_LEU
] = COND_LS
,
187 [TCG_COND_GTU
] = COND_HI
,
190 static inline void reloc_pc24(tcg_insn_unit
*code_ptr
, tcg_insn_unit
*target
)
192 ptrdiff_t offset
= (tcg_ptr_byte_diff(target
, code_ptr
) - 8) >> 2;
193 *code_ptr
= (*code_ptr
& ~0xffffff) | (offset
& 0xffffff);
196 static inline void reloc_pc24_atomic(tcg_insn_unit
*code_ptr
, tcg_insn_unit
*target
)
198 ptrdiff_t offset
= (tcg_ptr_byte_diff(target
, code_ptr
) - 8) >> 2;
199 tcg_insn_unit insn
= atomic_read(code_ptr
);
200 tcg_debug_assert(offset
== sextract32(offset
, 0, 24));
201 atomic_set(code_ptr
, deposit32(insn
, 0, 24, offset
));
204 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
205 intptr_t value
, intptr_t addend
)
207 tcg_debug_assert(addend
== 0);
209 if (type
== R_ARM_PC24
) {
210 reloc_pc24(code_ptr
, (tcg_insn_unit
*)value
);
211 } else if (type
== R_ARM_PC13
) {
212 intptr_t diff
= value
- (uintptr_t)(code_ptr
+ 2);
213 tcg_insn_unit insn
= *code_ptr
;
216 if (diff
>= -0xfff && diff
<= 0xfff) {
222 int rd
= extract32(insn
, 12, 4);
223 int rt
= rd
== TCG_REG_PC
? TCG_REG_TMP
: rd
;
224 assert(diff
>= 0x1000 && diff
< 0x100000);
225 /* add rt, pc, #high */
226 *code_ptr
++ = ((insn
& 0xf0000000) | (1 << 25) | ARITH_ADD
227 | (TCG_REG_PC
<< 16) | (rt
<< 12)
228 | (20 << 7) | (diff
>> 12));
229 /* ldr rd, [rt, #low] */
230 insn
= deposit32(insn
, 12, 4, rt
);
234 insn
= deposit32(insn
, 23, 1, u
);
235 insn
= deposit32(insn
, 0, 12, diff
);
238 g_assert_not_reached();
242 #define TCG_CT_CONST_ARM 0x100
243 #define TCG_CT_CONST_INV 0x200
244 #define TCG_CT_CONST_NEG 0x400
245 #define TCG_CT_CONST_ZERO 0x800
247 /* parse target specific constraints */
248 static const char *target_parse_constraint(TCGArgConstraint
*ct
,
249 const char *ct_str
, TCGType type
)
253 ct
->ct
|= TCG_CT_CONST_ARM
;
256 ct
->ct
|= TCG_CT_CONST_INV
;
258 case 'N': /* The gcc constraint letter is L, already used here. */
259 ct
->ct
|= TCG_CT_CONST_NEG
;
262 ct
->ct
|= TCG_CT_CONST_ZERO
;
266 ct
->ct
|= TCG_CT_REG
;
270 /* qemu_ld address */
272 ct
->ct
|= TCG_CT_REG
;
274 #ifdef CONFIG_SOFTMMU
275 /* r0-r2,lr will be overwritten when reading the tlb entry,
276 so don't use these. */
277 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
278 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
279 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
280 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R14
);
284 /* qemu_st address & data */
286 ct
->ct
|= TCG_CT_REG
;
288 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
289 and r0-r1 doing the byte swapping, so don't use these. */
290 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
291 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
292 #if defined(CONFIG_SOFTMMU)
293 /* Avoid clashes with registers being used for helper args */
294 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
295 #if TARGET_LONG_BITS == 64
296 /* Avoid clashes with registers being used for helper args */
297 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R3
);
299 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R14
);
309 static inline uint32_t rotl(uint32_t val
, int n
)
311 return (val
<< n
) | (val
>> (32 - n
));
314 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
315 right-rotated by an even amount between 0 and 30. */
316 static inline int encode_imm(uint32_t imm
)
320 /* simple case, only lower bits */
321 if ((imm
& ~0xff) == 0)
323 /* then try a simple even shift */
324 shift
= ctz32(imm
) & ~1;
325 if (((imm
>> shift
) & ~0xff) == 0)
327 /* now try harder with rotations */
328 if ((rotl(imm
, 2) & ~0xff) == 0)
330 if ((rotl(imm
, 4) & ~0xff) == 0)
332 if ((rotl(imm
, 6) & ~0xff) == 0)
334 /* imm can't be encoded */
338 static inline int check_fit_imm(uint32_t imm
)
340 return encode_imm(imm
) >= 0;
343 /* Test if a constant matches the constraint.
344 * TODO: define constraints for:
346 * ldr/str offset: between -0xfff and 0xfff
347 * ldrh/strh offset: between -0xff and 0xff
348 * mov operand2: values represented with x << (2 * y), x < 0x100
349 * add, sub, eor...: ditto
351 static inline int tcg_target_const_match(tcg_target_long val
, TCGType type
,
352 const TCGArgConstraint
*arg_ct
)
356 if (ct
& TCG_CT_CONST
) {
358 } else if ((ct
& TCG_CT_CONST_ARM
) && check_fit_imm(val
)) {
360 } else if ((ct
& TCG_CT_CONST_INV
) && check_fit_imm(~val
)) {
362 } else if ((ct
& TCG_CT_CONST_NEG
) && check_fit_imm(-val
)) {
364 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
371 static inline void tcg_out_b(TCGContext
*s
, int cond
, int32_t offset
)
373 tcg_out32(s
, (cond
<< 28) | 0x0a000000 |
374 (((offset
- 8) >> 2) & 0x00ffffff));
377 static inline void tcg_out_b_noaddr(TCGContext
*s
, int cond
)
379 /* We pay attention here to not modify the branch target by masking
380 the corresponding bytes. This ensure that caches and memory are
381 kept coherent during retranslation. */
382 tcg_out32(s
, deposit32(*s
->code_ptr
, 24, 8, (cond
<< 4) | 0x0a));
385 static inline void tcg_out_bl_noaddr(TCGContext
*s
, int cond
)
387 /* We pay attention here to not modify the branch target by masking
388 the corresponding bytes. This ensure that caches and memory are
389 kept coherent during retranslation. */
390 tcg_out32(s
, deposit32(*s
->code_ptr
, 24, 8, (cond
<< 4) | 0x0b));
393 static inline void tcg_out_bl(TCGContext
*s
, int cond
, int32_t offset
)
395 tcg_out32(s
, (cond
<< 28) | 0x0b000000 |
396 (((offset
- 8) >> 2) & 0x00ffffff));
399 static inline void tcg_out_blx(TCGContext
*s
, int cond
, int rn
)
401 tcg_out32(s
, (cond
<< 28) | 0x012fff30 | rn
);
404 static inline void tcg_out_blx_imm(TCGContext
*s
, int32_t offset
)
406 tcg_out32(s
, 0xfa000000 | ((offset
& 2) << 23) |
407 (((offset
- 8) >> 2) & 0x00ffffff));
410 static inline void tcg_out_dat_reg(TCGContext
*s
,
411 int cond
, int opc
, int rd
, int rn
, int rm
, int shift
)
413 tcg_out32(s
, (cond
<< 28) | (0 << 25) | opc
|
414 (rn
<< 16) | (rd
<< 12) | shift
| rm
);
417 static inline void tcg_out_nop(TCGContext
*s
)
419 tcg_out32(s
, INSN_NOP
);
422 static inline void tcg_out_mov_reg(TCGContext
*s
, int cond
, int rd
, int rm
)
424 /* Simple reg-reg move, optimising out the 'do nothing' case */
426 tcg_out_dat_reg(s
, cond
, ARITH_MOV
, rd
, 0, rm
, SHIFT_IMM_LSL(0));
430 static inline void tcg_out_bx(TCGContext
*s
, int cond
, TCGReg rn
)
432 /* Unless the C portion of QEMU is compiled as thumb, we don't
433 actually need true BX semantics; merely a branch to an address
434 held in a register. */
435 if (use_armv5t_instructions
) {
436 tcg_out32(s
, (cond
<< 28) | 0x012fff10 | rn
);
438 tcg_out_mov_reg(s
, cond
, TCG_REG_PC
, rn
);
442 static inline void tcg_out_dat_imm(TCGContext
*s
,
443 int cond
, int opc
, int rd
, int rn
, int im
)
445 tcg_out32(s
, (cond
<< 28) | (1 << 25) | opc
|
446 (rn
<< 16) | (rd
<< 12) | im
);
449 /* Note that this routine is used for both LDR and LDRH formats, so we do
450 not wish to include an immediate shift at this point. */
451 static void tcg_out_memop_r(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
452 TCGReg rn
, TCGReg rm
, bool u
, bool p
, bool w
)
454 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24)
455 | (w
<< 21) | (rn
<< 16) | (rt
<< 12) | rm
);
458 static void tcg_out_memop_8(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
459 TCGReg rn
, int imm8
, bool p
, bool w
)
466 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
467 (rn
<< 16) | (rt
<< 12) | ((imm8
& 0xf0) << 4) | (imm8
& 0xf));
470 static void tcg_out_memop_12(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
471 TCGReg rn
, int imm12
, bool p
, bool w
)
478 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
479 (rn
<< 16) | (rt
<< 12) | imm12
);
482 static inline void tcg_out_ld32_12(TCGContext
*s
, int cond
, TCGReg rt
,
483 TCGReg rn
, int imm12
)
485 tcg_out_memop_12(s
, cond
, INSN_LDR_IMM
, rt
, rn
, imm12
, 1, 0);
488 static inline void tcg_out_st32_12(TCGContext
*s
, int cond
, TCGReg rt
,
489 TCGReg rn
, int imm12
)
491 tcg_out_memop_12(s
, cond
, INSN_STR_IMM
, rt
, rn
, imm12
, 1, 0);
494 static inline void tcg_out_ld32_r(TCGContext
*s
, int cond
, TCGReg rt
,
495 TCGReg rn
, TCGReg rm
)
497 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 0);
500 static inline void tcg_out_st32_r(TCGContext
*s
, int cond
, TCGReg rt
,
501 TCGReg rn
, TCGReg rm
)
503 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 0);
506 static inline void tcg_out_ldrd_8(TCGContext
*s
, int cond
, TCGReg rt
,
509 tcg_out_memop_8(s
, cond
, INSN_LDRD_IMM
, rt
, rn
, imm8
, 1, 0);
512 static inline void tcg_out_ldrd_r(TCGContext
*s
, int cond
, TCGReg rt
,
513 TCGReg rn
, TCGReg rm
)
515 tcg_out_memop_r(s
, cond
, INSN_LDRD_REG
, rt
, rn
, rm
, 1, 1, 0);
518 static inline void tcg_out_strd_8(TCGContext
*s
, int cond
, TCGReg rt
,
521 tcg_out_memop_8(s
, cond
, INSN_STRD_IMM
, rt
, rn
, imm8
, 1, 0);
524 static inline void tcg_out_strd_r(TCGContext
*s
, int cond
, TCGReg rt
,
525 TCGReg rn
, TCGReg rm
)
527 tcg_out_memop_r(s
, cond
, INSN_STRD_REG
, rt
, rn
, rm
, 1, 1, 0);
530 /* Register pre-increment with base writeback. */
531 static inline void tcg_out_ld32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
532 TCGReg rn
, TCGReg rm
)
534 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 1);
537 static inline void tcg_out_st32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
538 TCGReg rn
, TCGReg rm
)
540 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 1);
543 static inline void tcg_out_ld16u_8(TCGContext
*s
, int cond
, TCGReg rt
,
546 tcg_out_memop_8(s
, cond
, INSN_LDRH_IMM
, rt
, rn
, imm8
, 1, 0);
549 static inline void tcg_out_st16_8(TCGContext
*s
, int cond
, TCGReg rt
,
552 tcg_out_memop_8(s
, cond
, INSN_STRH_IMM
, rt
, rn
, imm8
, 1, 0);
555 static inline void tcg_out_ld16u_r(TCGContext
*s
, int cond
, TCGReg rt
,
556 TCGReg rn
, TCGReg rm
)
558 tcg_out_memop_r(s
, cond
, INSN_LDRH_REG
, rt
, rn
, rm
, 1, 1, 0);
561 static inline void tcg_out_st16_r(TCGContext
*s
, int cond
, TCGReg rt
,
562 TCGReg rn
, TCGReg rm
)
564 tcg_out_memop_r(s
, cond
, INSN_STRH_REG
, rt
, rn
, rm
, 1, 1, 0);
567 static inline void tcg_out_ld16s_8(TCGContext
*s
, int cond
, TCGReg rt
,
570 tcg_out_memop_8(s
, cond
, INSN_LDRSH_IMM
, rt
, rn
, imm8
, 1, 0);
573 static inline void tcg_out_ld16s_r(TCGContext
*s
, int cond
, TCGReg rt
,
574 TCGReg rn
, TCGReg rm
)
576 tcg_out_memop_r(s
, cond
, INSN_LDRSH_REG
, rt
, rn
, rm
, 1, 1, 0);
579 static inline void tcg_out_ld8_12(TCGContext
*s
, int cond
, TCGReg rt
,
580 TCGReg rn
, int imm12
)
582 tcg_out_memop_12(s
, cond
, INSN_LDRB_IMM
, rt
, rn
, imm12
, 1, 0);
585 static inline void tcg_out_st8_12(TCGContext
*s
, int cond
, TCGReg rt
,
586 TCGReg rn
, int imm12
)
588 tcg_out_memop_12(s
, cond
, INSN_STRB_IMM
, rt
, rn
, imm12
, 1, 0);
591 static inline void tcg_out_ld8_r(TCGContext
*s
, int cond
, TCGReg rt
,
592 TCGReg rn
, TCGReg rm
)
594 tcg_out_memop_r(s
, cond
, INSN_LDRB_REG
, rt
, rn
, rm
, 1, 1, 0);
597 static inline void tcg_out_st8_r(TCGContext
*s
, int cond
, TCGReg rt
,
598 TCGReg rn
, TCGReg rm
)
600 tcg_out_memop_r(s
, cond
, INSN_STRB_REG
, rt
, rn
, rm
, 1, 1, 0);
603 static inline void tcg_out_ld8s_8(TCGContext
*s
, int cond
, TCGReg rt
,
606 tcg_out_memop_8(s
, cond
, INSN_LDRSB_IMM
, rt
, rn
, imm8
, 1, 0);
609 static inline void tcg_out_ld8s_r(TCGContext
*s
, int cond
, TCGReg rt
,
610 TCGReg rn
, TCGReg rm
)
612 tcg_out_memop_r(s
, cond
, INSN_LDRSB_REG
, rt
, rn
, rm
, 1, 1, 0);
615 static void tcg_out_movi_pool(TCGContext
*s
, int cond
, int rd
, uint32_t arg
)
617 /* The 12-bit range on the ldr insn is sometimes a bit too small.
618 In order to get around that we require two insns, one of which
619 will usually be a nop, but may be replaced in patch_reloc. */
620 new_pool_label(s
, arg
, R_ARM_PC13
, s
->code_ptr
, 0);
621 tcg_out_ld32_12(s
, cond
, rd
, TCG_REG_PC
, 0);
625 static void tcg_out_movi32(TCGContext
*s
, int cond
, int rd
, uint32_t arg
)
627 int rot
, diff
, opc
, sh1
, sh2
;
628 uint32_t tt0
, tt1
, tt2
;
630 /* Check a single MOV/MVN before anything else. */
631 rot
= encode_imm(arg
);
633 tcg_out_dat_imm(s
, cond
, ARITH_MOV
, rd
, 0,
634 rotl(arg
, rot
) | (rot
<< 7));
637 rot
= encode_imm(~arg
);
639 tcg_out_dat_imm(s
, cond
, ARITH_MVN
, rd
, 0,
640 rotl(~arg
, rot
) | (rot
<< 7));
644 /* Check for a pc-relative address. This will usually be the TB,
645 or within the TB, which is immediately before the code block. */
646 diff
= arg
- ((intptr_t)s
->code_ptr
+ 8);
648 rot
= encode_imm(diff
);
650 tcg_out_dat_imm(s
, cond
, ARITH_ADD
, rd
, TCG_REG_PC
,
651 rotl(diff
, rot
) | (rot
<< 7));
655 rot
= encode_imm(-diff
);
657 tcg_out_dat_imm(s
, cond
, ARITH_SUB
, rd
, TCG_REG_PC
,
658 rotl(-diff
, rot
) | (rot
<< 7));
663 /* Use movw + movt. */
664 if (use_armv7_instructions
) {
666 tcg_out32(s
, (cond
<< 28) | 0x03000000 | (rd
<< 12)
667 | ((arg
<< 4) & 0x000f0000) | (arg
& 0xfff));
668 if (arg
& 0xffff0000) {
670 tcg_out32(s
, (cond
<< 28) | 0x03400000 | (rd
<< 12)
671 | ((arg
>> 12) & 0x000f0000) | ((arg
>> 16) & 0xfff));
676 /* Look for sequences of two insns. If we have lots of 1's, we can
677 shorten the sequence by beginning with mvn and then clearing
678 higher bits with eor. */
681 if (ctpop32(arg
) > 16) {
685 sh1
= ctz32(tt0
) & ~1;
686 tt1
= tt0
& ~(0xff << sh1
);
687 sh2
= ctz32(tt1
) & ~1;
688 tt2
= tt1
& ~(0xff << sh2
);
690 rot
= ((32 - sh1
) << 7) & 0xf00;
691 tcg_out_dat_imm(s
, cond
, opc
, rd
, 0, ((tt0
>> sh1
) & 0xff) | rot
);
692 rot
= ((32 - sh2
) << 7) & 0xf00;
693 tcg_out_dat_imm(s
, cond
, ARITH_EOR
, rd
, rd
,
694 ((tt0
>> sh2
) & 0xff) | rot
);
698 /* Otherwise, drop it into the constant pool. */
699 tcg_out_movi_pool(s
, cond
, rd
, arg
);
702 static inline void tcg_out_dat_rI(TCGContext
*s
, int cond
, int opc
, TCGArg dst
,
703 TCGArg lhs
, TCGArg rhs
, int rhs_is_const
)
705 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
706 * rhs must satisfy the "rI" constraint.
709 int rot
= encode_imm(rhs
);
710 tcg_debug_assert(rot
>= 0);
711 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
713 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
717 static void tcg_out_dat_rIK(TCGContext
*s
, int cond
, int opc
, int opinv
,
718 TCGReg dst
, TCGReg lhs
, TCGArg rhs
,
721 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
722 * rhs must satisfy the "rIK" constraint.
725 int rot
= encode_imm(rhs
);
728 rot
= encode_imm(rhs
);
729 tcg_debug_assert(rot
>= 0);
732 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
734 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
738 static void tcg_out_dat_rIN(TCGContext
*s
, int cond
, int opc
, int opneg
,
739 TCGArg dst
, TCGArg lhs
, TCGArg rhs
,
742 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
743 * rhs must satisfy the "rIN" constraint.
746 int rot
= encode_imm(rhs
);
749 rot
= encode_imm(rhs
);
750 tcg_debug_assert(rot
>= 0);
753 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
755 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
759 static inline void tcg_out_mul32(TCGContext
*s
, int cond
, TCGReg rd
,
760 TCGReg rn
, TCGReg rm
)
762 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
763 if (!use_armv6_instructions
&& rd
== rn
) {
765 /* rd == rn == rm; copy an input to tmp first. */
766 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
767 rm
= rn
= TCG_REG_TMP
;
774 tcg_out32(s
, (cond
<< 28) | 0x90 | (rd
<< 16) | (rm
<< 8) | rn
);
777 static inline void tcg_out_umull32(TCGContext
*s
, int cond
, TCGReg rd0
,
778 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
780 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
781 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
782 if (rd0
== rm
|| rd1
== rm
) {
783 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
792 tcg_out32(s
, (cond
<< 28) | 0x00800090 |
793 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
796 static inline void tcg_out_smull32(TCGContext
*s
, int cond
, TCGReg rd0
,
797 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
799 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
800 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
801 if (rd0
== rm
|| rd1
== rm
) {
802 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
811 tcg_out32(s
, (cond
<< 28) | 0x00c00090 |
812 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
815 static inline void tcg_out_sdiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
817 tcg_out32(s
, 0x0710f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
820 static inline void tcg_out_udiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
822 tcg_out32(s
, 0x0730f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
825 static inline void tcg_out_ext8s(TCGContext
*s
, int cond
,
828 if (use_armv6_instructions
) {
830 tcg_out32(s
, 0x06af0070 | (cond
<< 28) | (rd
<< 12) | rn
);
832 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
833 rd
, 0, rn
, SHIFT_IMM_LSL(24));
834 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
835 rd
, 0, rd
, SHIFT_IMM_ASR(24));
839 static inline void tcg_out_ext8u(TCGContext
*s
, int cond
,
842 tcg_out_dat_imm(s
, cond
, ARITH_AND
, rd
, rn
, 0xff);
845 static inline void tcg_out_ext16s(TCGContext
*s
, int cond
,
848 if (use_armv6_instructions
) {
850 tcg_out32(s
, 0x06bf0070 | (cond
<< 28) | (rd
<< 12) | rn
);
852 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
853 rd
, 0, rn
, SHIFT_IMM_LSL(16));
854 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
855 rd
, 0, rd
, SHIFT_IMM_ASR(16));
859 static inline void tcg_out_ext16u(TCGContext
*s
, int cond
,
862 if (use_armv6_instructions
) {
864 tcg_out32(s
, 0x06ff0070 | (cond
<< 28) | (rd
<< 12) | rn
);
866 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
867 rd
, 0, rn
, SHIFT_IMM_LSL(16));
868 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
869 rd
, 0, rd
, SHIFT_IMM_LSR(16));
873 static inline void tcg_out_bswap16s(TCGContext
*s
, int cond
, int rd
, int rn
)
875 if (use_armv6_instructions
) {
877 tcg_out32(s
, 0x06ff0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
879 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
880 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
881 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
882 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_ASR(16));
883 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
884 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
888 static inline void tcg_out_bswap16(TCGContext
*s
, int cond
, int rd
, int rn
)
890 if (use_armv6_instructions
) {
892 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
894 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
895 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
896 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
897 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_LSR(16));
898 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
899 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
903 /* swap the two low bytes assuming that the two high input bytes and the
904 two high output bit can hold any value. */
905 static inline void tcg_out_bswap16st(TCGContext
*s
, int cond
, int rd
, int rn
)
907 if (use_armv6_instructions
) {
909 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
911 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
912 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSR(8));
913 tcg_out_dat_imm(s
, cond
, ARITH_AND
, TCG_REG_TMP
, TCG_REG_TMP
, 0xff);
914 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
915 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSL(8));
919 static inline void tcg_out_bswap32(TCGContext
*s
, int cond
, int rd
, int rn
)
921 if (use_armv6_instructions
) {
923 tcg_out32(s
, 0x06bf0f30 | (cond
<< 28) | (rd
<< 12) | rn
);
925 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
926 TCG_REG_TMP
, rn
, rn
, SHIFT_IMM_ROR(16));
927 tcg_out_dat_imm(s
, cond
, ARITH_BIC
,
928 TCG_REG_TMP
, TCG_REG_TMP
, 0xff | 0x800);
929 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
930 rd
, 0, rn
, SHIFT_IMM_ROR(8));
931 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
932 rd
, rd
, TCG_REG_TMP
, SHIFT_IMM_LSR(8));
936 static inline void tcg_out_deposit(TCGContext
*s
, int cond
, TCGReg rd
,
937 TCGArg a1
, int ofs
, int len
, bool const_a1
)
940 /* bfi becomes bfc with rn == 15. */
944 tcg_out32(s
, 0x07c00010 | (cond
<< 28) | (rd
<< 12) | a1
945 | (ofs
<< 7) | ((ofs
+ len
- 1) << 16));
948 static inline void tcg_out_extract(TCGContext
*s
, int cond
, TCGReg rd
,
949 TCGArg a1
, int ofs
, int len
)
952 tcg_out32(s
, 0x07e00050 | (cond
<< 28) | (rd
<< 12) | a1
953 | (ofs
<< 7) | ((len
- 1) << 16));
956 static inline void tcg_out_sextract(TCGContext
*s
, int cond
, TCGReg rd
,
957 TCGArg a1
, int ofs
, int len
)
960 tcg_out32(s
, 0x07a00050 | (cond
<< 28) | (rd
<< 12) | a1
961 | (ofs
<< 7) | ((len
- 1) << 16));
964 static inline void tcg_out_ld32u(TCGContext
*s
, int cond
,
965 int rd
, int rn
, int32_t offset
)
967 if (offset
> 0xfff || offset
< -0xfff) {
968 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
969 tcg_out_ld32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
971 tcg_out_ld32_12(s
, cond
, rd
, rn
, offset
);
974 static inline void tcg_out_st32(TCGContext
*s
, int cond
,
975 int rd
, int rn
, int32_t offset
)
977 if (offset
> 0xfff || offset
< -0xfff) {
978 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
979 tcg_out_st32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
981 tcg_out_st32_12(s
, cond
, rd
, rn
, offset
);
984 static inline void tcg_out_ld16u(TCGContext
*s
, int cond
,
985 int rd
, int rn
, int32_t offset
)
987 if (offset
> 0xff || offset
< -0xff) {
988 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
989 tcg_out_ld16u_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
991 tcg_out_ld16u_8(s
, cond
, rd
, rn
, offset
);
994 static inline void tcg_out_ld16s(TCGContext
*s
, int cond
,
995 int rd
, int rn
, int32_t offset
)
997 if (offset
> 0xff || offset
< -0xff) {
998 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
999 tcg_out_ld16s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
1001 tcg_out_ld16s_8(s
, cond
, rd
, rn
, offset
);
1004 static inline void tcg_out_st16(TCGContext
*s
, int cond
,
1005 int rd
, int rn
, int32_t offset
)
1007 if (offset
> 0xff || offset
< -0xff) {
1008 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
1009 tcg_out_st16_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
1011 tcg_out_st16_8(s
, cond
, rd
, rn
, offset
);
1014 static inline void tcg_out_ld8u(TCGContext
*s
, int cond
,
1015 int rd
, int rn
, int32_t offset
)
1017 if (offset
> 0xfff || offset
< -0xfff) {
1018 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
1019 tcg_out_ld8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
1021 tcg_out_ld8_12(s
, cond
, rd
, rn
, offset
);
1024 static inline void tcg_out_ld8s(TCGContext
*s
, int cond
,
1025 int rd
, int rn
, int32_t offset
)
1027 if (offset
> 0xff || offset
< -0xff) {
1028 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
1029 tcg_out_ld8s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
1031 tcg_out_ld8s_8(s
, cond
, rd
, rn
, offset
);
1034 static inline void tcg_out_st8(TCGContext
*s
, int cond
,
1035 int rd
, int rn
, int32_t offset
)
1037 if (offset
> 0xfff || offset
< -0xfff) {
1038 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
1039 tcg_out_st8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
1041 tcg_out_st8_12(s
, cond
, rd
, rn
, offset
);
1044 /* The _goto case is normally between TBs within the same code buffer, and
1045 * with the code buffer limited to 16MB we wouldn't need the long case.
1046 * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
1048 static void tcg_out_goto(TCGContext
*s
, int cond
, tcg_insn_unit
*addr
)
1050 intptr_t addri
= (intptr_t)addr
;
1051 ptrdiff_t disp
= tcg_pcrel_diff(s
, addr
);
1053 if ((addri
& 1) == 0 && disp
- 8 < 0x01fffffd && disp
- 8 > -0x01fffffd) {
1054 tcg_out_b(s
, cond
, disp
);
1057 tcg_out_movi_pool(s
, cond
, TCG_REG_PC
, addri
);
1060 /* The call case is mostly used for helpers - so it's not unreasonable
1061 * for them to be beyond branch range */
1062 static void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*addr
)
1064 intptr_t addri
= (intptr_t)addr
;
1065 ptrdiff_t disp
= tcg_pcrel_diff(s
, addr
);
1067 if (disp
- 8 < 0x02000000 && disp
- 8 >= -0x02000000) {
1069 /* Use BLX if the target is in Thumb mode */
1070 if (!use_armv5t_instructions
) {
1073 tcg_out_blx_imm(s
, disp
);
1075 tcg_out_bl(s
, COND_AL
, disp
);
1077 } else if (use_armv7_instructions
) {
1078 tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, addri
);
1079 tcg_out_blx(s
, COND_AL
, TCG_REG_TMP
);
1081 /* ??? Know that movi_pool emits exactly 2 insns. */
1082 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R14
, TCG_REG_PC
, 4);
1083 tcg_out_movi_pool(s
, COND_AL
, TCG_REG_PC
, addri
);
1087 static inline void tcg_out_goto_label(TCGContext
*s
, int cond
, TCGLabel
*l
)
1090 tcg_out_goto(s
, cond
, l
->u
.value_ptr
);
1092 tcg_out_reloc(s
, s
->code_ptr
, R_ARM_PC24
, l
, 0);
1093 tcg_out_b_noaddr(s
, cond
);
1097 static inline void tcg_out_mb(TCGContext
*s
, TCGArg a0
)
1099 if (use_armv7_instructions
) {
1100 tcg_out32(s
, INSN_DMB_ISH
);
1101 } else if (use_armv6_instructions
) {
1102 tcg_out32(s
, INSN_DMB_MCR
);
1106 static TCGCond
tcg_out_cmp2(TCGContext
*s
, const TCGArg
*args
,
1107 const int *const_args
)
1109 TCGReg al
= args
[0];
1110 TCGReg ah
= args
[1];
1111 TCGArg bl
= args
[2];
1112 TCGArg bh
= args
[3];
1113 TCGCond cond
= args
[4];
1114 int const_bl
= const_args
[2];
1115 int const_bh
= const_args
[3];
1124 /* We perform a conditional comparision. If the high half is
1125 equal, then overwrite the flags with the comparison of the
1126 low half. The resulting flags cover the whole. */
1127 tcg_out_dat_rI(s
, COND_AL
, ARITH_CMP
, 0, ah
, bh
, const_bh
);
1128 tcg_out_dat_rI(s
, COND_EQ
, ARITH_CMP
, 0, al
, bl
, const_bl
);
1133 /* We perform a double-word subtraction and examine the result.
1134 We do not actually need the result of the subtract, so the
1135 low part "subtract" is a compare. For the high half we have
1136 no choice but to compute into a temporary. */
1137 tcg_out_dat_rI(s
, COND_AL
, ARITH_CMP
, 0, al
, bl
, const_bl
);
1138 tcg_out_dat_rI(s
, COND_AL
, ARITH_SBC
| TO_CPSR
,
1139 TCG_REG_TMP
, ah
, bh
, const_bh
);
1144 /* Similar, but with swapped arguments, via reversed subtract. */
1145 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
| TO_CPSR
,
1146 TCG_REG_TMP
, al
, bl
, const_bl
);
1147 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSC
| TO_CPSR
,
1148 TCG_REG_TMP
, ah
, bh
, const_bh
);
1149 return tcg_swap_cond(cond
);
1152 g_assert_not_reached();
1156 #ifdef CONFIG_SOFTMMU
1157 #include "tcg-ldst.inc.c"
1159 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1160 * int mmu_idx, uintptr_t ra)
1162 static void * const qemu_ld_helpers
[16] = {
1163 [MO_UB
] = helper_ret_ldub_mmu
,
1164 [MO_SB
] = helper_ret_ldsb_mmu
,
1166 [MO_LEUW
] = helper_le_lduw_mmu
,
1167 [MO_LEUL
] = helper_le_ldul_mmu
,
1168 [MO_LEQ
] = helper_le_ldq_mmu
,
1169 [MO_LESW
] = helper_le_ldsw_mmu
,
1170 [MO_LESL
] = helper_le_ldul_mmu
,
1172 [MO_BEUW
] = helper_be_lduw_mmu
,
1173 [MO_BEUL
] = helper_be_ldul_mmu
,
1174 [MO_BEQ
] = helper_be_ldq_mmu
,
1175 [MO_BESW
] = helper_be_ldsw_mmu
,
1176 [MO_BESL
] = helper_be_ldul_mmu
,
1179 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1180 * uintxx_t val, int mmu_idx, uintptr_t ra)
1182 static void * const qemu_st_helpers
[16] = {
1183 [MO_UB
] = helper_ret_stb_mmu
,
1184 [MO_LEUW
] = helper_le_stw_mmu
,
1185 [MO_LEUL
] = helper_le_stl_mmu
,
1186 [MO_LEQ
] = helper_le_stq_mmu
,
1187 [MO_BEUW
] = helper_be_stw_mmu
,
1188 [MO_BEUL
] = helper_be_stl_mmu
,
1189 [MO_BEQ
] = helper_be_stq_mmu
,
1192 /* Helper routines for marshalling helper function arguments into
1193 * the correct registers and stack.
1194 * argreg is where we want to put this argument, arg is the argument itself.
1195 * Return value is the updated argreg ready for the next call.
1196 * Note that argreg 0..3 is real registers, 4+ on stack.
1198 * We provide routines for arguments which are: immediate, 32 bit
1199 * value in register, 16 and 8 bit values in register (which must be zero
1200 * extended before use) and 64 bit value in a lo:hi register pair.
1202 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1203 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1206 MOV_ARG(s, COND_AL, argreg, arg); \
1208 int ofs = (argreg - 4) * 4; \
1210 tcg_debug_assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1211 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1213 return argreg + 1; \
1216 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32
, uint32_t, tcg_out_movi32
,
1217 (tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1218 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8
, TCGReg
, tcg_out_ext8u
,
1219 (tcg_out_ext8u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1220 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16
, TCGReg
, tcg_out_ext16u
,
1221 (tcg_out_ext16u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1222 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32
, TCGReg
, tcg_out_mov_reg
, )
1224 static TCGReg
tcg_out_arg_reg64(TCGContext
*s
, TCGReg argreg
,
1225 TCGReg arglo
, TCGReg arghi
)
1227 /* 64 bit arguments must go in even/odd register pairs
1228 * and in 8-aligned stack slots.
1233 if (use_armv6_instructions
&& argreg
>= 4
1234 && (arglo
& 1) == 0 && arghi
== arglo
+ 1) {
1235 tcg_out_strd_8(s
, COND_AL
, arglo
,
1236 TCG_REG_CALL_STACK
, (argreg
- 4) * 4);
1239 argreg
= tcg_out_arg_reg32(s
, argreg
, arglo
);
1240 argreg
= tcg_out_arg_reg32(s
, argreg
, arghi
);
1245 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1247 /* We're expecting to use an 8-bit immediate and to mask. */
1248 QEMU_BUILD_BUG_ON(CPU_TLB_BITS
> 8);
1250 /* Load and compare a TLB entry, leaving the flags set. Returns the register
1251 containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
1253 static TCGReg
tcg_out_tlb_read(TCGContext
*s
, TCGReg addrlo
, TCGReg addrhi
,
1254 TCGMemOp opc
, int mem_index
, bool is_load
)
1256 TCGReg base
= TCG_AREG0
;
1259 ? offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1260 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
));
1261 int add_off
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addend
);
1263 unsigned s_bits
= opc
& MO_SIZE
;
1264 unsigned a_bits
= get_alignment_bits(opc
);
1266 /* V7 generates the following:
1267 * ubfx r0, addrlo, #TARGET_PAGE_BITS, #CPU_TLB_BITS
1268 * add r2, env, #high
1269 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS
1270 * ldr r0, [r2, #cmp]
1271 * ldr r2, [r2, #add]
1272 * movw tmp, #page_align_mask
1273 * bic tmp, addrlo, tmp
1276 * Otherwise we generate:
1277 * shr tmp, addrlo, #TARGET_PAGE_BITS
1278 * add r2, env, #high
1279 * and r0, tmp, #(CPU_TLB_SIZE - 1)
1280 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS
1281 * ldr r0, [r2, #cmp]
1282 * ldr r2, [r2, #add]
1283 * tst addrlo, #s_mask
1284 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS
1286 if (use_armv7_instructions
) {
1287 tcg_out_extract(s
, COND_AL
, TCG_REG_R0
, addrlo
,
1288 TARGET_PAGE_BITS
, CPU_TLB_BITS
);
1290 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, TCG_REG_TMP
,
1291 0, addrlo
, SHIFT_IMM_LSR(TARGET_PAGE_BITS
));
1294 /* Add portions of the offset until the memory access is in range.
1295 * If we plan on using ldrd, reduce to an 8-bit offset; otherwise
1296 * we can use a 12-bit offset. */
1297 if (use_armv6_instructions
&& TARGET_LONG_BITS
== 64) {
1302 while (cmp_off
> mask_off
) {
1303 int shift
= ctz32(cmp_off
& ~mask_off
) & ~1;
1304 int rot
= ((32 - shift
) << 7) & 0xf00;
1305 int addend
= cmp_off
& (0xff << shift
);
1306 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1307 rot
| ((cmp_off
>> shift
) & 0xff));
1313 if (!use_armv7_instructions
) {
1314 tcg_out_dat_imm(s
, COND_AL
, ARITH_AND
,
1315 TCG_REG_R0
, TCG_REG_TMP
, CPU_TLB_SIZE
- 1);
1317 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1318 TCG_REG_R0
, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS
));
1320 /* Load the tlb comparator. Use ldrd if needed and available,
1321 but due to how the pointer needs setting up, ldm isn't useful.
1322 Base arm5 doesn't have ldrd, but armv5te does. */
1323 if (use_armv6_instructions
&& TARGET_LONG_BITS
== 64) {
1324 tcg_out_ldrd_8(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R2
, cmp_off
);
1326 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R2
, cmp_off
);
1327 if (TARGET_LONG_BITS
== 64) {
1328 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R1
, TCG_REG_R2
, cmp_off
+ 4);
1332 /* Load the tlb addend. */
1333 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R2
, TCG_REG_R2
, add_off
);
1335 /* Check alignment. We don't support inline unaligned acceses,
1336 but we can easily support overalignment checks. */
1337 if (a_bits
< s_bits
) {
1341 if (use_armv7_instructions
) {
1342 tcg_target_ulong mask
= ~(TARGET_PAGE_MASK
| ((1 << a_bits
) - 1));
1343 int rot
= encode_imm(mask
);
1346 tcg_out_dat_imm(s
, COND_AL
, ARITH_BIC
, TCG_REG_TMP
, addrlo
,
1347 rotl(mask
, rot
) | (rot
<< 7));
1349 tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, mask
);
1350 tcg_out_dat_reg(s
, COND_AL
, ARITH_BIC
, TCG_REG_TMP
,
1351 addrlo
, TCG_REG_TMP
, 0);
1353 tcg_out_dat_reg(s
, COND_AL
, ARITH_CMP
, 0, TCG_REG_R0
, TCG_REG_TMP
, 0);
1356 tcg_out_dat_imm(s
, COND_AL
, ARITH_TST
, 0, addrlo
,
1359 tcg_out_dat_reg(s
, (a_bits
? COND_EQ
: COND_AL
), ARITH_CMP
,
1360 0, TCG_REG_R0
, TCG_REG_TMP
,
1361 SHIFT_IMM_LSL(TARGET_PAGE_BITS
));
1364 if (TARGET_LONG_BITS
== 64) {
1365 tcg_out_dat_reg(s
, COND_EQ
, ARITH_CMP
, 0, TCG_REG_R1
, addrhi
, 0);
1371 /* Record the context of a call to the out of line helper code for the slow
1372 path for a load or store, so that we can later generate the correct
1374 static void add_qemu_ldst_label(TCGContext
*s
, bool is_ld
, TCGMemOpIdx oi
,
1375 TCGReg datalo
, TCGReg datahi
, TCGReg addrlo
,
1376 TCGReg addrhi
, tcg_insn_unit
*raddr
,
1377 tcg_insn_unit
*label_ptr
)
1379 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1381 label
->is_ld
= is_ld
;
1383 label
->datalo_reg
= datalo
;
1384 label
->datahi_reg
= datahi
;
1385 label
->addrlo_reg
= addrlo
;
1386 label
->addrhi_reg
= addrhi
;
1387 label
->raddr
= raddr
;
1388 label
->label_ptr
[0] = label_ptr
;
1391 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1393 TCGReg argreg
, datalo
, datahi
;
1394 TCGMemOpIdx oi
= lb
->oi
;
1395 TCGMemOp opc
= get_memop(oi
);
1398 reloc_pc24(lb
->label_ptr
[0], s
->code_ptr
);
1400 argreg
= tcg_out_arg_reg32(s
, TCG_REG_R0
, TCG_AREG0
);
1401 if (TARGET_LONG_BITS
== 64) {
1402 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1404 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1406 argreg
= tcg_out_arg_imm32(s
, argreg
, oi
);
1407 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_REG_R14
);
1409 /* For armv6 we can use the canonical unsigned helpers and minimize
1410 icache usage. For pre-armv6, use the signed helpers since we do
1411 not have a single insn sign-extend. */
1412 if (use_armv6_instructions
) {
1413 func
= qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)];
1415 func
= qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SSIZE
)];
1416 if (opc
& MO_SIGN
) {
1420 tcg_out_call(s
, func
);
1422 datalo
= lb
->datalo_reg
;
1423 datahi
= lb
->datahi_reg
;
1424 switch (opc
& MO_SSIZE
) {
1426 tcg_out_ext8s(s
, COND_AL
, datalo
, TCG_REG_R0
);
1429 tcg_out_ext16s(s
, COND_AL
, datalo
, TCG_REG_R0
);
1432 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1435 if (datalo
!= TCG_REG_R1
) {
1436 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1437 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1438 } else if (datahi
!= TCG_REG_R0
) {
1439 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1440 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1442 tcg_out_mov_reg(s
, COND_AL
, TCG_REG_TMP
, TCG_REG_R0
);
1443 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1444 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_TMP
);
1449 tcg_out_goto(s
, COND_AL
, lb
->raddr
);
1452 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1454 TCGReg argreg
, datalo
, datahi
;
1455 TCGMemOpIdx oi
= lb
->oi
;
1456 TCGMemOp opc
= get_memop(oi
);
1458 reloc_pc24(lb
->label_ptr
[0], s
->code_ptr
);
1460 argreg
= TCG_REG_R0
;
1461 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_AREG0
);
1462 if (TARGET_LONG_BITS
== 64) {
1463 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1465 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1468 datalo
= lb
->datalo_reg
;
1469 datahi
= lb
->datahi_reg
;
1470 switch (opc
& MO_SIZE
) {
1472 argreg
= tcg_out_arg_reg8(s
, argreg
, datalo
);
1475 argreg
= tcg_out_arg_reg16(s
, argreg
, datalo
);
1479 argreg
= tcg_out_arg_reg32(s
, argreg
, datalo
);
1482 argreg
= tcg_out_arg_reg64(s
, argreg
, datalo
, datahi
);
1486 argreg
= tcg_out_arg_imm32(s
, argreg
, oi
);
1487 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_REG_R14
);
1489 /* Tail-call to the helper, which will return to the fast path. */
1490 tcg_out_goto(s
, COND_AL
, qemu_st_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)]);
1492 #endif /* SOFTMMU */
1494 static inline void tcg_out_qemu_ld_index(TCGContext
*s
, TCGMemOp opc
,
1495 TCGReg datalo
, TCGReg datahi
,
1496 TCGReg addrlo
, TCGReg addend
)
1498 TCGMemOp bswap
= opc
& MO_BSWAP
;
1500 switch (opc
& MO_SSIZE
) {
1502 tcg_out_ld8_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1505 tcg_out_ld8s_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1508 tcg_out_ld16u_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1510 tcg_out_bswap16(s
, COND_AL
, datalo
, datalo
);
1515 tcg_out_ld16u_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1516 tcg_out_bswap16s(s
, COND_AL
, datalo
, datalo
);
1518 tcg_out_ld16s_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1523 tcg_out_ld32_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1525 tcg_out_bswap32(s
, COND_AL
, datalo
, datalo
);
1530 TCGReg dl
= (bswap
? datahi
: datalo
);
1531 TCGReg dh
= (bswap
? datalo
: datahi
);
1533 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1534 if (USING_SOFTMMU
&& use_armv6_instructions
1535 && (dl
& 1) == 0 && dh
== dl
+ 1) {
1536 tcg_out_ldrd_r(s
, COND_AL
, dl
, addrlo
, addend
);
1537 } else if (dl
!= addend
) {
1538 tcg_out_ld32_rwb(s
, COND_AL
, dl
, addend
, addrlo
);
1539 tcg_out_ld32_12(s
, COND_AL
, dh
, addend
, 4);
1541 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_TMP
,
1542 addend
, addrlo
, SHIFT_IMM_LSL(0));
1543 tcg_out_ld32_12(s
, COND_AL
, dl
, TCG_REG_TMP
, 0);
1544 tcg_out_ld32_12(s
, COND_AL
, dh
, TCG_REG_TMP
, 4);
1547 tcg_out_bswap32(s
, COND_AL
, dl
, dl
);
1548 tcg_out_bswap32(s
, COND_AL
, dh
, dh
);
1555 static inline void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGMemOp opc
,
1556 TCGReg datalo
, TCGReg datahi
,
1559 TCGMemOp bswap
= opc
& MO_BSWAP
;
1561 switch (opc
& MO_SSIZE
) {
1563 tcg_out_ld8_12(s
, COND_AL
, datalo
, addrlo
, 0);
1566 tcg_out_ld8s_8(s
, COND_AL
, datalo
, addrlo
, 0);
1569 tcg_out_ld16u_8(s
, COND_AL
, datalo
, addrlo
, 0);
1571 tcg_out_bswap16(s
, COND_AL
, datalo
, datalo
);
1576 tcg_out_ld16u_8(s
, COND_AL
, datalo
, addrlo
, 0);
1577 tcg_out_bswap16s(s
, COND_AL
, datalo
, datalo
);
1579 tcg_out_ld16s_8(s
, COND_AL
, datalo
, addrlo
, 0);
1584 tcg_out_ld32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1586 tcg_out_bswap32(s
, COND_AL
, datalo
, datalo
);
1591 TCGReg dl
= (bswap
? datahi
: datalo
);
1592 TCGReg dh
= (bswap
? datalo
: datahi
);
1594 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1595 if (USING_SOFTMMU
&& use_armv6_instructions
1596 && (dl
& 1) == 0 && dh
== dl
+ 1) {
1597 tcg_out_ldrd_8(s
, COND_AL
, dl
, addrlo
, 0);
1598 } else if (dl
== addrlo
) {
1599 tcg_out_ld32_12(s
, COND_AL
, dh
, addrlo
, bswap
? 0 : 4);
1600 tcg_out_ld32_12(s
, COND_AL
, dl
, addrlo
, bswap
? 4 : 0);
1602 tcg_out_ld32_12(s
, COND_AL
, dl
, addrlo
, bswap
? 4 : 0);
1603 tcg_out_ld32_12(s
, COND_AL
, dh
, addrlo
, bswap
? 0 : 4);
1606 tcg_out_bswap32(s
, COND_AL
, dl
, dl
);
1607 tcg_out_bswap32(s
, COND_AL
, dh
, dh
);
1614 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, bool is64
)
1616 TCGReg addrlo
, datalo
, datahi
, addrhi
__attribute__((unused
));
1619 #ifdef CONFIG_SOFTMMU
1622 tcg_insn_unit
*label_ptr
;
1626 datahi
= (is64
? *args
++ : 0);
1628 addrhi
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1630 opc
= get_memop(oi
);
1632 #ifdef CONFIG_SOFTMMU
1633 mem_index
= get_mmuidx(oi
);
1634 addend
= tcg_out_tlb_read(s
, addrlo
, addrhi
, opc
, mem_index
, 1);
1636 /* This a conditional BL only to load a pointer within this opcode into LR
1637 for the slow path. We will not be using the value for a tail call. */
1638 label_ptr
= s
->code_ptr
;
1639 tcg_out_bl_noaddr(s
, COND_NE
);
1641 tcg_out_qemu_ld_index(s
, opc
, datalo
, datahi
, addrlo
, addend
);
1643 add_qemu_ldst_label(s
, true, oi
, datalo
, datahi
, addrlo
, addrhi
,
1644 s
->code_ptr
, label_ptr
);
1645 #else /* !CONFIG_SOFTMMU */
1647 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_TMP
, guest_base
);
1648 tcg_out_qemu_ld_index(s
, opc
, datalo
, datahi
, addrlo
, TCG_REG_TMP
);
1650 tcg_out_qemu_ld_direct(s
, opc
, datalo
, datahi
, addrlo
);
1655 static inline void tcg_out_qemu_st_index(TCGContext
*s
, int cond
, TCGMemOp opc
,
1656 TCGReg datalo
, TCGReg datahi
,
1657 TCGReg addrlo
, TCGReg addend
)
1659 TCGMemOp bswap
= opc
& MO_BSWAP
;
1661 switch (opc
& MO_SIZE
) {
1663 tcg_out_st8_r(s
, cond
, datalo
, addrlo
, addend
);
1667 tcg_out_bswap16st(s
, cond
, TCG_REG_R0
, datalo
);
1668 tcg_out_st16_r(s
, cond
, TCG_REG_R0
, addrlo
, addend
);
1670 tcg_out_st16_r(s
, cond
, datalo
, addrlo
, addend
);
1676 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datalo
);
1677 tcg_out_st32_r(s
, cond
, TCG_REG_R0
, addrlo
, addend
);
1679 tcg_out_st32_r(s
, cond
, datalo
, addrlo
, addend
);
1683 /* Avoid strd for user-only emulation, to handle unaligned. */
1685 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datahi
);
1686 tcg_out_st32_rwb(s
, cond
, TCG_REG_R0
, addend
, addrlo
);
1687 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datalo
);
1688 tcg_out_st32_12(s
, cond
, TCG_REG_R0
, addend
, 4);
1689 } else if (USING_SOFTMMU
&& use_armv6_instructions
1690 && (datalo
& 1) == 0 && datahi
== datalo
+ 1) {
1691 tcg_out_strd_r(s
, cond
, datalo
, addrlo
, addend
);
1693 tcg_out_st32_rwb(s
, cond
, datalo
, addend
, addrlo
);
1694 tcg_out_st32_12(s
, cond
, datahi
, addend
, 4);
1700 static inline void tcg_out_qemu_st_direct(TCGContext
*s
, TCGMemOp opc
,
1701 TCGReg datalo
, TCGReg datahi
,
1704 TCGMemOp bswap
= opc
& MO_BSWAP
;
1706 switch (opc
& MO_SIZE
) {
1708 tcg_out_st8_12(s
, COND_AL
, datalo
, addrlo
, 0);
1712 tcg_out_bswap16st(s
, COND_AL
, TCG_REG_R0
, datalo
);
1713 tcg_out_st16_8(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1715 tcg_out_st16_8(s
, COND_AL
, datalo
, addrlo
, 0);
1721 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datalo
);
1722 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1724 tcg_out_st32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1728 /* Avoid strd for user-only emulation, to handle unaligned. */
1730 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datahi
);
1731 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1732 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datalo
);
1733 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 4);
1734 } else if (USING_SOFTMMU
&& use_armv6_instructions
1735 && (datalo
& 1) == 0 && datahi
== datalo
+ 1) {
1736 tcg_out_strd_8(s
, COND_AL
, datalo
, addrlo
, 0);
1738 tcg_out_st32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1739 tcg_out_st32_12(s
, COND_AL
, datahi
, addrlo
, 4);
1745 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, bool is64
)
1747 TCGReg addrlo
, datalo
, datahi
, addrhi
__attribute__((unused
));
1750 #ifdef CONFIG_SOFTMMU
1753 tcg_insn_unit
*label_ptr
;
1757 datahi
= (is64
? *args
++ : 0);
1759 addrhi
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1761 opc
= get_memop(oi
);
1763 #ifdef CONFIG_SOFTMMU
1764 mem_index
= get_mmuidx(oi
);
1765 addend
= tcg_out_tlb_read(s
, addrlo
, addrhi
, opc
, mem_index
, 0);
1767 tcg_out_qemu_st_index(s
, COND_EQ
, opc
, datalo
, datahi
, addrlo
, addend
);
1769 /* The conditional call must come last, as we're going to return here. */
1770 label_ptr
= s
->code_ptr
;
1771 tcg_out_bl_noaddr(s
, COND_NE
);
1773 add_qemu_ldst_label(s
, false, oi
, datalo
, datahi
, addrlo
, addrhi
,
1774 s
->code_ptr
, label_ptr
);
1775 #else /* !CONFIG_SOFTMMU */
1777 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_TMP
, guest_base
);
1778 tcg_out_qemu_st_index(s
, COND_AL
, opc
, datalo
,
1779 datahi
, addrlo
, TCG_REG_TMP
);
1781 tcg_out_qemu_st_direct(s
, opc
, datalo
, datahi
, addrlo
);
1786 static tcg_insn_unit
*tb_ret_addr
;
1788 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1789 const TCGArg
*args
, const int *const_args
)
1791 TCGArg a0
, a1
, a2
, a3
, a4
, a5
;
1795 case INDEX_op_exit_tb
:
1796 /* Reuse the zeroing that exists for goto_ptr. */
1799 tcg_out_goto(s
, COND_AL
, s
->code_gen_epilogue
);
1801 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
, args
[0]);
1802 tcg_out_goto(s
, COND_AL
, tb_ret_addr
);
1805 case INDEX_op_goto_tb
:
1807 /* Indirect jump method */
1808 intptr_t ptr
, dif
, dil
;
1809 TCGReg base
= TCG_REG_PC
;
1811 tcg_debug_assert(s
->tb_jmp_insn_offset
== 0);
1812 ptr
= (intptr_t)(s
->tb_jmp_target_addr
+ args
[0]);
1813 dif
= ptr
- ((intptr_t)s
->code_ptr
+ 8);
1814 dil
= sextract32(dif
, 0, 12);
1816 /* The TB is close, but outside the 12 bits addressable by
1817 the load. We can extend this to 20 bits with a sub of a
1818 shifted immediate from pc. In the vastly unlikely event
1819 the code requires more than 1MB, we'll use 2 insns and
1822 tcg_out_movi32(s
, COND_AL
, base
, ptr
- dil
);
1824 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, base
, dil
);
1825 set_jmp_reset_offset(s
, args
[0]);
1828 case INDEX_op_goto_ptr
:
1829 tcg_out_bx(s
, COND_AL
, args
[0]);
1832 tcg_out_goto_label(s
, COND_AL
, arg_label(args
[0]));
1835 case INDEX_op_ld8u_i32
:
1836 tcg_out_ld8u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1838 case INDEX_op_ld8s_i32
:
1839 tcg_out_ld8s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1841 case INDEX_op_ld16u_i32
:
1842 tcg_out_ld16u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1844 case INDEX_op_ld16s_i32
:
1845 tcg_out_ld16s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1847 case INDEX_op_ld_i32
:
1848 tcg_out_ld32u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1850 case INDEX_op_st8_i32
:
1851 tcg_out_st8(s
, COND_AL
, args
[0], args
[1], args
[2]);
1853 case INDEX_op_st16_i32
:
1854 tcg_out_st16(s
, COND_AL
, args
[0], args
[1], args
[2]);
1856 case INDEX_op_st_i32
:
1857 tcg_out_st32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1860 case INDEX_op_movcond_i32
:
1861 /* Constraints mean that v2 is always in the same register as dest,
1862 * so we only need to do "if condition passed, move v1 to dest".
1864 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1865 args
[1], args
[2], const_args
[2]);
1866 tcg_out_dat_rIK(s
, tcg_cond_to_arm_cond
[args
[5]], ARITH_MOV
,
1867 ARITH_MVN
, args
[0], 0, args
[3], const_args
[3]);
1869 case INDEX_op_add_i32
:
1870 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
, ARITH_SUB
,
1871 args
[0], args
[1], args
[2], const_args
[2]);
1873 case INDEX_op_sub_i32
:
1874 if (const_args
[1]) {
1875 if (const_args
[2]) {
1876 tcg_out_movi32(s
, COND_AL
, args
[0], args
[1] - args
[2]);
1878 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
,
1879 args
[0], args
[2], args
[1], 1);
1882 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
, ARITH_ADD
,
1883 args
[0], args
[1], args
[2], const_args
[2]);
1886 case INDEX_op_and_i32
:
1887 tcg_out_dat_rIK(s
, COND_AL
, ARITH_AND
, ARITH_BIC
,
1888 args
[0], args
[1], args
[2], const_args
[2]);
1890 case INDEX_op_andc_i32
:
1891 tcg_out_dat_rIK(s
, COND_AL
, ARITH_BIC
, ARITH_AND
,
1892 args
[0], args
[1], args
[2], const_args
[2]);
1894 case INDEX_op_or_i32
:
1897 case INDEX_op_xor_i32
:
1901 tcg_out_dat_rI(s
, COND_AL
, c
, args
[0], args
[1], args
[2], const_args
[2]);
1903 case INDEX_op_add2_i32
:
1904 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1905 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1906 if (a0
== a3
|| (a0
== a5
&& !const_args
[5])) {
1909 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
| TO_CPSR
, ARITH_SUB
| TO_CPSR
,
1910 a0
, a2
, a4
, const_args
[4]);
1911 tcg_out_dat_rIK(s
, COND_AL
, ARITH_ADC
, ARITH_SBC
,
1912 a1
, a3
, a5
, const_args
[5]);
1913 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1915 case INDEX_op_sub2_i32
:
1916 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1917 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1918 if ((a0
== a3
&& !const_args
[3]) || (a0
== a5
&& !const_args
[5])) {
1921 if (const_args
[2]) {
1922 if (const_args
[4]) {
1923 tcg_out_movi32(s
, COND_AL
, a0
, a4
);
1926 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
| TO_CPSR
, a0
, a4
, a2
, 1);
1928 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
| TO_CPSR
,
1929 ARITH_ADD
| TO_CPSR
, a0
, a2
, a4
, const_args
[4]);
1931 if (const_args
[3]) {
1932 if (const_args
[5]) {
1933 tcg_out_movi32(s
, COND_AL
, a1
, a5
);
1936 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSC
, a1
, a5
, a3
, 1);
1938 tcg_out_dat_rIK(s
, COND_AL
, ARITH_SBC
, ARITH_ADC
,
1939 a1
, a3
, a5
, const_args
[5]);
1941 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1943 case INDEX_op_neg_i32
:
1944 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, args
[0], args
[1], 0);
1946 case INDEX_op_not_i32
:
1947 tcg_out_dat_reg(s
, COND_AL
,
1948 ARITH_MVN
, args
[0], 0, args
[1], SHIFT_IMM_LSL(0));
1950 case INDEX_op_mul_i32
:
1951 tcg_out_mul32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1953 case INDEX_op_mulu2_i32
:
1954 tcg_out_umull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1956 case INDEX_op_muls2_i32
:
1957 tcg_out_smull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1959 /* XXX: Perhaps args[2] & 0x1f is wrong */
1960 case INDEX_op_shl_i32
:
1962 SHIFT_IMM_LSL(args
[2] & 0x1f) : SHIFT_REG_LSL(args
[2]);
1964 case INDEX_op_shr_i32
:
1965 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_LSR(args
[2] & 0x1f) :
1966 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args
[2]);
1968 case INDEX_op_sar_i32
:
1969 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ASR(args
[2] & 0x1f) :
1970 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args
[2]);
1972 case INDEX_op_rotr_i32
:
1973 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ROR(args
[2] & 0x1f) :
1974 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args
[2]);
1977 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1], c
);
1980 case INDEX_op_rotl_i32
:
1981 if (const_args
[2]) {
1982 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1983 ((0x20 - args
[2]) & 0x1f) ?
1984 SHIFT_IMM_ROR((0x20 - args
[2]) & 0x1f) :
1987 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, TCG_REG_TMP
, args
[2], 0x20);
1988 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1989 SHIFT_REG_ROR(TCG_REG_TMP
));
1993 case INDEX_op_ctz_i32
:
1994 tcg_out_dat_reg(s
, COND_AL
, INSN_RBIT
, TCG_REG_TMP
, 0, args
[1], 0);
1998 case INDEX_op_clz_i32
:
2004 if (c
&& a2
== 32) {
2005 tcg_out_dat_reg(s
, COND_AL
, INSN_CLZ
, a0
, 0, a1
, 0);
2008 tcg_out_dat_imm(s
, COND_AL
, ARITH_CMP
, 0, a1
, 0);
2009 tcg_out_dat_reg(s
, COND_NE
, INSN_CLZ
, a0
, 0, a1
, 0);
2010 if (c
|| a0
!= a2
) {
2011 tcg_out_dat_rIK(s
, COND_EQ
, ARITH_MOV
, ARITH_MVN
, a0
, 0, a2
, c
);
2015 case INDEX_op_brcond_i32
:
2016 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
2017 args
[0], args
[1], const_args
[1]);
2018 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[2]],
2019 arg_label(args
[3]));
2021 case INDEX_op_setcond_i32
:
2022 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
2023 args
[1], args
[2], const_args
[2]);
2024 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[3]],
2025 ARITH_MOV
, args
[0], 0, 1);
2026 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[3])],
2027 ARITH_MOV
, args
[0], 0, 0);
2030 case INDEX_op_brcond2_i32
:
2031 c
= tcg_out_cmp2(s
, args
, const_args
);
2032 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[c
], arg_label(args
[5]));
2034 case INDEX_op_setcond2_i32
:
2035 c
= tcg_out_cmp2(s
, args
+ 1, const_args
+ 1);
2036 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[c
], ARITH_MOV
, args
[0], 0, 1);
2037 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(c
)],
2038 ARITH_MOV
, args
[0], 0, 0);
2041 case INDEX_op_qemu_ld_i32
:
2042 tcg_out_qemu_ld(s
, args
, 0);
2044 case INDEX_op_qemu_ld_i64
:
2045 tcg_out_qemu_ld(s
, args
, 1);
2047 case INDEX_op_qemu_st_i32
:
2048 tcg_out_qemu_st(s
, args
, 0);
2050 case INDEX_op_qemu_st_i64
:
2051 tcg_out_qemu_st(s
, args
, 1);
2054 case INDEX_op_bswap16_i32
:
2055 tcg_out_bswap16(s
, COND_AL
, args
[0], args
[1]);
2057 case INDEX_op_bswap32_i32
:
2058 tcg_out_bswap32(s
, COND_AL
, args
[0], args
[1]);
2061 case INDEX_op_ext8s_i32
:
2062 tcg_out_ext8s(s
, COND_AL
, args
[0], args
[1]);
2064 case INDEX_op_ext16s_i32
:
2065 tcg_out_ext16s(s
, COND_AL
, args
[0], args
[1]);
2067 case INDEX_op_ext16u_i32
:
2068 tcg_out_ext16u(s
, COND_AL
, args
[0], args
[1]);
2071 case INDEX_op_deposit_i32
:
2072 tcg_out_deposit(s
, COND_AL
, args
[0], args
[2],
2073 args
[3], args
[4], const_args
[2]);
2075 case INDEX_op_extract_i32
:
2076 tcg_out_extract(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
2078 case INDEX_op_sextract_i32
:
2079 tcg_out_sextract(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
2082 case INDEX_op_div_i32
:
2083 tcg_out_sdiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
2085 case INDEX_op_divu_i32
:
2086 tcg_out_udiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
2090 tcg_out_mb(s
, args
[0]);
2093 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
2094 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
2095 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
2101 static const TCGTargetOpDef
*tcg_target_op_def(TCGOpcode op
)
2103 static const TCGTargetOpDef r
= { .args_ct_str
= { "r" } };
2104 static const TCGTargetOpDef r_r
= { .args_ct_str
= { "r", "r" } };
2105 static const TCGTargetOpDef s_s
= { .args_ct_str
= { "s", "s" } };
2106 static const TCGTargetOpDef r_l
= { .args_ct_str
= { "r", "l" } };
2107 static const TCGTargetOpDef r_r_r
= { .args_ct_str
= { "r", "r", "r" } };
2108 static const TCGTargetOpDef r_r_l
= { .args_ct_str
= { "r", "r", "l" } };
2109 static const TCGTargetOpDef r_l_l
= { .args_ct_str
= { "r", "l", "l" } };
2110 static const TCGTargetOpDef s_s_s
= { .args_ct_str
= { "s", "s", "s" } };
2111 static const TCGTargetOpDef r_r_ri
= { .args_ct_str
= { "r", "r", "ri" } };
2112 static const TCGTargetOpDef r_r_rI
= { .args_ct_str
= { "r", "r", "rI" } };
2113 static const TCGTargetOpDef r_r_rIN
2114 = { .args_ct_str
= { "r", "r", "rIN" } };
2115 static const TCGTargetOpDef r_r_rIK
2116 = { .args_ct_str
= { "r", "r", "rIK" } };
2117 static const TCGTargetOpDef r_r_r_r
2118 = { .args_ct_str
= { "r", "r", "r", "r" } };
2119 static const TCGTargetOpDef r_r_l_l
2120 = { .args_ct_str
= { "r", "r", "l", "l" } };
2121 static const TCGTargetOpDef s_s_s_s
2122 = { .args_ct_str
= { "s", "s", "s", "s" } };
2123 static const TCGTargetOpDef br
2124 = { .args_ct_str
= { "r", "rIN" } };
2125 static const TCGTargetOpDef dep
2126 = { .args_ct_str
= { "r", "0", "rZ" } };
2127 static const TCGTargetOpDef movc
2128 = { .args_ct_str
= { "r", "r", "rIN", "rIK", "0" } };
2129 static const TCGTargetOpDef add2
2130 = { .args_ct_str
= { "r", "r", "r", "r", "rIN", "rIK" } };
2131 static const TCGTargetOpDef sub2
2132 = { .args_ct_str
= { "r", "r", "rI", "rI", "rIN", "rIK" } };
2133 static const TCGTargetOpDef br2
2134 = { .args_ct_str
= { "r", "r", "rI", "rI" } };
2135 static const TCGTargetOpDef setc2
2136 = { .args_ct_str
= { "r", "r", "r", "rI", "rI" } };
2139 case INDEX_op_goto_ptr
:
2142 case INDEX_op_ld8u_i32
:
2143 case INDEX_op_ld8s_i32
:
2144 case INDEX_op_ld16u_i32
:
2145 case INDEX_op_ld16s_i32
:
2146 case INDEX_op_ld_i32
:
2147 case INDEX_op_st8_i32
:
2148 case INDEX_op_st16_i32
:
2149 case INDEX_op_st_i32
:
2150 case INDEX_op_neg_i32
:
2151 case INDEX_op_not_i32
:
2152 case INDEX_op_bswap16_i32
:
2153 case INDEX_op_bswap32_i32
:
2154 case INDEX_op_ext8s_i32
:
2155 case INDEX_op_ext16s_i32
:
2156 case INDEX_op_ext16u_i32
:
2157 case INDEX_op_extract_i32
:
2158 case INDEX_op_sextract_i32
:
2161 case INDEX_op_add_i32
:
2162 case INDEX_op_sub_i32
:
2163 case INDEX_op_setcond_i32
:
2165 case INDEX_op_and_i32
:
2166 case INDEX_op_andc_i32
:
2167 case INDEX_op_clz_i32
:
2168 case INDEX_op_ctz_i32
:
2170 case INDEX_op_mul_i32
:
2171 case INDEX_op_div_i32
:
2172 case INDEX_op_divu_i32
:
2174 case INDEX_op_mulu2_i32
:
2175 case INDEX_op_muls2_i32
:
2177 case INDEX_op_or_i32
:
2178 case INDEX_op_xor_i32
:
2180 case INDEX_op_shl_i32
:
2181 case INDEX_op_shr_i32
:
2182 case INDEX_op_sar_i32
:
2183 case INDEX_op_rotl_i32
:
2184 case INDEX_op_rotr_i32
:
2187 case INDEX_op_brcond_i32
:
2189 case INDEX_op_deposit_i32
:
2191 case INDEX_op_movcond_i32
:
2193 case INDEX_op_add2_i32
:
2195 case INDEX_op_sub2_i32
:
2197 case INDEX_op_brcond2_i32
:
2199 case INDEX_op_setcond2_i32
:
2202 case INDEX_op_qemu_ld_i32
:
2203 return TARGET_LONG_BITS
== 32 ? &r_l
: &r_l_l
;
2204 case INDEX_op_qemu_ld_i64
:
2205 return TARGET_LONG_BITS
== 32 ? &r_r_l
: &r_r_l_l
;
2206 case INDEX_op_qemu_st_i32
:
2207 return TARGET_LONG_BITS
== 32 ? &s_s
: &s_s_s
;
2208 case INDEX_op_qemu_st_i64
:
2209 return TARGET_LONG_BITS
== 32 ? &s_s_s
: &s_s_s_s
;
2216 static void tcg_target_init(TCGContext
*s
)
2218 /* Only probe for the platform and capabilities if we havn't already
2219 determined maximum values at compile time. */
2220 #ifndef use_idiv_instructions
2222 unsigned long hwcap
= qemu_getauxval(AT_HWCAP
);
2223 use_idiv_instructions
= (hwcap
& HWCAP_ARM_IDIVA
) != 0;
2226 if (__ARM_ARCH
< 7) {
2227 const char *pl
= (const char *)qemu_getauxval(AT_PLATFORM
);
2228 if (pl
!= NULL
&& pl
[0] == 'v' && pl
[1] >= '4' && pl
[1] <= '9') {
2229 arm_arch
= pl
[1] - '0';
2233 tcg_target_available_regs
[TCG_TYPE_I32
] = 0xffff;
2235 tcg_target_call_clobber_regs
= 0;
2236 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_R0
);
2237 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_R1
);
2238 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_R2
);
2239 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_R3
);
2240 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_R12
);
2241 tcg_regset_set_reg(tcg_target_call_clobber_regs
, TCG_REG_R14
);
2243 s
->reserved_regs
= 0;
2244 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_CALL_STACK
);
2245 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_TMP
);
2246 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_PC
);
2249 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
2250 TCGReg arg1
, intptr_t arg2
)
2252 tcg_out_ld32u(s
, COND_AL
, arg
, arg1
, arg2
);
2255 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
2256 TCGReg arg1
, intptr_t arg2
)
2258 tcg_out_st32(s
, COND_AL
, arg
, arg1
, arg2
);
2261 static inline bool tcg_out_sti(TCGContext
*s
, TCGType type
, TCGArg val
,
2262 TCGReg base
, intptr_t ofs
)
2267 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
2268 TCGReg ret
, TCGReg arg
)
2270 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, ret
, 0, arg
, SHIFT_IMM_LSL(0));
2273 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
2274 TCGReg ret
, tcg_target_long arg
)
2276 tcg_out_movi32(s
, COND_AL
, ret
, arg
);
2279 static void tcg_out_nop_fill(tcg_insn_unit
*p
, int count
)
2282 for (i
= 0; i
< count
; ++i
) {
2287 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2288 and tcg_register_jit. */
2290 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2292 #define FRAME_SIZE \
2294 + TCG_STATIC_CALL_ARGS_SIZE \
2295 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2296 + TCG_TARGET_STACK_ALIGN - 1) \
2297 & -TCG_TARGET_STACK_ALIGN)
2299 static void tcg_target_qemu_prologue(TCGContext
*s
)
2303 /* Calling convention requires us to save r4-r11 and lr. */
2304 /* stmdb sp!, { r4 - r11, lr } */
2305 tcg_out32(s
, (COND_AL
<< 28) | 0x092d4ff0);
2307 /* Reserve callee argument and tcg temp space. */
2308 stack_addend
= FRAME_SIZE
- PUSH_SIZE
;
2310 tcg_out_dat_rI(s
, COND_AL
, ARITH_SUB
, TCG_REG_CALL_STACK
,
2311 TCG_REG_CALL_STACK
, stack_addend
, 1);
2312 tcg_set_frame(s
, TCG_REG_CALL_STACK
, TCG_STATIC_CALL_ARGS_SIZE
,
2313 CPU_TEMP_BUF_NLONGS
* sizeof(long));
2315 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
2317 tcg_out_bx(s
, COND_AL
, tcg_target_call_iarg_regs
[1]);
2320 * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2321 * and fall through to the rest of the epilogue.
2323 s
->code_gen_epilogue
= s
->code_ptr
;
2324 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_R0
, 0);
2327 tb_ret_addr
= s
->code_ptr
;
2328 tcg_out_dat_rI(s
, COND_AL
, ARITH_ADD
, TCG_REG_CALL_STACK
,
2329 TCG_REG_CALL_STACK
, stack_addend
, 1);
2331 /* ldmia sp!, { r4 - r11, pc } */
2332 tcg_out32(s
, (COND_AL
<< 28) | 0x08bd8ff0);
2337 uint8_t fde_def_cfa
[4];
2338 uint8_t fde_reg_ofs
[18];
2341 #define ELF_HOST_MACHINE EM_ARM
2343 /* We're expecting a 2 byte uleb128 encoded value. */
2344 QEMU_BUILD_BUG_ON(FRAME_SIZE
>= (1 << 14));
2346 static const DebugFrame debug_frame
= {
2347 .h
.cie
.len
= sizeof(DebugFrameCIE
)-4, /* length after .len member */
2350 .h
.cie
.code_align
= 1,
2351 .h
.cie
.data_align
= 0x7c, /* sleb128 -4 */
2352 .h
.cie
.return_column
= 14,
2354 /* Total FDE size does not include the "len" member. */
2355 .h
.fde
.len
= sizeof(DebugFrame
) - offsetof(DebugFrame
, h
.fde
.cie_offset
),
2358 12, 13, /* DW_CFA_def_cfa sp, ... */
2359 (FRAME_SIZE
& 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2363 /* The following must match the stmdb in the prologue. */
2364 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2365 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2366 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2367 0x89, 4, /* DW_CFA_offset, r9, -16 */
2368 0x88, 5, /* DW_CFA_offset, r8, -20 */
2369 0x87, 6, /* DW_CFA_offset, r7, -24 */
2370 0x86, 7, /* DW_CFA_offset, r6, -28 */
2371 0x85, 8, /* DW_CFA_offset, r5, -32 */
2372 0x84, 9, /* DW_CFA_offset, r4, -36 */
2376 void tcg_register_jit(void *buf
, size_t buf_size
)
2378 tcg_register_jit_int(buf
, buf_size
, &debug_frame
, sizeof(debug_frame
));