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-be-ldst.h"
28 /* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
30 # if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
31 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
32 || defined(__ARM_ARCH_7EM__)
34 # elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
35 || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
36 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
38 # elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
39 || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
40 || defined(__ARM_ARCH_5TEJ__)
47 static int arm_arch
= __ARM_ARCH
;
49 #if defined(__ARM_ARCH_5T__) \
50 || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
51 # define use_armv5t_instructions 1
53 # define use_armv5t_instructions use_armv6_instructions
56 #define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6)
57 #define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7)
59 #ifndef use_idiv_instructions
60 bool use_idiv_instructions
;
63 /* ??? Ought to think about changing CONFIG_SOFTMMU to always defined. */
65 # define USING_SOFTMMU 1
67 # define USING_SOFTMMU 0
71 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
91 static const int tcg_target_reg_alloc_order
[] = {
109 static const int tcg_target_call_iarg_regs
[4] = {
110 TCG_REG_R0
, TCG_REG_R1
, TCG_REG_R2
, TCG_REG_R3
112 static const int tcg_target_call_oarg_regs
[2] = {
113 TCG_REG_R0
, TCG_REG_R1
116 #define TCG_REG_TMP TCG_REG_R12
118 static inline void reloc_pc24(tcg_insn_unit
*code_ptr
, tcg_insn_unit
*target
)
120 ptrdiff_t offset
= (tcg_ptr_byte_diff(target
, code_ptr
) - 8) >> 2;
121 *code_ptr
= (*code_ptr
& ~0xffffff) | (offset
& 0xffffff);
124 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
125 intptr_t value
, intptr_t addend
)
127 assert(type
== R_ARM_PC24
);
129 reloc_pc24(code_ptr
, (tcg_insn_unit
*)value
);
132 #define TCG_CT_CONST_ARM 0x100
133 #define TCG_CT_CONST_INV 0x200
134 #define TCG_CT_CONST_NEG 0x400
135 #define TCG_CT_CONST_ZERO 0x800
137 /* parse target specific constraints */
138 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
145 ct
->ct
|= TCG_CT_CONST_ARM
;
148 ct
->ct
|= TCG_CT_CONST_INV
;
150 case 'N': /* The gcc constraint letter is L, already used here. */
151 ct
->ct
|= TCG_CT_CONST_NEG
;
154 ct
->ct
|= TCG_CT_CONST_ZERO
;
158 ct
->ct
|= TCG_CT_REG
;
159 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
162 /* qemu_ld address */
164 ct
->ct
|= TCG_CT_REG
;
165 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
166 #ifdef CONFIG_SOFTMMU
167 /* r0-r2,lr will be overwritten when reading the tlb entry,
168 so don't use these. */
169 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
170 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
171 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
172 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R14
);
176 /* qemu_st address & data */
178 ct
->ct
|= TCG_CT_REG
;
179 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
180 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
181 and r0-r1 doing the byte swapping, so don't use these. */
182 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
183 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
184 #if defined(CONFIG_SOFTMMU)
185 /* Avoid clashes with registers being used for helper args */
186 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
187 #if TARGET_LONG_BITS == 64
188 /* Avoid clashes with registers being used for helper args */
189 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R3
);
191 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R14
);
204 static inline uint32_t rotl(uint32_t val
, int n
)
206 return (val
<< n
) | (val
>> (32 - n
));
209 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
210 right-rotated by an even amount between 0 and 30. */
211 static inline int encode_imm(uint32_t imm
)
215 /* simple case, only lower bits */
216 if ((imm
& ~0xff) == 0)
218 /* then try a simple even shift */
219 shift
= ctz32(imm
) & ~1;
220 if (((imm
>> shift
) & ~0xff) == 0)
222 /* now try harder with rotations */
223 if ((rotl(imm
, 2) & ~0xff) == 0)
225 if ((rotl(imm
, 4) & ~0xff) == 0)
227 if ((rotl(imm
, 6) & ~0xff) == 0)
229 /* imm can't be encoded */
233 static inline int check_fit_imm(uint32_t imm
)
235 return encode_imm(imm
) >= 0;
238 /* Test if a constant matches the constraint.
239 * TODO: define constraints for:
241 * ldr/str offset: between -0xfff and 0xfff
242 * ldrh/strh offset: between -0xff and 0xff
243 * mov operand2: values represented with x << (2 * y), x < 0x100
244 * add, sub, eor...: ditto
246 static inline int tcg_target_const_match(tcg_target_long val
, TCGType type
,
247 const TCGArgConstraint
*arg_ct
)
251 if (ct
& TCG_CT_CONST
) {
253 } else if ((ct
& TCG_CT_CONST_ARM
) && check_fit_imm(val
)) {
255 } else if ((ct
& TCG_CT_CONST_INV
) && check_fit_imm(~val
)) {
257 } else if ((ct
& TCG_CT_CONST_NEG
) && check_fit_imm(-val
)) {
259 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
266 #define TO_CPSR (1 << 20)
269 ARITH_AND
= 0x0 << 21,
270 ARITH_EOR
= 0x1 << 21,
271 ARITH_SUB
= 0x2 << 21,
272 ARITH_RSB
= 0x3 << 21,
273 ARITH_ADD
= 0x4 << 21,
274 ARITH_ADC
= 0x5 << 21,
275 ARITH_SBC
= 0x6 << 21,
276 ARITH_RSC
= 0x7 << 21,
277 ARITH_TST
= 0x8 << 21 | TO_CPSR
,
278 ARITH_CMP
= 0xa << 21 | TO_CPSR
,
279 ARITH_CMN
= 0xb << 21 | TO_CPSR
,
280 ARITH_ORR
= 0xc << 21,
281 ARITH_MOV
= 0xd << 21,
282 ARITH_BIC
= 0xe << 21,
283 ARITH_MVN
= 0xf << 21,
285 INSN_LDR_IMM
= 0x04100000,
286 INSN_LDR_REG
= 0x06100000,
287 INSN_STR_IMM
= 0x04000000,
288 INSN_STR_REG
= 0x06000000,
290 INSN_LDRH_IMM
= 0x005000b0,
291 INSN_LDRH_REG
= 0x001000b0,
292 INSN_LDRSH_IMM
= 0x005000f0,
293 INSN_LDRSH_REG
= 0x001000f0,
294 INSN_STRH_IMM
= 0x004000b0,
295 INSN_STRH_REG
= 0x000000b0,
297 INSN_LDRB_IMM
= 0x04500000,
298 INSN_LDRB_REG
= 0x06500000,
299 INSN_LDRSB_IMM
= 0x005000d0,
300 INSN_LDRSB_REG
= 0x001000d0,
301 INSN_STRB_IMM
= 0x04400000,
302 INSN_STRB_REG
= 0x06400000,
304 INSN_LDRD_IMM
= 0x004000d0,
305 INSN_LDRD_REG
= 0x000000d0,
306 INSN_STRD_IMM
= 0x004000f0,
307 INSN_STRD_REG
= 0x000000f0,
310 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
311 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
312 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
313 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
314 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
315 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
316 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
317 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
319 enum arm_cond_code_e
{
322 COND_CS
= 0x2, /* Unsigned greater or equal */
323 COND_CC
= 0x3, /* Unsigned less than */
324 COND_MI
= 0x4, /* Negative */
325 COND_PL
= 0x5, /* Zero or greater */
326 COND_VS
= 0x6, /* Overflow */
327 COND_VC
= 0x7, /* No overflow */
328 COND_HI
= 0x8, /* Unsigned greater than */
329 COND_LS
= 0x9, /* Unsigned less or equal */
337 static const uint8_t tcg_cond_to_arm_cond
[] = {
338 [TCG_COND_EQ
] = COND_EQ
,
339 [TCG_COND_NE
] = COND_NE
,
340 [TCG_COND_LT
] = COND_LT
,
341 [TCG_COND_GE
] = COND_GE
,
342 [TCG_COND_LE
] = COND_LE
,
343 [TCG_COND_GT
] = COND_GT
,
345 [TCG_COND_LTU
] = COND_CC
,
346 [TCG_COND_GEU
] = COND_CS
,
347 [TCG_COND_LEU
] = COND_LS
,
348 [TCG_COND_GTU
] = COND_HI
,
351 static inline void tcg_out_bx(TCGContext
*s
, int cond
, int rn
)
353 tcg_out32(s
, (cond
<< 28) | 0x012fff10 | rn
);
356 static inline void tcg_out_b(TCGContext
*s
, int cond
, int32_t offset
)
358 tcg_out32(s
, (cond
<< 28) | 0x0a000000 |
359 (((offset
- 8) >> 2) & 0x00ffffff));
362 static inline void tcg_out_b_noaddr(TCGContext
*s
, int cond
)
364 /* We pay attention here to not modify the branch target by masking
365 the corresponding bytes. This ensure that caches and memory are
366 kept coherent during retranslation. */
367 tcg_out32(s
, deposit32(*s
->code_ptr
, 24, 8, (cond
<< 4) | 0x0a));
370 static inline void tcg_out_bl_noaddr(TCGContext
*s
, int cond
)
372 /* We pay attention here to not modify the branch target by masking
373 the corresponding bytes. This ensure that caches and memory are
374 kept coherent during retranslation. */
375 tcg_out32(s
, deposit32(*s
->code_ptr
, 24, 8, (cond
<< 4) | 0x0b));
378 static inline void tcg_out_bl(TCGContext
*s
, int cond
, int32_t offset
)
380 tcg_out32(s
, (cond
<< 28) | 0x0b000000 |
381 (((offset
- 8) >> 2) & 0x00ffffff));
384 static inline void tcg_out_blx(TCGContext
*s
, int cond
, int rn
)
386 tcg_out32(s
, (cond
<< 28) | 0x012fff30 | rn
);
389 static inline void tcg_out_blx_imm(TCGContext
*s
, int32_t offset
)
391 tcg_out32(s
, 0xfa000000 | ((offset
& 2) << 23) |
392 (((offset
- 8) >> 2) & 0x00ffffff));
395 static inline void tcg_out_dat_reg(TCGContext
*s
,
396 int cond
, int opc
, int rd
, int rn
, int rm
, int shift
)
398 tcg_out32(s
, (cond
<< 28) | (0 << 25) | opc
|
399 (rn
<< 16) | (rd
<< 12) | shift
| rm
);
402 static inline void tcg_out_nop(TCGContext
*s
)
404 if (use_armv7_instructions
) {
405 /* Architected nop introduced in v6k. */
406 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
407 also Just So Happened to do nothing on pre-v6k so that we
408 don't need to conditionalize it? */
409 tcg_out32(s
, 0xe320f000);
411 /* Prior to that the assembler uses mov r0, r0. */
412 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, 0, 0, 0, SHIFT_IMM_LSL(0));
416 static inline void tcg_out_mov_reg(TCGContext
*s
, int cond
, int rd
, int rm
)
418 /* Simple reg-reg move, optimising out the 'do nothing' case */
420 tcg_out_dat_reg(s
, cond
, ARITH_MOV
, rd
, 0, rm
, SHIFT_IMM_LSL(0));
424 static inline void tcg_out_dat_imm(TCGContext
*s
,
425 int cond
, int opc
, int rd
, int rn
, int im
)
427 tcg_out32(s
, (cond
<< 28) | (1 << 25) | opc
|
428 (rn
<< 16) | (rd
<< 12) | im
);
431 static void tcg_out_movi32(TCGContext
*s
, int cond
, int rd
, uint32_t arg
)
435 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
436 Speed things up by only checking when movt would be required.
437 Prior to armv7, have one go at fully rotated immediates before
438 doing the decomposition thing below. */
439 if (!use_armv7_instructions
|| (arg
& 0xffff0000)) {
440 rot
= encode_imm(arg
);
442 tcg_out_dat_imm(s
, cond
, ARITH_MOV
, rd
, 0,
443 rotl(arg
, rot
) | (rot
<< 7));
446 rot
= encode_imm(~arg
);
448 tcg_out_dat_imm(s
, cond
, ARITH_MVN
, rd
, 0,
449 rotl(~arg
, rot
) | (rot
<< 7));
454 /* Use movw + movt. */
455 if (use_armv7_instructions
) {
457 tcg_out32(s
, (cond
<< 28) | 0x03000000 | (rd
<< 12)
458 | ((arg
<< 4) & 0x000f0000) | (arg
& 0xfff));
459 if (arg
& 0xffff0000) {
461 tcg_out32(s
, (cond
<< 28) | 0x03400000 | (rd
<< 12)
462 | ((arg
>> 12) & 0x000f0000) | ((arg
>> 16) & 0xfff));
467 /* TODO: This is very suboptimal, we can easily have a constant
468 pool somewhere after all the instructions. */
471 /* If we have lots of leading 1's, we can shorten the sequence by
472 beginning with mvn and then clearing higher bits with eor. */
473 if (clz32(~arg
) > clz32(arg
)) {
474 opc
= ARITH_MVN
, arg
= ~arg
;
477 int i
= ctz32(arg
) & ~1;
478 rot
= ((32 - i
) << 7) & 0xf00;
479 tcg_out_dat_imm(s
, cond
, opc
, rd
, rn
, ((arg
>> i
) & 0xff) | rot
);
487 static inline void tcg_out_dat_rI(TCGContext
*s
, int cond
, int opc
, TCGArg dst
,
488 TCGArg lhs
, TCGArg rhs
, int rhs_is_const
)
490 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
491 * rhs must satisfy the "rI" constraint.
494 int rot
= encode_imm(rhs
);
496 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
498 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
502 static void tcg_out_dat_rIK(TCGContext
*s
, int cond
, int opc
, int opinv
,
503 TCGReg dst
, TCGReg lhs
, TCGArg rhs
,
506 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
507 * rhs must satisfy the "rIK" constraint.
510 int rot
= encode_imm(rhs
);
513 rot
= encode_imm(rhs
);
517 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
519 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
523 static void tcg_out_dat_rIN(TCGContext
*s
, int cond
, int opc
, int opneg
,
524 TCGArg dst
, TCGArg lhs
, TCGArg rhs
,
527 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
528 * rhs must satisfy the "rIN" constraint.
531 int rot
= encode_imm(rhs
);
534 rot
= encode_imm(rhs
);
538 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
540 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
544 static inline void tcg_out_mul32(TCGContext
*s
, int cond
, TCGReg rd
,
545 TCGReg rn
, TCGReg rm
)
547 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
548 if (!use_armv6_instructions
&& rd
== rn
) {
550 /* rd == rn == rm; copy an input to tmp first. */
551 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
552 rm
= rn
= TCG_REG_TMP
;
559 tcg_out32(s
, (cond
<< 28) | 0x90 | (rd
<< 16) | (rm
<< 8) | rn
);
562 static inline void tcg_out_umull32(TCGContext
*s
, int cond
, TCGReg rd0
,
563 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
565 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
566 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
567 if (rd0
== rm
|| rd1
== rm
) {
568 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
577 tcg_out32(s
, (cond
<< 28) | 0x00800090 |
578 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
581 static inline void tcg_out_smull32(TCGContext
*s
, int cond
, TCGReg rd0
,
582 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
584 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
585 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
586 if (rd0
== rm
|| rd1
== rm
) {
587 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
596 tcg_out32(s
, (cond
<< 28) | 0x00c00090 |
597 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
600 static inline void tcg_out_sdiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
602 tcg_out32(s
, 0x0710f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
605 static inline void tcg_out_udiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
607 tcg_out32(s
, 0x0730f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
610 static inline void tcg_out_ext8s(TCGContext
*s
, int cond
,
613 if (use_armv6_instructions
) {
615 tcg_out32(s
, 0x06af0070 | (cond
<< 28) | (rd
<< 12) | rn
);
617 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
618 rd
, 0, rn
, SHIFT_IMM_LSL(24));
619 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
620 rd
, 0, rd
, SHIFT_IMM_ASR(24));
624 static inline void tcg_out_ext8u(TCGContext
*s
, int cond
,
627 tcg_out_dat_imm(s
, cond
, ARITH_AND
, rd
, rn
, 0xff);
630 static inline void tcg_out_ext16s(TCGContext
*s
, int cond
,
633 if (use_armv6_instructions
) {
635 tcg_out32(s
, 0x06bf0070 | (cond
<< 28) | (rd
<< 12) | rn
);
637 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
638 rd
, 0, rn
, SHIFT_IMM_LSL(16));
639 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
640 rd
, 0, rd
, SHIFT_IMM_ASR(16));
644 static inline void tcg_out_ext16u(TCGContext
*s
, int cond
,
647 if (use_armv6_instructions
) {
649 tcg_out32(s
, 0x06ff0070 | (cond
<< 28) | (rd
<< 12) | rn
);
651 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
652 rd
, 0, rn
, SHIFT_IMM_LSL(16));
653 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
654 rd
, 0, rd
, SHIFT_IMM_LSR(16));
658 static inline void tcg_out_bswap16s(TCGContext
*s
, int cond
, int rd
, int rn
)
660 if (use_armv6_instructions
) {
662 tcg_out32(s
, 0x06ff0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
664 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
665 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
666 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
667 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_ASR(16));
668 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
669 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
673 static inline void tcg_out_bswap16(TCGContext
*s
, int cond
, int rd
, int rn
)
675 if (use_armv6_instructions
) {
677 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
679 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
680 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
681 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
682 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_LSR(16));
683 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
684 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
688 /* swap the two low bytes assuming that the two high input bytes and the
689 two high output bit can hold any value. */
690 static inline void tcg_out_bswap16st(TCGContext
*s
, int cond
, int rd
, int rn
)
692 if (use_armv6_instructions
) {
694 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
696 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
697 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSR(8));
698 tcg_out_dat_imm(s
, cond
, ARITH_AND
, TCG_REG_TMP
, TCG_REG_TMP
, 0xff);
699 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
700 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSL(8));
704 static inline void tcg_out_bswap32(TCGContext
*s
, int cond
, int rd
, int rn
)
706 if (use_armv6_instructions
) {
708 tcg_out32(s
, 0x06bf0f30 | (cond
<< 28) | (rd
<< 12) | rn
);
710 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
711 TCG_REG_TMP
, rn
, rn
, SHIFT_IMM_ROR(16));
712 tcg_out_dat_imm(s
, cond
, ARITH_BIC
,
713 TCG_REG_TMP
, TCG_REG_TMP
, 0xff | 0x800);
714 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
715 rd
, 0, rn
, SHIFT_IMM_ROR(8));
716 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
717 rd
, rd
, TCG_REG_TMP
, SHIFT_IMM_LSR(8));
721 bool tcg_target_deposit_valid(int ofs
, int len
)
723 /* ??? Without bfi, we could improve over generic code by combining
724 the right-shift from a non-zero ofs with the orr. We do run into
725 problems when rd == rs, and the mask generated from ofs+len doesn't
726 fit into an immediate. We would have to be careful not to pessimize
727 wrt the optimizations performed on the expanded code. */
728 return use_armv7_instructions
;
731 static inline void tcg_out_deposit(TCGContext
*s
, int cond
, TCGReg rd
,
732 TCGArg a1
, int ofs
, int len
, bool const_a1
)
735 /* bfi becomes bfc with rn == 15. */
739 tcg_out32(s
, 0x07c00010 | (cond
<< 28) | (rd
<< 12) | a1
740 | (ofs
<< 7) | ((ofs
+ len
- 1) << 16));
743 /* Note that this routine is used for both LDR and LDRH formats, so we do
744 not wish to include an immediate shift at this point. */
745 static void tcg_out_memop_r(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
746 TCGReg rn
, TCGReg rm
, bool u
, bool p
, bool w
)
748 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24)
749 | (w
<< 21) | (rn
<< 16) | (rt
<< 12) | rm
);
752 static void tcg_out_memop_8(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
753 TCGReg rn
, int imm8
, bool p
, bool w
)
760 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
761 (rn
<< 16) | (rt
<< 12) | ((imm8
& 0xf0) << 4) | (imm8
& 0xf));
764 static void tcg_out_memop_12(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
765 TCGReg rn
, int imm12
, bool p
, bool w
)
772 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
773 (rn
<< 16) | (rt
<< 12) | imm12
);
776 static inline void tcg_out_ld32_12(TCGContext
*s
, int cond
, TCGReg rt
,
777 TCGReg rn
, int imm12
)
779 tcg_out_memop_12(s
, cond
, INSN_LDR_IMM
, rt
, rn
, imm12
, 1, 0);
782 static inline void tcg_out_st32_12(TCGContext
*s
, int cond
, TCGReg rt
,
783 TCGReg rn
, int imm12
)
785 tcg_out_memop_12(s
, cond
, INSN_STR_IMM
, rt
, rn
, imm12
, 1, 0);
788 static inline void tcg_out_ld32_r(TCGContext
*s
, int cond
, TCGReg rt
,
789 TCGReg rn
, TCGReg rm
)
791 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 0);
794 static inline void tcg_out_st32_r(TCGContext
*s
, int cond
, TCGReg rt
,
795 TCGReg rn
, TCGReg rm
)
797 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 0);
800 static inline void tcg_out_ldrd_8(TCGContext
*s
, int cond
, TCGReg rt
,
803 tcg_out_memop_8(s
, cond
, INSN_LDRD_IMM
, rt
, rn
, imm8
, 1, 0);
806 static inline void tcg_out_ldrd_r(TCGContext
*s
, int cond
, TCGReg rt
,
807 TCGReg rn
, TCGReg rm
)
809 tcg_out_memop_r(s
, cond
, INSN_LDRD_REG
, rt
, rn
, rm
, 1, 1, 0);
812 static inline void tcg_out_strd_8(TCGContext
*s
, int cond
, TCGReg rt
,
815 tcg_out_memop_8(s
, cond
, INSN_STRD_IMM
, rt
, rn
, imm8
, 1, 0);
818 static inline void tcg_out_strd_r(TCGContext
*s
, int cond
, TCGReg rt
,
819 TCGReg rn
, TCGReg rm
)
821 tcg_out_memop_r(s
, cond
, INSN_STRD_REG
, rt
, rn
, rm
, 1, 1, 0);
824 /* Register pre-increment with base writeback. */
825 static inline void tcg_out_ld32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
826 TCGReg rn
, TCGReg rm
)
828 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 1);
831 static inline void tcg_out_st32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
832 TCGReg rn
, TCGReg rm
)
834 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 1);
837 static inline void tcg_out_ld16u_8(TCGContext
*s
, int cond
, TCGReg rt
,
840 tcg_out_memop_8(s
, cond
, INSN_LDRH_IMM
, rt
, rn
, imm8
, 1, 0);
843 static inline void tcg_out_st16_8(TCGContext
*s
, int cond
, TCGReg rt
,
846 tcg_out_memop_8(s
, cond
, INSN_STRH_IMM
, rt
, rn
, imm8
, 1, 0);
849 static inline void tcg_out_ld16u_r(TCGContext
*s
, int cond
, TCGReg rt
,
850 TCGReg rn
, TCGReg rm
)
852 tcg_out_memop_r(s
, cond
, INSN_LDRH_REG
, rt
, rn
, rm
, 1, 1, 0);
855 static inline void tcg_out_st16_r(TCGContext
*s
, int cond
, TCGReg rt
,
856 TCGReg rn
, TCGReg rm
)
858 tcg_out_memop_r(s
, cond
, INSN_STRH_REG
, rt
, rn
, rm
, 1, 1, 0);
861 static inline void tcg_out_ld16s_8(TCGContext
*s
, int cond
, TCGReg rt
,
864 tcg_out_memop_8(s
, cond
, INSN_LDRSH_IMM
, rt
, rn
, imm8
, 1, 0);
867 static inline void tcg_out_ld16s_r(TCGContext
*s
, int cond
, TCGReg rt
,
868 TCGReg rn
, TCGReg rm
)
870 tcg_out_memop_r(s
, cond
, INSN_LDRSH_REG
, rt
, rn
, rm
, 1, 1, 0);
873 static inline void tcg_out_ld8_12(TCGContext
*s
, int cond
, TCGReg rt
,
874 TCGReg rn
, int imm12
)
876 tcg_out_memop_12(s
, cond
, INSN_LDRB_IMM
, rt
, rn
, imm12
, 1, 0);
879 static inline void tcg_out_st8_12(TCGContext
*s
, int cond
, TCGReg rt
,
880 TCGReg rn
, int imm12
)
882 tcg_out_memop_12(s
, cond
, INSN_STRB_IMM
, rt
, rn
, imm12
, 1, 0);
885 static inline void tcg_out_ld8_r(TCGContext
*s
, int cond
, TCGReg rt
,
886 TCGReg rn
, TCGReg rm
)
888 tcg_out_memop_r(s
, cond
, INSN_LDRB_REG
, rt
, rn
, rm
, 1, 1, 0);
891 static inline void tcg_out_st8_r(TCGContext
*s
, int cond
, TCGReg rt
,
892 TCGReg rn
, TCGReg rm
)
894 tcg_out_memop_r(s
, cond
, INSN_STRB_REG
, rt
, rn
, rm
, 1, 1, 0);
897 static inline void tcg_out_ld8s_8(TCGContext
*s
, int cond
, TCGReg rt
,
900 tcg_out_memop_8(s
, cond
, INSN_LDRSB_IMM
, rt
, rn
, imm8
, 1, 0);
903 static inline void tcg_out_ld8s_r(TCGContext
*s
, int cond
, TCGReg rt
,
904 TCGReg rn
, TCGReg rm
)
906 tcg_out_memop_r(s
, cond
, INSN_LDRSB_REG
, rt
, rn
, rm
, 1, 1, 0);
909 static inline void tcg_out_ld32u(TCGContext
*s
, int cond
,
910 int rd
, int rn
, int32_t offset
)
912 if (offset
> 0xfff || offset
< -0xfff) {
913 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
914 tcg_out_ld32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
916 tcg_out_ld32_12(s
, cond
, rd
, rn
, offset
);
919 static inline void tcg_out_st32(TCGContext
*s
, int cond
,
920 int rd
, int rn
, int32_t offset
)
922 if (offset
> 0xfff || offset
< -0xfff) {
923 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
924 tcg_out_st32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
926 tcg_out_st32_12(s
, cond
, rd
, rn
, offset
);
929 static inline void tcg_out_ld16u(TCGContext
*s
, int cond
,
930 int rd
, int rn
, int32_t offset
)
932 if (offset
> 0xff || offset
< -0xff) {
933 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
934 tcg_out_ld16u_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
936 tcg_out_ld16u_8(s
, cond
, rd
, rn
, offset
);
939 static inline void tcg_out_ld16s(TCGContext
*s
, int cond
,
940 int rd
, int rn
, int32_t offset
)
942 if (offset
> 0xff || offset
< -0xff) {
943 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
944 tcg_out_ld16s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
946 tcg_out_ld16s_8(s
, cond
, rd
, rn
, offset
);
949 static inline void tcg_out_st16(TCGContext
*s
, int cond
,
950 int rd
, int rn
, int32_t offset
)
952 if (offset
> 0xff || offset
< -0xff) {
953 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
954 tcg_out_st16_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
956 tcg_out_st16_8(s
, cond
, rd
, rn
, offset
);
959 static inline void tcg_out_ld8u(TCGContext
*s
, int cond
,
960 int rd
, int rn
, int32_t offset
)
962 if (offset
> 0xfff || offset
< -0xfff) {
963 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
964 tcg_out_ld8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
966 tcg_out_ld8_12(s
, cond
, rd
, rn
, offset
);
969 static inline void tcg_out_ld8s(TCGContext
*s
, int cond
,
970 int rd
, int rn
, int32_t offset
)
972 if (offset
> 0xff || offset
< -0xff) {
973 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
974 tcg_out_ld8s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
976 tcg_out_ld8s_8(s
, cond
, rd
, rn
, offset
);
979 static inline void tcg_out_st8(TCGContext
*s
, int cond
,
980 int rd
, int rn
, int32_t offset
)
982 if (offset
> 0xfff || offset
< -0xfff) {
983 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
984 tcg_out_st8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
986 tcg_out_st8_12(s
, cond
, rd
, rn
, offset
);
989 /* The _goto case is normally between TBs within the same code buffer, and
990 * with the code buffer limited to 16MB we wouldn't need the long case.
991 * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
993 static inline void tcg_out_goto(TCGContext
*s
, int cond
, tcg_insn_unit
*addr
)
995 intptr_t addri
= (intptr_t)addr
;
996 ptrdiff_t disp
= tcg_pcrel_diff(s
, addr
);
998 if ((addri
& 1) == 0 && disp
- 8 < 0x01fffffd && disp
- 8 > -0x01fffffd) {
999 tcg_out_b(s
, cond
, disp
);
1003 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, addri
);
1004 if (use_armv5t_instructions
) {
1005 tcg_out_bx(s
, cond
, TCG_REG_TMP
);
1010 tcg_out_mov_reg(s
, cond
, TCG_REG_PC
, TCG_REG_TMP
);
1014 /* The call case is mostly used for helpers - so it's not unreasonable
1015 * for them to be beyond branch range */
1016 static void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*addr
)
1018 intptr_t addri
= (intptr_t)addr
;
1019 ptrdiff_t disp
= tcg_pcrel_diff(s
, addr
);
1021 if (disp
- 8 < 0x02000000 && disp
- 8 >= -0x02000000) {
1023 /* Use BLX if the target is in Thumb mode */
1024 if (!use_armv5t_instructions
) {
1027 tcg_out_blx_imm(s
, disp
);
1029 tcg_out_bl(s
, COND_AL
, disp
);
1031 } else if (use_armv7_instructions
) {
1032 tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, addri
);
1033 tcg_out_blx(s
, COND_AL
, TCG_REG_TMP
);
1035 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R14
, TCG_REG_PC
, 4);
1036 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1037 tcg_out32(s
, addri
);
1041 static inline void tcg_out_goto_label(TCGContext
*s
, int cond
, int label_index
)
1043 TCGLabel
*l
= &s
->labels
[label_index
];
1046 tcg_out_goto(s
, cond
, l
->u
.value_ptr
);
1048 tcg_out_reloc(s
, s
->code_ptr
, R_ARM_PC24
, label_index
, 0);
1049 tcg_out_b_noaddr(s
, cond
);
1053 #ifdef CONFIG_SOFTMMU
1054 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1055 * int mmu_idx, uintptr_t ra)
1057 static void * const qemu_ld_helpers
[16] = {
1058 [MO_UB
] = helper_ret_ldub_mmu
,
1059 [MO_SB
] = helper_ret_ldsb_mmu
,
1061 [MO_LEUW
] = helper_le_lduw_mmu
,
1062 [MO_LEUL
] = helper_le_ldul_mmu
,
1063 [MO_LEQ
] = helper_le_ldq_mmu
,
1064 [MO_LESW
] = helper_le_ldsw_mmu
,
1065 [MO_LESL
] = helper_le_ldul_mmu
,
1067 [MO_BEUW
] = helper_be_lduw_mmu
,
1068 [MO_BEUL
] = helper_be_ldul_mmu
,
1069 [MO_BEQ
] = helper_be_ldq_mmu
,
1070 [MO_BESW
] = helper_be_ldsw_mmu
,
1071 [MO_BESL
] = helper_be_ldul_mmu
,
1074 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1075 * uintxx_t val, int mmu_idx, uintptr_t ra)
1077 static void * const qemu_st_helpers
[16] = {
1078 [MO_UB
] = helper_ret_stb_mmu
,
1079 [MO_LEUW
] = helper_le_stw_mmu
,
1080 [MO_LEUL
] = helper_le_stl_mmu
,
1081 [MO_LEQ
] = helper_le_stq_mmu
,
1082 [MO_BEUW
] = helper_be_stw_mmu
,
1083 [MO_BEUL
] = helper_be_stl_mmu
,
1084 [MO_BEQ
] = helper_be_stq_mmu
,
1087 /* Helper routines for marshalling helper function arguments into
1088 * the correct registers and stack.
1089 * argreg is where we want to put this argument, arg is the argument itself.
1090 * Return value is the updated argreg ready for the next call.
1091 * Note that argreg 0..3 is real registers, 4+ on stack.
1093 * We provide routines for arguments which are: immediate, 32 bit
1094 * value in register, 16 and 8 bit values in register (which must be zero
1095 * extended before use) and 64 bit value in a lo:hi register pair.
1097 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1098 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1101 MOV_ARG(s, COND_AL, argreg, arg); \
1103 int ofs = (argreg - 4) * 4; \
1105 assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1106 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1108 return argreg + 1; \
1111 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32
, uint32_t, tcg_out_movi32
,
1112 (tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1113 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8
, TCGReg
, tcg_out_ext8u
,
1114 (tcg_out_ext8u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1115 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16
, TCGReg
, tcg_out_ext16u
,
1116 (tcg_out_ext16u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1117 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32
, TCGReg
, tcg_out_mov_reg
, )
1119 static TCGReg
tcg_out_arg_reg64(TCGContext
*s
, TCGReg argreg
,
1120 TCGReg arglo
, TCGReg arghi
)
1122 /* 64 bit arguments must go in even/odd register pairs
1123 * and in 8-aligned stack slots.
1128 if (use_armv6_instructions
&& argreg
>= 4
1129 && (arglo
& 1) == 0 && arghi
== arglo
+ 1) {
1130 tcg_out_strd_8(s
, COND_AL
, arglo
,
1131 TCG_REG_CALL_STACK
, (argreg
- 4) * 4);
1134 argreg
= tcg_out_arg_reg32(s
, argreg
, arglo
);
1135 argreg
= tcg_out_arg_reg32(s
, argreg
, arghi
);
1140 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1142 /* We're expecting to use an 8-bit immediate and to mask. */
1143 QEMU_BUILD_BUG_ON(CPU_TLB_BITS
> 8);
1145 /* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset.
1146 Using the offset of the second entry in the last tlb table ensures
1147 that we can index all of the elements of the first entry. */
1148 QEMU_BUILD_BUG_ON(offsetof(CPUArchState
, tlb_table
[NB_MMU_MODES
- 1][1])
1151 /* Load and compare a TLB entry, leaving the flags set. Returns the register
1152 containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
1154 static TCGReg
tcg_out_tlb_read(TCGContext
*s
, TCGReg addrlo
, TCGReg addrhi
,
1155 TCGMemOp s_bits
, int mem_index
, bool is_load
)
1157 TCGReg base
= TCG_AREG0
;
1160 ? offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1161 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
));
1162 int add_off
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addend
);
1164 /* Should generate something like the following:
1165 * shr tmp, addrlo, #TARGET_PAGE_BITS (1)
1166 * add r2, env, #high
1167 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1168 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1169 * ldr r0, [r2, #cmp] (4)
1170 * tst addrlo, #s_mask
1171 * ldr r2, [r2, #add] (5)
1172 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS
1174 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, TCG_REG_TMP
,
1175 0, addrlo
, SHIFT_IMM_LSR(TARGET_PAGE_BITS
));
1177 /* We checked that the offset is contained within 16 bits above. */
1178 if (add_off
> 0xfff || (use_armv6_instructions
&& cmp_off
> 0xff)) {
1179 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1180 (24 << 7) | (cmp_off
>> 8));
1182 add_off
-= cmp_off
& 0xff00;
1186 tcg_out_dat_imm(s
, COND_AL
, ARITH_AND
,
1187 TCG_REG_R0
, TCG_REG_TMP
, CPU_TLB_SIZE
- 1);
1188 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1189 TCG_REG_R0
, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS
));
1191 /* Load the tlb comparator. Use ldrd if needed and available,
1192 but due to how the pointer needs setting up, ldm isn't useful.
1193 Base arm5 doesn't have ldrd, but armv5te does. */
1194 if (use_armv6_instructions
&& TARGET_LONG_BITS
== 64) {
1195 tcg_out_ldrd_8(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R2
, cmp_off
);
1197 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R2
, cmp_off
);
1198 if (TARGET_LONG_BITS
== 64) {
1199 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R1
, TCG_REG_R2
, cmp_off
+ 4);
1203 /* Check alignment. */
1205 tcg_out_dat_imm(s
, COND_AL
, ARITH_TST
,
1206 0, addrlo
, (1 << s_bits
) - 1);
1209 /* Load the tlb addend. */
1210 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R2
, TCG_REG_R2
, add_off
);
1212 tcg_out_dat_reg(s
, (s_bits
? COND_EQ
: COND_AL
), ARITH_CMP
, 0,
1213 TCG_REG_R0
, TCG_REG_TMP
, SHIFT_IMM_LSL(TARGET_PAGE_BITS
));
1215 if (TARGET_LONG_BITS
== 64) {
1216 tcg_out_dat_reg(s
, COND_EQ
, ARITH_CMP
, 0,
1217 TCG_REG_R1
, addrhi
, SHIFT_IMM_LSL(0));
1223 /* Record the context of a call to the out of line helper code for the slow
1224 path for a load or store, so that we can later generate the correct
1226 static void add_qemu_ldst_label(TCGContext
*s
, bool is_ld
, TCGMemOp opc
,
1227 TCGReg datalo
, TCGReg datahi
, TCGReg addrlo
,
1228 TCGReg addrhi
, int mem_index
,
1229 tcg_insn_unit
*raddr
, tcg_insn_unit
*label_ptr
)
1231 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1233 label
->is_ld
= is_ld
;
1235 label
->datalo_reg
= datalo
;
1236 label
->datahi_reg
= datahi
;
1237 label
->addrlo_reg
= addrlo
;
1238 label
->addrhi_reg
= addrhi
;
1239 label
->mem_index
= mem_index
;
1240 label
->raddr
= raddr
;
1241 label
->label_ptr
[0] = label_ptr
;
1244 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1246 TCGReg argreg
, datalo
, datahi
;
1247 TCGMemOp opc
= lb
->opc
;
1250 reloc_pc24(lb
->label_ptr
[0], s
->code_ptr
);
1252 argreg
= tcg_out_arg_reg32(s
, TCG_REG_R0
, TCG_AREG0
);
1253 if (TARGET_LONG_BITS
== 64) {
1254 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1256 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1258 argreg
= tcg_out_arg_imm32(s
, argreg
, lb
->mem_index
);
1259 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_REG_R14
);
1261 /* For armv6 we can use the canonical unsigned helpers and minimize
1262 icache usage. For pre-armv6, use the signed helpers since we do
1263 not have a single insn sign-extend. */
1264 if (use_armv6_instructions
) {
1265 func
= qemu_ld_helpers
[opc
& ~MO_SIGN
];
1267 func
= qemu_ld_helpers
[opc
];
1268 if (opc
& MO_SIGN
) {
1272 tcg_out_call(s
, func
);
1274 datalo
= lb
->datalo_reg
;
1275 datahi
= lb
->datahi_reg
;
1276 switch (opc
& MO_SSIZE
) {
1278 tcg_out_ext8s(s
, COND_AL
, datalo
, TCG_REG_R0
);
1281 tcg_out_ext16s(s
, COND_AL
, datalo
, TCG_REG_R0
);
1284 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1287 if (datalo
!= TCG_REG_R1
) {
1288 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1289 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1290 } else if (datahi
!= TCG_REG_R0
) {
1291 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1292 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1294 tcg_out_mov_reg(s
, COND_AL
, TCG_REG_TMP
, TCG_REG_R0
);
1295 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1296 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_TMP
);
1301 tcg_out_goto(s
, COND_AL
, lb
->raddr
);
1304 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1306 TCGReg argreg
, datalo
, datahi
;
1307 TCGMemOp opc
= lb
->opc
;
1309 reloc_pc24(lb
->label_ptr
[0], s
->code_ptr
);
1311 argreg
= TCG_REG_R0
;
1312 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_AREG0
);
1313 if (TARGET_LONG_BITS
== 64) {
1314 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1316 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1319 datalo
= lb
->datalo_reg
;
1320 datahi
= lb
->datahi_reg
;
1321 switch (opc
& MO_SIZE
) {
1323 argreg
= tcg_out_arg_reg8(s
, argreg
, datalo
);
1326 argreg
= tcg_out_arg_reg16(s
, argreg
, datalo
);
1330 argreg
= tcg_out_arg_reg32(s
, argreg
, datalo
);
1333 argreg
= tcg_out_arg_reg64(s
, argreg
, datalo
, datahi
);
1337 argreg
= tcg_out_arg_imm32(s
, argreg
, lb
->mem_index
);
1338 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_REG_R14
);
1340 /* Tail-call to the helper, which will return to the fast path. */
1341 tcg_out_goto(s
, COND_AL
, qemu_st_helpers
[opc
]);
1343 #endif /* SOFTMMU */
1345 static inline void tcg_out_qemu_ld_index(TCGContext
*s
, TCGMemOp opc
,
1346 TCGReg datalo
, TCGReg datahi
,
1347 TCGReg addrlo
, TCGReg addend
)
1349 TCGMemOp bswap
= opc
& MO_BSWAP
;
1351 switch (opc
& MO_SSIZE
) {
1353 tcg_out_ld8_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1356 tcg_out_ld8s_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1359 tcg_out_ld16u_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1361 tcg_out_bswap16(s
, COND_AL
, datalo
, datalo
);
1366 tcg_out_ld16u_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1367 tcg_out_bswap16s(s
, COND_AL
, datalo
, datalo
);
1369 tcg_out_ld16s_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1374 tcg_out_ld32_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1376 tcg_out_bswap32(s
, COND_AL
, datalo
, datalo
);
1381 TCGReg dl
= (bswap
? datahi
: datalo
);
1382 TCGReg dh
= (bswap
? datalo
: datahi
);
1384 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1385 if (USING_SOFTMMU
&& use_armv6_instructions
1386 && (dl
& 1) == 0 && dh
== dl
+ 1) {
1387 tcg_out_ldrd_r(s
, COND_AL
, dl
, addrlo
, addend
);
1388 } else if (dl
!= addend
) {
1389 tcg_out_ld32_rwb(s
, COND_AL
, dl
, addend
, addrlo
);
1390 tcg_out_ld32_12(s
, COND_AL
, dh
, addend
, 4);
1392 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_TMP
,
1393 addend
, addrlo
, SHIFT_IMM_LSL(0));
1394 tcg_out_ld32_12(s
, COND_AL
, dl
, TCG_REG_TMP
, 0);
1395 tcg_out_ld32_12(s
, COND_AL
, dh
, TCG_REG_TMP
, 4);
1398 tcg_out_bswap32(s
, COND_AL
, dl
, dl
);
1399 tcg_out_bswap32(s
, COND_AL
, dh
, dh
);
1406 static inline void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGMemOp opc
,
1407 TCGReg datalo
, TCGReg datahi
,
1410 TCGMemOp bswap
= opc
& MO_BSWAP
;
1412 switch (opc
& MO_SSIZE
) {
1414 tcg_out_ld8_12(s
, COND_AL
, datalo
, addrlo
, 0);
1417 tcg_out_ld8s_8(s
, COND_AL
, datalo
, addrlo
, 0);
1420 tcg_out_ld16u_8(s
, COND_AL
, datalo
, addrlo
, 0);
1422 tcg_out_bswap16(s
, COND_AL
, datalo
, datalo
);
1427 tcg_out_ld16u_8(s
, COND_AL
, datalo
, addrlo
, 0);
1428 tcg_out_bswap16s(s
, COND_AL
, datalo
, datalo
);
1430 tcg_out_ld16s_8(s
, COND_AL
, datalo
, addrlo
, 0);
1435 tcg_out_ld32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1437 tcg_out_bswap32(s
, COND_AL
, datalo
, datalo
);
1442 TCGReg dl
= (bswap
? datahi
: datalo
);
1443 TCGReg dh
= (bswap
? datalo
: datahi
);
1445 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1446 if (USING_SOFTMMU
&& use_armv6_instructions
1447 && (dl
& 1) == 0 && dh
== dl
+ 1) {
1448 tcg_out_ldrd_8(s
, COND_AL
, dl
, addrlo
, 0);
1449 } else if (dl
== addrlo
) {
1450 tcg_out_ld32_12(s
, COND_AL
, dh
, addrlo
, bswap
? 0 : 4);
1451 tcg_out_ld32_12(s
, COND_AL
, dl
, addrlo
, bswap
? 4 : 0);
1453 tcg_out_ld32_12(s
, COND_AL
, dl
, addrlo
, bswap
? 4 : 0);
1454 tcg_out_ld32_12(s
, COND_AL
, dh
, addrlo
, bswap
? 0 : 4);
1457 tcg_out_bswap32(s
, COND_AL
, dl
, dl
);
1458 tcg_out_bswap32(s
, COND_AL
, dh
, dh
);
1465 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, bool is64
)
1467 TCGReg addrlo
, datalo
, datahi
, addrhi
__attribute__((unused
));
1469 #ifdef CONFIG_SOFTMMU
1472 tcg_insn_unit
*label_ptr
;
1476 datahi
= (is64
? *args
++ : 0);
1478 addrhi
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1481 #ifdef CONFIG_SOFTMMU
1483 addend
= tcg_out_tlb_read(s
, addrlo
, addrhi
, opc
& MO_SIZE
, mem_index
, 1);
1485 /* This a conditional BL only to load a pointer within this opcode into LR
1486 for the slow path. We will not be using the value for a tail call. */
1487 label_ptr
= s
->code_ptr
;
1488 tcg_out_bl_noaddr(s
, COND_NE
);
1490 tcg_out_qemu_ld_index(s
, opc
, datalo
, datahi
, addrlo
, addend
);
1492 add_qemu_ldst_label(s
, true, opc
, datalo
, datahi
, addrlo
, addrhi
,
1493 mem_index
, s
->code_ptr
, label_ptr
);
1494 #else /* !CONFIG_SOFTMMU */
1496 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_TMP
, GUEST_BASE
);
1497 tcg_out_qemu_ld_index(s
, opc
, datalo
, datahi
, addrlo
, TCG_REG_TMP
);
1499 tcg_out_qemu_ld_direct(s
, opc
, datalo
, datahi
, addrlo
);
1504 static inline void tcg_out_qemu_st_index(TCGContext
*s
, int cond
, TCGMemOp opc
,
1505 TCGReg datalo
, TCGReg datahi
,
1506 TCGReg addrlo
, TCGReg addend
)
1508 TCGMemOp bswap
= opc
& MO_BSWAP
;
1510 switch (opc
& MO_SIZE
) {
1512 tcg_out_st8_r(s
, cond
, datalo
, addrlo
, addend
);
1516 tcg_out_bswap16st(s
, cond
, TCG_REG_R0
, datalo
);
1517 tcg_out_st16_r(s
, cond
, TCG_REG_R0
, addrlo
, addend
);
1519 tcg_out_st16_r(s
, cond
, datalo
, addrlo
, addend
);
1525 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datalo
);
1526 tcg_out_st32_r(s
, cond
, TCG_REG_R0
, addrlo
, addend
);
1528 tcg_out_st32_r(s
, cond
, datalo
, addrlo
, addend
);
1532 /* Avoid strd for user-only emulation, to handle unaligned. */
1534 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datahi
);
1535 tcg_out_st32_rwb(s
, cond
, TCG_REG_R0
, addend
, addrlo
);
1536 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datalo
);
1537 tcg_out_st32_12(s
, cond
, TCG_REG_R0
, addend
, 4);
1538 } else if (USING_SOFTMMU
&& use_armv6_instructions
1539 && (datalo
& 1) == 0 && datahi
== datalo
+ 1) {
1540 tcg_out_strd_r(s
, cond
, datalo
, addrlo
, addend
);
1542 tcg_out_st32_rwb(s
, cond
, datalo
, addend
, addrlo
);
1543 tcg_out_st32_12(s
, cond
, datahi
, addend
, 4);
1549 static inline void tcg_out_qemu_st_direct(TCGContext
*s
, TCGMemOp opc
,
1550 TCGReg datalo
, TCGReg datahi
,
1553 TCGMemOp bswap
= opc
& MO_BSWAP
;
1555 switch (opc
& MO_SIZE
) {
1557 tcg_out_st8_12(s
, COND_AL
, datalo
, addrlo
, 0);
1561 tcg_out_bswap16st(s
, COND_AL
, TCG_REG_R0
, datalo
);
1562 tcg_out_st16_8(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1564 tcg_out_st16_8(s
, COND_AL
, datalo
, addrlo
, 0);
1570 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datalo
);
1571 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1573 tcg_out_st32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1577 /* Avoid strd for user-only emulation, to handle unaligned. */
1579 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datahi
);
1580 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1581 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datalo
);
1582 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 4);
1583 } else if (USING_SOFTMMU
&& use_armv6_instructions
1584 && (datalo
& 1) == 0 && datahi
== datalo
+ 1) {
1585 tcg_out_strd_8(s
, COND_AL
, datalo
, addrlo
, 0);
1587 tcg_out_st32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1588 tcg_out_st32_12(s
, COND_AL
, datahi
, addrlo
, 4);
1594 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, bool is64
)
1596 TCGReg addrlo
, datalo
, datahi
, addrhi
__attribute__((unused
));
1598 #ifdef CONFIG_SOFTMMU
1601 tcg_insn_unit
*label_ptr
;
1605 datahi
= (is64
? *args
++ : 0);
1607 addrhi
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1610 #ifdef CONFIG_SOFTMMU
1612 addend
= tcg_out_tlb_read(s
, addrlo
, addrhi
, opc
& MO_SIZE
, mem_index
, 0);
1614 tcg_out_qemu_st_index(s
, COND_EQ
, opc
, datalo
, datahi
, addrlo
, addend
);
1616 /* The conditional call must come last, as we're going to return here. */
1617 label_ptr
= s
->code_ptr
;
1618 tcg_out_bl_noaddr(s
, COND_NE
);
1620 add_qemu_ldst_label(s
, false, opc
, datalo
, datahi
, addrlo
, addrhi
,
1621 mem_index
, s
->code_ptr
, label_ptr
);
1622 #else /* !CONFIG_SOFTMMU */
1624 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_TMP
, GUEST_BASE
);
1625 tcg_out_qemu_st_index(s
, COND_AL
, opc
, datalo
,
1626 datahi
, addrlo
, TCG_REG_TMP
);
1628 tcg_out_qemu_st_direct(s
, opc
, datalo
, datahi
, addrlo
);
1633 static tcg_insn_unit
*tb_ret_addr
;
1635 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1636 const TCGArg
*args
, const int *const_args
)
1638 TCGArg a0
, a1
, a2
, a3
, a4
, a5
;
1642 case INDEX_op_exit_tb
:
1643 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
, args
[0]);
1644 tcg_out_goto(s
, COND_AL
, tb_ret_addr
);
1646 case INDEX_op_goto_tb
:
1647 if (s
->tb_jmp_offset
) {
1648 /* Direct jump method */
1649 s
->tb_jmp_offset
[args
[0]] = tcg_current_code_size(s
);
1650 tcg_out_b_noaddr(s
, COND_AL
);
1652 /* Indirect jump method */
1653 intptr_t ptr
= (intptr_t)(s
->tb_next
+ args
[0]);
1654 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
, ptr
& ~0xfff);
1655 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_R0
, ptr
& 0xfff);
1657 s
->tb_next_offset
[args
[0]] = tcg_current_code_size(s
);
1660 tcg_out_goto_label(s
, COND_AL
, args
[0]);
1663 case INDEX_op_ld8u_i32
:
1664 tcg_out_ld8u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1666 case INDEX_op_ld8s_i32
:
1667 tcg_out_ld8s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1669 case INDEX_op_ld16u_i32
:
1670 tcg_out_ld16u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1672 case INDEX_op_ld16s_i32
:
1673 tcg_out_ld16s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1675 case INDEX_op_ld_i32
:
1676 tcg_out_ld32u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1678 case INDEX_op_st8_i32
:
1679 tcg_out_st8(s
, COND_AL
, args
[0], args
[1], args
[2]);
1681 case INDEX_op_st16_i32
:
1682 tcg_out_st16(s
, COND_AL
, args
[0], args
[1], args
[2]);
1684 case INDEX_op_st_i32
:
1685 tcg_out_st32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1688 case INDEX_op_movcond_i32
:
1689 /* Constraints mean that v2 is always in the same register as dest,
1690 * so we only need to do "if condition passed, move v1 to dest".
1692 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1693 args
[1], args
[2], const_args
[2]);
1694 tcg_out_dat_rIK(s
, tcg_cond_to_arm_cond
[args
[5]], ARITH_MOV
,
1695 ARITH_MVN
, args
[0], 0, args
[3], const_args
[3]);
1697 case INDEX_op_add_i32
:
1698 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
, ARITH_SUB
,
1699 args
[0], args
[1], args
[2], const_args
[2]);
1701 case INDEX_op_sub_i32
:
1702 if (const_args
[1]) {
1703 if (const_args
[2]) {
1704 tcg_out_movi32(s
, COND_AL
, args
[0], args
[1] - args
[2]);
1706 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
,
1707 args
[0], args
[2], args
[1], 1);
1710 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
, ARITH_ADD
,
1711 args
[0], args
[1], args
[2], const_args
[2]);
1714 case INDEX_op_and_i32
:
1715 tcg_out_dat_rIK(s
, COND_AL
, ARITH_AND
, ARITH_BIC
,
1716 args
[0], args
[1], args
[2], const_args
[2]);
1718 case INDEX_op_andc_i32
:
1719 tcg_out_dat_rIK(s
, COND_AL
, ARITH_BIC
, ARITH_AND
,
1720 args
[0], args
[1], args
[2], const_args
[2]);
1722 case INDEX_op_or_i32
:
1725 case INDEX_op_xor_i32
:
1729 tcg_out_dat_rI(s
, COND_AL
, c
, args
[0], args
[1], args
[2], const_args
[2]);
1731 case INDEX_op_add2_i32
:
1732 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1733 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1734 if (a0
== a3
|| (a0
== a5
&& !const_args
[5])) {
1737 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
| TO_CPSR
, ARITH_SUB
| TO_CPSR
,
1738 a0
, a2
, a4
, const_args
[4]);
1739 tcg_out_dat_rIK(s
, COND_AL
, ARITH_ADC
, ARITH_SBC
,
1740 a1
, a3
, a5
, const_args
[5]);
1741 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1743 case INDEX_op_sub2_i32
:
1744 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1745 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1746 if ((a0
== a3
&& !const_args
[3]) || (a0
== a5
&& !const_args
[5])) {
1749 if (const_args
[2]) {
1750 if (const_args
[4]) {
1751 tcg_out_movi32(s
, COND_AL
, a0
, a4
);
1754 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
| TO_CPSR
, a0
, a4
, a2
, 1);
1756 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
| TO_CPSR
,
1757 ARITH_ADD
| TO_CPSR
, a0
, a2
, a4
, const_args
[4]);
1759 if (const_args
[3]) {
1760 if (const_args
[5]) {
1761 tcg_out_movi32(s
, COND_AL
, a1
, a5
);
1764 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSC
, a1
, a5
, a3
, 1);
1766 tcg_out_dat_rIK(s
, COND_AL
, ARITH_SBC
, ARITH_ADC
,
1767 a1
, a3
, a5
, const_args
[5]);
1769 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1771 case INDEX_op_neg_i32
:
1772 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, args
[0], args
[1], 0);
1774 case INDEX_op_not_i32
:
1775 tcg_out_dat_reg(s
, COND_AL
,
1776 ARITH_MVN
, args
[0], 0, args
[1], SHIFT_IMM_LSL(0));
1778 case INDEX_op_mul_i32
:
1779 tcg_out_mul32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1781 case INDEX_op_mulu2_i32
:
1782 tcg_out_umull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1784 case INDEX_op_muls2_i32
:
1785 tcg_out_smull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1787 /* XXX: Perhaps args[2] & 0x1f is wrong */
1788 case INDEX_op_shl_i32
:
1790 SHIFT_IMM_LSL(args
[2] & 0x1f) : SHIFT_REG_LSL(args
[2]);
1792 case INDEX_op_shr_i32
:
1793 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_LSR(args
[2] & 0x1f) :
1794 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args
[2]);
1796 case INDEX_op_sar_i32
:
1797 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ASR(args
[2] & 0x1f) :
1798 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args
[2]);
1800 case INDEX_op_rotr_i32
:
1801 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ROR(args
[2] & 0x1f) :
1802 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args
[2]);
1805 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1], c
);
1808 case INDEX_op_rotl_i32
:
1809 if (const_args
[2]) {
1810 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1811 ((0x20 - args
[2]) & 0x1f) ?
1812 SHIFT_IMM_ROR((0x20 - args
[2]) & 0x1f) :
1815 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, TCG_REG_TMP
, args
[2], 0x20);
1816 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1817 SHIFT_REG_ROR(TCG_REG_TMP
));
1821 case INDEX_op_brcond_i32
:
1822 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1823 args
[0], args
[1], const_args
[1]);
1824 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[2]], args
[3]);
1826 case INDEX_op_brcond2_i32
:
1827 /* The resulting conditions are:
1828 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1829 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1830 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1831 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1832 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1833 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1835 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1836 args
[1], args
[3], const_args
[3]);
1837 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1838 args
[0], args
[2], const_args
[2]);
1839 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[4]], args
[5]);
1841 case INDEX_op_setcond_i32
:
1842 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1843 args
[1], args
[2], const_args
[2]);
1844 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[3]],
1845 ARITH_MOV
, args
[0], 0, 1);
1846 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[3])],
1847 ARITH_MOV
, args
[0], 0, 0);
1849 case INDEX_op_setcond2_i32
:
1850 /* See brcond2_i32 comment */
1851 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1852 args
[2], args
[4], const_args
[4]);
1853 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1854 args
[1], args
[3], const_args
[3]);
1855 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[5]],
1856 ARITH_MOV
, args
[0], 0, 1);
1857 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[5])],
1858 ARITH_MOV
, args
[0], 0, 0);
1861 case INDEX_op_qemu_ld_i32
:
1862 tcg_out_qemu_ld(s
, args
, 0);
1864 case INDEX_op_qemu_ld_i64
:
1865 tcg_out_qemu_ld(s
, args
, 1);
1867 case INDEX_op_qemu_st_i32
:
1868 tcg_out_qemu_st(s
, args
, 0);
1870 case INDEX_op_qemu_st_i64
:
1871 tcg_out_qemu_st(s
, args
, 1);
1874 case INDEX_op_bswap16_i32
:
1875 tcg_out_bswap16(s
, COND_AL
, args
[0], args
[1]);
1877 case INDEX_op_bswap32_i32
:
1878 tcg_out_bswap32(s
, COND_AL
, args
[0], args
[1]);
1881 case INDEX_op_ext8s_i32
:
1882 tcg_out_ext8s(s
, COND_AL
, args
[0], args
[1]);
1884 case INDEX_op_ext16s_i32
:
1885 tcg_out_ext16s(s
, COND_AL
, args
[0], args
[1]);
1887 case INDEX_op_ext16u_i32
:
1888 tcg_out_ext16u(s
, COND_AL
, args
[0], args
[1]);
1891 case INDEX_op_deposit_i32
:
1892 tcg_out_deposit(s
, COND_AL
, args
[0], args
[2],
1893 args
[3], args
[4], const_args
[2]);
1896 case INDEX_op_div_i32
:
1897 tcg_out_sdiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
1899 case INDEX_op_divu_i32
:
1900 tcg_out_udiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
1903 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
1904 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
1905 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
1911 static const TCGTargetOpDef arm_op_defs
[] = {
1912 { INDEX_op_exit_tb
, { } },
1913 { INDEX_op_goto_tb
, { } },
1914 { INDEX_op_br
, { } },
1916 { INDEX_op_ld8u_i32
, { "r", "r" } },
1917 { INDEX_op_ld8s_i32
, { "r", "r" } },
1918 { INDEX_op_ld16u_i32
, { "r", "r" } },
1919 { INDEX_op_ld16s_i32
, { "r", "r" } },
1920 { INDEX_op_ld_i32
, { "r", "r" } },
1921 { INDEX_op_st8_i32
, { "r", "r" } },
1922 { INDEX_op_st16_i32
, { "r", "r" } },
1923 { INDEX_op_st_i32
, { "r", "r" } },
1925 /* TODO: "r", "r", "ri" */
1926 { INDEX_op_add_i32
, { "r", "r", "rIN" } },
1927 { INDEX_op_sub_i32
, { "r", "rI", "rIN" } },
1928 { INDEX_op_mul_i32
, { "r", "r", "r" } },
1929 { INDEX_op_mulu2_i32
, { "r", "r", "r", "r" } },
1930 { INDEX_op_muls2_i32
, { "r", "r", "r", "r" } },
1931 { INDEX_op_and_i32
, { "r", "r", "rIK" } },
1932 { INDEX_op_andc_i32
, { "r", "r", "rIK" } },
1933 { INDEX_op_or_i32
, { "r", "r", "rI" } },
1934 { INDEX_op_xor_i32
, { "r", "r", "rI" } },
1935 { INDEX_op_neg_i32
, { "r", "r" } },
1936 { INDEX_op_not_i32
, { "r", "r" } },
1938 { INDEX_op_shl_i32
, { "r", "r", "ri" } },
1939 { INDEX_op_shr_i32
, { "r", "r", "ri" } },
1940 { INDEX_op_sar_i32
, { "r", "r", "ri" } },
1941 { INDEX_op_rotl_i32
, { "r", "r", "ri" } },
1942 { INDEX_op_rotr_i32
, { "r", "r", "ri" } },
1944 { INDEX_op_brcond_i32
, { "r", "rIN" } },
1945 { INDEX_op_setcond_i32
, { "r", "r", "rIN" } },
1946 { INDEX_op_movcond_i32
, { "r", "r", "rIN", "rIK", "0" } },
1948 { INDEX_op_add2_i32
, { "r", "r", "r", "r", "rIN", "rIK" } },
1949 { INDEX_op_sub2_i32
, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1950 { INDEX_op_brcond2_i32
, { "r", "r", "rIN", "rIN" } },
1951 { INDEX_op_setcond2_i32
, { "r", "r", "r", "rIN", "rIN" } },
1953 #if TARGET_LONG_BITS == 32
1954 { INDEX_op_qemu_ld_i32
, { "r", "l" } },
1955 { INDEX_op_qemu_ld_i64
, { "r", "r", "l" } },
1956 { INDEX_op_qemu_st_i32
, { "s", "s" } },
1957 { INDEX_op_qemu_st_i64
, { "s", "s", "s" } },
1959 { INDEX_op_qemu_ld_i32
, { "r", "l", "l" } },
1960 { INDEX_op_qemu_ld_i64
, { "r", "r", "l", "l" } },
1961 { INDEX_op_qemu_st_i32
, { "s", "s", "s" } },
1962 { INDEX_op_qemu_st_i64
, { "s", "s", "s", "s" } },
1965 { INDEX_op_bswap16_i32
, { "r", "r" } },
1966 { INDEX_op_bswap32_i32
, { "r", "r" } },
1968 { INDEX_op_ext8s_i32
, { "r", "r" } },
1969 { INDEX_op_ext16s_i32
, { "r", "r" } },
1970 { INDEX_op_ext16u_i32
, { "r", "r" } },
1972 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
1974 { INDEX_op_div_i32
, { "r", "r", "r" } },
1975 { INDEX_op_divu_i32
, { "r", "r", "r" } },
1980 static void tcg_target_init(TCGContext
*s
)
1982 /* Only probe for the platform and capabilities if we havn't already
1983 determined maximum values at compile time. */
1984 #ifndef use_idiv_instructions
1986 unsigned long hwcap
= qemu_getauxval(AT_HWCAP
);
1987 use_idiv_instructions
= (hwcap
& HWCAP_ARM_IDIVA
) != 0;
1990 if (__ARM_ARCH
< 7) {
1991 const char *pl
= (const char *)qemu_getauxval(AT_PLATFORM
);
1992 if (pl
!= NULL
&& pl
[0] == 'v' && pl
[1] >= '4' && pl
[1] <= '9') {
1993 arm_arch
= pl
[1] - '0';
1997 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I32
], 0, 0xffff);
1998 tcg_regset_set32(tcg_target_call_clobber_regs
, 0,
2003 (1 << TCG_REG_R12
) |
2004 (1 << TCG_REG_R14
));
2006 tcg_regset_clear(s
->reserved_regs
);
2007 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_CALL_STACK
);
2008 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_TMP
);
2009 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_PC
);
2011 tcg_add_target_add_op_defs(arm_op_defs
);
2014 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
2015 TCGReg arg1
, intptr_t arg2
)
2017 tcg_out_ld32u(s
, COND_AL
, arg
, arg1
, arg2
);
2020 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
2021 TCGReg arg1
, intptr_t arg2
)
2023 tcg_out_st32(s
, COND_AL
, arg
, arg1
, arg2
);
2026 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
2027 TCGReg ret
, TCGReg arg
)
2029 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, ret
, 0, arg
, SHIFT_IMM_LSL(0));
2032 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
2033 TCGReg ret
, tcg_target_long arg
)
2035 tcg_out_movi32(s
, COND_AL
, ret
, arg
);
2038 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2039 and tcg_register_jit. */
2041 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2043 #define FRAME_SIZE \
2045 + TCG_STATIC_CALL_ARGS_SIZE \
2046 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2047 + TCG_TARGET_STACK_ALIGN - 1) \
2048 & -TCG_TARGET_STACK_ALIGN)
2050 static void tcg_target_qemu_prologue(TCGContext
*s
)
2054 /* Calling convention requires us to save r4-r11 and lr. */
2055 /* stmdb sp!, { r4 - r11, lr } */
2056 tcg_out32(s
, (COND_AL
<< 28) | 0x092d4ff0);
2058 /* Reserve callee argument and tcg temp space. */
2059 stack_addend
= FRAME_SIZE
- PUSH_SIZE
;
2061 tcg_out_dat_rI(s
, COND_AL
, ARITH_SUB
, TCG_REG_CALL_STACK
,
2062 TCG_REG_CALL_STACK
, stack_addend
, 1);
2063 tcg_set_frame(s
, TCG_REG_CALL_STACK
, TCG_STATIC_CALL_ARGS_SIZE
,
2064 CPU_TEMP_BUF_NLONGS
* sizeof(long));
2066 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
2068 tcg_out_bx(s
, COND_AL
, tcg_target_call_iarg_regs
[1]);
2069 tb_ret_addr
= s
->code_ptr
;
2071 /* Epilogue. We branch here via tb_ret_addr. */
2072 tcg_out_dat_rI(s
, COND_AL
, ARITH_ADD
, TCG_REG_CALL_STACK
,
2073 TCG_REG_CALL_STACK
, stack_addend
, 1);
2075 /* ldmia sp!, { r4 - r11, pc } */
2076 tcg_out32(s
, (COND_AL
<< 28) | 0x08bd8ff0);
2081 uint8_t fde_def_cfa
[4];
2082 uint8_t fde_reg_ofs
[18];
2085 #define ELF_HOST_MACHINE EM_ARM
2087 /* We're expecting a 2 byte uleb128 encoded value. */
2088 QEMU_BUILD_BUG_ON(FRAME_SIZE
>= (1 << 14));
2090 static const DebugFrame debug_frame
= {
2091 .h
.cie
.len
= sizeof(DebugFrameCIE
)-4, /* length after .len member */
2094 .h
.cie
.code_align
= 1,
2095 .h
.cie
.data_align
= 0x7c, /* sleb128 -4 */
2096 .h
.cie
.return_column
= 14,
2098 /* Total FDE size does not include the "len" member. */
2099 .h
.fde
.len
= sizeof(DebugFrame
) - offsetof(DebugFrame
, h
.fde
.cie_offset
),
2102 12, 13, /* DW_CFA_def_cfa sp, ... */
2103 (FRAME_SIZE
& 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2107 /* The following must match the stmdb in the prologue. */
2108 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2109 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2110 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2111 0x89, 4, /* DW_CFA_offset, r9, -16 */
2112 0x88, 5, /* DW_CFA_offset, r8, -20 */
2113 0x87, 6, /* DW_CFA_offset, r7, -24 */
2114 0x86, 7, /* DW_CFA_offset, r6, -28 */
2115 0x85, 8, /* DW_CFA_offset, r5, -32 */
2116 0x84, 9, /* DW_CFA_offset, r4, -36 */
2120 void tcg_register_jit(void *buf
, size_t buf_size
)
2122 tcg_register_jit_int(buf
, buf_size
, &debug_frame
, sizeof(debug_frame
));