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
25 /* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
27 # if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
28 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
29 || defined(__ARM_ARCH_7EM__)
31 # elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
32 || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
33 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
35 # elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
36 || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
37 || defined(__ARM_ARCH_5TEJ__)
44 static int arm_arch
= __ARM_ARCH
;
46 #if defined(__ARM_ARCH_5T__) \
47 || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
48 # define use_armv5t_instructions 1
50 # define use_armv5t_instructions use_armv6_instructions
53 #define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6)
54 #define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7)
56 #ifndef use_idiv_instructions
57 bool use_idiv_instructions
;
59 #ifdef CONFIG_GETAUXVAL
60 # include <sys/auxv.h>
64 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
84 static const int tcg_target_reg_alloc_order
[] = {
102 static const int tcg_target_call_iarg_regs
[4] = {
103 TCG_REG_R0
, TCG_REG_R1
, TCG_REG_R2
, TCG_REG_R3
105 static const int tcg_target_call_oarg_regs
[2] = {
106 TCG_REG_R0
, TCG_REG_R1
109 #define TCG_REG_TMP TCG_REG_R12
111 static inline void reloc_abs32(void *code_ptr
, tcg_target_long target
)
113 *(uint32_t *) code_ptr
= target
;
116 static inline void reloc_pc24(void *code_ptr
, tcg_target_long target
)
118 uint32_t offset
= ((target
- ((tcg_target_long
) code_ptr
+ 8)) >> 2);
120 *(uint32_t *) code_ptr
= ((*(uint32_t *) code_ptr
) & ~0xffffff)
121 | (offset
& 0xffffff);
124 static void patch_reloc(uint8_t *code_ptr
, int type
,
125 tcg_target_long value
, tcg_target_long addend
)
129 reloc_abs32(code_ptr
, value
);
138 reloc_pc24(code_ptr
, value
);
143 #define TCG_CT_CONST_ARM 0x100
144 #define TCG_CT_CONST_INV 0x200
145 #define TCG_CT_CONST_NEG 0x400
146 #define TCG_CT_CONST_ZERO 0x800
148 /* parse target specific constraints */
149 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
156 ct
->ct
|= TCG_CT_CONST_ARM
;
159 ct
->ct
|= TCG_CT_CONST_INV
;
161 case 'N': /* The gcc constraint letter is L, already used here. */
162 ct
->ct
|= TCG_CT_CONST_NEG
;
165 ct
->ct
|= TCG_CT_CONST_ZERO
;
169 ct
->ct
|= TCG_CT_REG
;
170 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
173 /* qemu_ld address */
175 ct
->ct
|= TCG_CT_REG
;
176 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
177 #ifdef CONFIG_SOFTMMU
178 /* r0-r2 will be overwritten when reading the tlb entry,
179 so don't use these. */
180 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
181 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
182 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
186 ct
->ct
|= TCG_CT_REG
;
187 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
188 #ifdef CONFIG_SOFTMMU
189 /* r1 is still needed to load data_reg or data_reg2,
191 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
195 /* qemu_st address & data_reg */
197 ct
->ct
|= TCG_CT_REG
;
198 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
199 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
200 and r0-r1 doing the byte swapping, so don't use these. */
201 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
202 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
203 #if defined(CONFIG_SOFTMMU)
204 /* Avoid clashes with registers being used for helper args */
205 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
206 #if TARGET_LONG_BITS == 64
207 /* Avoid clashes with registers being used for helper args */
208 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R3
);
222 static inline uint32_t rotl(uint32_t val
, int n
)
224 return (val
<< n
) | (val
>> (32 - n
));
227 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
228 right-rotated by an even amount between 0 and 30. */
229 static inline int encode_imm(uint32_t imm
)
233 /* simple case, only lower bits */
234 if ((imm
& ~0xff) == 0)
236 /* then try a simple even shift */
237 shift
= ctz32(imm
) & ~1;
238 if (((imm
>> shift
) & ~0xff) == 0)
240 /* now try harder with rotations */
241 if ((rotl(imm
, 2) & ~0xff) == 0)
243 if ((rotl(imm
, 4) & ~0xff) == 0)
245 if ((rotl(imm
, 6) & ~0xff) == 0)
247 /* imm can't be encoded */
251 static inline int check_fit_imm(uint32_t imm
)
253 return encode_imm(imm
) >= 0;
256 /* Test if a constant matches the constraint.
257 * TODO: define constraints for:
259 * ldr/str offset: between -0xfff and 0xfff
260 * ldrh/strh offset: between -0xff and 0xff
261 * mov operand2: values represented with x << (2 * y), x < 0x100
262 * add, sub, eor...: ditto
264 static inline int tcg_target_const_match(tcg_target_long val
,
265 const TCGArgConstraint
*arg_ct
)
269 if (ct
& TCG_CT_CONST
) {
271 } else if ((ct
& TCG_CT_CONST_ARM
) && check_fit_imm(val
)) {
273 } else if ((ct
& TCG_CT_CONST_INV
) && check_fit_imm(~val
)) {
275 } else if ((ct
& TCG_CT_CONST_NEG
) && check_fit_imm(-val
)) {
277 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
284 #define TO_CPSR (1 << 20)
287 ARITH_AND
= 0x0 << 21,
288 ARITH_EOR
= 0x1 << 21,
289 ARITH_SUB
= 0x2 << 21,
290 ARITH_RSB
= 0x3 << 21,
291 ARITH_ADD
= 0x4 << 21,
292 ARITH_ADC
= 0x5 << 21,
293 ARITH_SBC
= 0x6 << 21,
294 ARITH_RSC
= 0x7 << 21,
295 ARITH_TST
= 0x8 << 21 | TO_CPSR
,
296 ARITH_CMP
= 0xa << 21 | TO_CPSR
,
297 ARITH_CMN
= 0xb << 21 | TO_CPSR
,
298 ARITH_ORR
= 0xc << 21,
299 ARITH_MOV
= 0xd << 21,
300 ARITH_BIC
= 0xe << 21,
301 ARITH_MVN
= 0xf << 21,
303 INSN_LDR_IMM
= 0x04100000,
304 INSN_LDR_REG
= 0x06100000,
305 INSN_STR_IMM
= 0x04000000,
306 INSN_STR_REG
= 0x06000000,
308 INSN_LDRH_IMM
= 0x005000b0,
309 INSN_LDRH_REG
= 0x001000b0,
310 INSN_LDRSH_IMM
= 0x005000f0,
311 INSN_LDRSH_REG
= 0x001000f0,
312 INSN_STRH_IMM
= 0x004000b0,
313 INSN_STRH_REG
= 0x000000b0,
315 INSN_LDRB_IMM
= 0x04500000,
316 INSN_LDRB_REG
= 0x06500000,
317 INSN_LDRSB_IMM
= 0x005000d0,
318 INSN_LDRSB_REG
= 0x001000d0,
319 INSN_STRB_IMM
= 0x04400000,
320 INSN_STRB_REG
= 0x06400000,
322 INSN_LDRD_IMM
= 0x004000d0,
325 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
326 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
327 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
328 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
329 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
330 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
331 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
332 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
334 enum arm_cond_code_e
{
337 COND_CS
= 0x2, /* Unsigned greater or equal */
338 COND_CC
= 0x3, /* Unsigned less than */
339 COND_MI
= 0x4, /* Negative */
340 COND_PL
= 0x5, /* Zero or greater */
341 COND_VS
= 0x6, /* Overflow */
342 COND_VC
= 0x7, /* No overflow */
343 COND_HI
= 0x8, /* Unsigned greater than */
344 COND_LS
= 0x9, /* Unsigned less or equal */
352 static const uint8_t tcg_cond_to_arm_cond
[] = {
353 [TCG_COND_EQ
] = COND_EQ
,
354 [TCG_COND_NE
] = COND_NE
,
355 [TCG_COND_LT
] = COND_LT
,
356 [TCG_COND_GE
] = COND_GE
,
357 [TCG_COND_LE
] = COND_LE
,
358 [TCG_COND_GT
] = COND_GT
,
360 [TCG_COND_LTU
] = COND_CC
,
361 [TCG_COND_GEU
] = COND_CS
,
362 [TCG_COND_LEU
] = COND_LS
,
363 [TCG_COND_GTU
] = COND_HI
,
366 static inline void tcg_out_bx(TCGContext
*s
, int cond
, int rn
)
368 tcg_out32(s
, (cond
<< 28) | 0x012fff10 | rn
);
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 skipping
380 the corresponding bytes. This ensure that caches and memory are
381 kept coherent during retranslation. */
382 #ifdef HOST_WORDS_BIGENDIAN
383 tcg_out8(s
, (cond
<< 4) | 0x0a);
387 tcg_out8(s
, (cond
<< 4) | 0x0a);
391 static inline void tcg_out_bl(TCGContext
*s
, int cond
, int32_t offset
)
393 tcg_out32(s
, (cond
<< 28) | 0x0b000000 |
394 (((offset
- 8) >> 2) & 0x00ffffff));
397 static inline void tcg_out_blx(TCGContext
*s
, int cond
, int rn
)
399 tcg_out32(s
, (cond
<< 28) | 0x012fff30 | rn
);
402 static inline void tcg_out_blx_imm(TCGContext
*s
, int32_t offset
)
404 tcg_out32(s
, 0xfa000000 | ((offset
& 2) << 23) |
405 (((offset
- 8) >> 2) & 0x00ffffff));
408 static inline void tcg_out_dat_reg(TCGContext
*s
,
409 int cond
, int opc
, int rd
, int rn
, int rm
, int shift
)
411 tcg_out32(s
, (cond
<< 28) | (0 << 25) | opc
|
412 (rn
<< 16) | (rd
<< 12) | shift
| rm
);
415 static inline void tcg_out_nop(TCGContext
*s
)
417 if (use_armv7_instructions
) {
418 /* Architected nop introduced in v6k. */
419 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
420 also Just So Happened to do nothing on pre-v6k so that we
421 don't need to conditionalize it? */
422 tcg_out32(s
, 0xe320f000);
424 /* Prior to that the assembler uses mov r0, r0. */
425 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, 0, 0, 0, SHIFT_IMM_LSL(0));
429 static inline void tcg_out_mov_reg(TCGContext
*s
, int cond
, int rd
, int rm
)
431 /* Simple reg-reg move, optimising out the 'do nothing' case */
433 tcg_out_dat_reg(s
, cond
, ARITH_MOV
, rd
, 0, rm
, SHIFT_IMM_LSL(0));
437 static inline void tcg_out_dat_imm(TCGContext
*s
,
438 int cond
, int opc
, int rd
, int rn
, int im
)
440 tcg_out32(s
, (cond
<< 28) | (1 << 25) | opc
|
441 (rn
<< 16) | (rd
<< 12) | im
);
444 static void tcg_out_movi32(TCGContext
*s
, int cond
, int rd
, uint32_t arg
)
448 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
449 Speed things up by only checking when movt would be required.
450 Prior to armv7, have one go at fully rotated immediates before
451 doing the decomposition thing below. */
452 if (!use_armv7_instructions
|| (arg
& 0xffff0000)) {
453 rot
= encode_imm(arg
);
455 tcg_out_dat_imm(s
, cond
, ARITH_MOV
, rd
, 0,
456 rotl(arg
, rot
) | (rot
<< 7));
459 rot
= encode_imm(~arg
);
461 tcg_out_dat_imm(s
, cond
, ARITH_MVN
, rd
, 0,
462 rotl(~arg
, rot
) | (rot
<< 7));
467 /* Use movw + movt. */
468 if (use_armv7_instructions
) {
470 tcg_out32(s
, (cond
<< 28) | 0x03000000 | (rd
<< 12)
471 | ((arg
<< 4) & 0x000f0000) | (arg
& 0xfff));
472 if (arg
& 0xffff0000) {
474 tcg_out32(s
, (cond
<< 28) | 0x03400000 | (rd
<< 12)
475 | ((arg
>> 12) & 0x000f0000) | ((arg
>> 16) & 0xfff));
480 /* TODO: This is very suboptimal, we can easily have a constant
481 pool somewhere after all the instructions. */
484 /* If we have lots of leading 1's, we can shorten the sequence by
485 beginning with mvn and then clearing higher bits with eor. */
486 if (clz32(~arg
) > clz32(arg
)) {
487 opc
= ARITH_MVN
, arg
= ~arg
;
490 int i
= ctz32(arg
) & ~1;
491 rot
= ((32 - i
) << 7) & 0xf00;
492 tcg_out_dat_imm(s
, cond
, opc
, rd
, rn
, ((arg
>> i
) & 0xff) | rot
);
500 static inline void tcg_out_dat_rI(TCGContext
*s
, int cond
, int opc
, TCGArg dst
,
501 TCGArg lhs
, TCGArg rhs
, int rhs_is_const
)
503 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
504 * rhs must satisfy the "rI" constraint.
507 int rot
= encode_imm(rhs
);
509 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
511 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
515 static void tcg_out_dat_rIK(TCGContext
*s
, int cond
, int opc
, int opinv
,
516 TCGReg dst
, TCGReg lhs
, TCGArg rhs
,
519 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
520 * rhs must satisfy the "rIK" constraint.
523 int rot
= encode_imm(rhs
);
526 rot
= encode_imm(rhs
);
530 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
532 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
536 static void tcg_out_dat_rIN(TCGContext
*s
, int cond
, int opc
, int opneg
,
537 TCGArg dst
, TCGArg lhs
, TCGArg rhs
,
540 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
541 * rhs must satisfy the "rIN" constraint.
544 int rot
= encode_imm(rhs
);
547 rot
= encode_imm(rhs
);
551 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
553 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
557 static inline void tcg_out_mul32(TCGContext
*s
, int cond
, TCGReg rd
,
558 TCGReg rn
, TCGReg rm
)
560 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
561 if (!use_armv6_instructions
&& rd
== rn
) {
563 /* rd == rn == rm; copy an input to tmp first. */
564 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
565 rm
= rn
= TCG_REG_TMP
;
572 tcg_out32(s
, (cond
<< 28) | 0x90 | (rd
<< 16) | (rm
<< 8) | rn
);
575 static inline void tcg_out_umull32(TCGContext
*s
, int cond
, TCGReg rd0
,
576 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
578 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
579 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
580 if (rd0
== rm
|| rd1
== rm
) {
581 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
590 tcg_out32(s
, (cond
<< 28) | 0x00800090 |
591 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
594 static inline void tcg_out_smull32(TCGContext
*s
, int cond
, TCGReg rd0
,
595 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
597 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
598 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
599 if (rd0
== rm
|| rd1
== rm
) {
600 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
609 tcg_out32(s
, (cond
<< 28) | 0x00c00090 |
610 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
613 static inline void tcg_out_sdiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
615 tcg_out32(s
, 0x0710f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
618 static inline void tcg_out_udiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
620 tcg_out32(s
, 0x0730f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
623 static inline void tcg_out_ext8s(TCGContext
*s
, int cond
,
626 if (use_armv6_instructions
) {
628 tcg_out32(s
, 0x06af0070 | (cond
<< 28) | (rd
<< 12) | rn
);
630 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
631 rd
, 0, rn
, SHIFT_IMM_LSL(24));
632 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
633 rd
, 0, rd
, SHIFT_IMM_ASR(24));
637 static inline void tcg_out_ext8u(TCGContext
*s
, int cond
,
640 tcg_out_dat_imm(s
, cond
, ARITH_AND
, rd
, rn
, 0xff);
643 static inline void tcg_out_ext16s(TCGContext
*s
, int cond
,
646 if (use_armv6_instructions
) {
648 tcg_out32(s
, 0x06bf0070 | (cond
<< 28) | (rd
<< 12) | rn
);
650 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
651 rd
, 0, rn
, SHIFT_IMM_LSL(16));
652 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
653 rd
, 0, rd
, SHIFT_IMM_ASR(16));
657 static inline void tcg_out_ext16u(TCGContext
*s
, int cond
,
660 if (use_armv6_instructions
) {
662 tcg_out32(s
, 0x06ff0070 | (cond
<< 28) | (rd
<< 12) | rn
);
664 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
665 rd
, 0, rn
, SHIFT_IMM_LSL(16));
666 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
667 rd
, 0, rd
, SHIFT_IMM_LSR(16));
671 static inline void tcg_out_bswap16s(TCGContext
*s
, int cond
, int rd
, int rn
)
673 if (use_armv6_instructions
) {
675 tcg_out32(s
, 0x06ff0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
677 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
678 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
679 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
680 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_ASR(16));
681 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
682 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
686 static inline void tcg_out_bswap16(TCGContext
*s
, int cond
, int rd
, int rn
)
688 if (use_armv6_instructions
) {
690 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
692 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
693 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
694 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
695 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_LSR(16));
696 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
697 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
701 /* swap the two low bytes assuming that the two high input bytes and the
702 two high output bit can hold any value. */
703 static inline void tcg_out_bswap16st(TCGContext
*s
, int cond
, int rd
, int rn
)
705 if (use_armv6_instructions
) {
707 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
709 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
710 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSR(8));
711 tcg_out_dat_imm(s
, cond
, ARITH_AND
, TCG_REG_TMP
, TCG_REG_TMP
, 0xff);
712 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
713 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSL(8));
717 static inline void tcg_out_bswap32(TCGContext
*s
, int cond
, int rd
, int rn
)
719 if (use_armv6_instructions
) {
721 tcg_out32(s
, 0x06bf0f30 | (cond
<< 28) | (rd
<< 12) | rn
);
723 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
724 TCG_REG_TMP
, rn
, rn
, SHIFT_IMM_ROR(16));
725 tcg_out_dat_imm(s
, cond
, ARITH_BIC
,
726 TCG_REG_TMP
, TCG_REG_TMP
, 0xff | 0x800);
727 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
728 rd
, 0, rn
, SHIFT_IMM_ROR(8));
729 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
730 rd
, rd
, TCG_REG_TMP
, SHIFT_IMM_LSR(8));
734 bool tcg_target_deposit_valid(int ofs
, int len
)
736 /* ??? Without bfi, we could improve over generic code by combining
737 the right-shift from a non-zero ofs with the orr. We do run into
738 problems when rd == rs, and the mask generated from ofs+len doesn't
739 fit into an immediate. We would have to be careful not to pessimize
740 wrt the optimizations performed on the expanded code. */
741 return use_armv7_instructions
;
744 static inline void tcg_out_deposit(TCGContext
*s
, int cond
, TCGReg rd
,
745 TCGArg a1
, int ofs
, int len
, bool const_a1
)
748 /* bfi becomes bfc with rn == 15. */
752 tcg_out32(s
, 0x07c00010 | (cond
<< 28) | (rd
<< 12) | a1
753 | (ofs
<< 7) | ((ofs
+ len
- 1) << 16));
756 /* Note that this routine is used for both LDR and LDRH formats, so we do
757 not wish to include an immediate shift at this point. */
758 static void tcg_out_memop_r(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
759 TCGReg rn
, TCGReg rm
, bool u
, bool p
, bool w
)
761 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24)
762 | (w
<< 21) | (rn
<< 16) | (rt
<< 12) | rm
);
765 static void tcg_out_memop_8(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
766 TCGReg rn
, int imm8
, bool p
, bool w
)
773 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
774 (rn
<< 16) | (rt
<< 12) | ((imm8
& 0xf0) << 4) | (imm8
& 0xf));
777 static void tcg_out_memop_12(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
778 TCGReg rn
, int imm12
, bool p
, bool w
)
785 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
786 (rn
<< 16) | (rt
<< 12) | imm12
);
789 static inline void tcg_out_ld32_12(TCGContext
*s
, int cond
, TCGReg rt
,
790 TCGReg rn
, int imm12
)
792 tcg_out_memop_12(s
, cond
, INSN_LDR_IMM
, rt
, rn
, imm12
, 1, 0);
795 static inline void tcg_out_st32_12(TCGContext
*s
, int cond
, TCGReg rt
,
796 TCGReg rn
, int imm12
)
798 tcg_out_memop_12(s
, cond
, INSN_STR_IMM
, rt
, rn
, imm12
, 1, 0);
801 static inline void tcg_out_ld32_r(TCGContext
*s
, int cond
, TCGReg rt
,
802 TCGReg rn
, TCGReg rm
)
804 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 0);
807 static inline void tcg_out_st32_r(TCGContext
*s
, int cond
, TCGReg rt
,
808 TCGReg rn
, TCGReg rm
)
810 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 0);
813 /* Register pre-increment with base writeback. */
814 static inline void tcg_out_ld32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
815 TCGReg rn
, TCGReg rm
)
817 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 1);
820 static inline void tcg_out_st32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
821 TCGReg rn
, TCGReg rm
)
823 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 1);
826 static inline void tcg_out_ld16u_8(TCGContext
*s
, int cond
, TCGReg rt
,
829 tcg_out_memop_8(s
, cond
, INSN_LDRH_IMM
, rt
, rn
, imm8
, 1, 0);
832 static inline void tcg_out_st16_8(TCGContext
*s
, int cond
, TCGReg rt
,
835 tcg_out_memop_8(s
, cond
, INSN_STRH_IMM
, rt
, rn
, imm8
, 1, 0);
838 static inline void tcg_out_ld16u_r(TCGContext
*s
, int cond
, TCGReg rt
,
839 TCGReg rn
, TCGReg rm
)
841 tcg_out_memop_r(s
, cond
, INSN_LDRH_REG
, rt
, rn
, rm
, 1, 1, 0);
844 static inline void tcg_out_st16_r(TCGContext
*s
, int cond
, TCGReg rt
,
845 TCGReg rn
, TCGReg rm
)
847 tcg_out_memop_r(s
, cond
, INSN_STRH_REG
, rt
, rn
, rm
, 1, 1, 0);
850 static inline void tcg_out_ld16s_8(TCGContext
*s
, int cond
, TCGReg rt
,
853 tcg_out_memop_8(s
, cond
, INSN_LDRSH_IMM
, rt
, rn
, imm8
, 1, 0);
856 static inline void tcg_out_ld16s_r(TCGContext
*s
, int cond
, TCGReg rt
,
857 TCGReg rn
, TCGReg rm
)
859 tcg_out_memop_r(s
, cond
, INSN_LDRSH_REG
, rt
, rn
, rm
, 1, 1, 0);
862 static inline void tcg_out_ld8_12(TCGContext
*s
, int cond
, TCGReg rt
,
863 TCGReg rn
, int imm12
)
865 tcg_out_memop_12(s
, cond
, INSN_LDRB_IMM
, rt
, rn
, imm12
, 1, 0);
868 static inline void tcg_out_st8_12(TCGContext
*s
, int cond
, TCGReg rt
,
869 TCGReg rn
, int imm12
)
871 tcg_out_memop_12(s
, cond
, INSN_STRB_IMM
, rt
, rn
, imm12
, 1, 0);
874 static inline void tcg_out_ld8_r(TCGContext
*s
, int cond
, TCGReg rt
,
875 TCGReg rn
, TCGReg rm
)
877 tcg_out_memop_r(s
, cond
, INSN_LDRB_REG
, rt
, rn
, rm
, 1, 1, 0);
880 static inline void tcg_out_st8_r(TCGContext
*s
, int cond
, TCGReg rt
,
881 TCGReg rn
, TCGReg rm
)
883 tcg_out_memop_r(s
, cond
, INSN_STRB_REG
, rt
, rn
, rm
, 1, 1, 0);
886 static inline void tcg_out_ld8s_8(TCGContext
*s
, int cond
, TCGReg rt
,
889 tcg_out_memop_8(s
, cond
, INSN_LDRSB_IMM
, rt
, rn
, imm8
, 1, 0);
892 static inline void tcg_out_ld8s_r(TCGContext
*s
, int cond
, TCGReg rt
,
893 TCGReg rn
, TCGReg rm
)
895 tcg_out_memop_r(s
, cond
, INSN_LDRSB_REG
, rt
, rn
, rm
, 1, 1, 0);
898 static inline void tcg_out_ld32u(TCGContext
*s
, int cond
,
899 int rd
, int rn
, int32_t offset
)
901 if (offset
> 0xfff || offset
< -0xfff) {
902 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
903 tcg_out_ld32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
905 tcg_out_ld32_12(s
, cond
, rd
, rn
, offset
);
908 static inline void tcg_out_st32(TCGContext
*s
, int cond
,
909 int rd
, int rn
, int32_t offset
)
911 if (offset
> 0xfff || offset
< -0xfff) {
912 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
913 tcg_out_st32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
915 tcg_out_st32_12(s
, cond
, rd
, rn
, offset
);
918 static inline void tcg_out_ld16u(TCGContext
*s
, int cond
,
919 int rd
, int rn
, int32_t offset
)
921 if (offset
> 0xff || offset
< -0xff) {
922 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
923 tcg_out_ld16u_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
925 tcg_out_ld16u_8(s
, cond
, rd
, rn
, offset
);
928 static inline void tcg_out_ld16s(TCGContext
*s
, int cond
,
929 int rd
, int rn
, int32_t offset
)
931 if (offset
> 0xff || offset
< -0xff) {
932 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
933 tcg_out_ld16s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
935 tcg_out_ld16s_8(s
, cond
, rd
, rn
, offset
);
938 static inline void tcg_out_st16(TCGContext
*s
, int cond
,
939 int rd
, int rn
, int32_t offset
)
941 if (offset
> 0xff || offset
< -0xff) {
942 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
943 tcg_out_st16_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
945 tcg_out_st16_8(s
, cond
, rd
, rn
, offset
);
948 static inline void tcg_out_ld8u(TCGContext
*s
, int cond
,
949 int rd
, int rn
, int32_t offset
)
951 if (offset
> 0xfff || offset
< -0xfff) {
952 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
953 tcg_out_ld8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
955 tcg_out_ld8_12(s
, cond
, rd
, rn
, offset
);
958 static inline void tcg_out_ld8s(TCGContext
*s
, int cond
,
959 int rd
, int rn
, int32_t offset
)
961 if (offset
> 0xff || offset
< -0xff) {
962 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
963 tcg_out_ld8s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
965 tcg_out_ld8s_8(s
, cond
, rd
, rn
, offset
);
968 static inline void tcg_out_st8(TCGContext
*s
, int cond
,
969 int rd
, int rn
, int32_t offset
)
971 if (offset
> 0xfff || offset
< -0xfff) {
972 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
973 tcg_out_st8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
975 tcg_out_st8_12(s
, cond
, rd
, rn
, offset
);
978 /* The _goto case is normally between TBs within the same code buffer,
979 * and with the code buffer limited to 16MB we shouldn't need the long
982 * .... except to the prologue that is in its own buffer.
984 static inline void tcg_out_goto(TCGContext
*s
, int cond
, uint32_t addr
)
989 /* goto to a Thumb destination isn't supported */
993 val
= addr
- (tcg_target_long
) s
->code_ptr
;
994 if (val
- 8 < 0x01fffffd && val
- 8 > -0x01fffffd)
995 tcg_out_b(s
, cond
, val
);
997 if (cond
== COND_AL
) {
998 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1001 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, val
- 8);
1002 tcg_out_dat_reg(s
, cond
, ARITH_ADD
,
1003 TCG_REG_PC
, TCG_REG_PC
,
1004 TCG_REG_TMP
, SHIFT_IMM_LSL(0));
1009 /* The call case is mostly used for helpers - so it's not unreasonable
1010 * for them to be beyond branch range */
1011 static inline void tcg_out_call(TCGContext
*s
, uint32_t addr
)
1015 val
= addr
- (tcg_target_long
) s
->code_ptr
;
1016 if (val
- 8 < 0x02000000 && val
- 8 >= -0x02000000) {
1018 /* Use BLX if the target is in Thumb mode */
1019 if (!use_armv5t_instructions
) {
1022 tcg_out_blx_imm(s
, val
);
1024 tcg_out_bl(s
, COND_AL
, val
);
1026 } else if (use_armv7_instructions
) {
1027 tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, addr
);
1028 tcg_out_blx(s
, COND_AL
, TCG_REG_TMP
);
1030 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R14
, TCG_REG_PC
, 4);
1031 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1036 static inline void tcg_out_callr(TCGContext
*s
, int cond
, int arg
)
1038 if (use_armv5t_instructions
) {
1039 tcg_out_blx(s
, cond
, arg
);
1041 tcg_out_dat_reg(s
, cond
, ARITH_MOV
, TCG_REG_R14
, 0,
1042 TCG_REG_PC
, SHIFT_IMM_LSL(0));
1043 tcg_out_bx(s
, cond
, arg
);
1047 static inline void tcg_out_goto_label(TCGContext
*s
, int cond
, int label_index
)
1049 TCGLabel
*l
= &s
->labels
[label_index
];
1052 tcg_out_goto(s
, cond
, l
->u
.value
);
1054 tcg_out_reloc(s
, s
->code_ptr
, R_ARM_PC24
, label_index
, 31337);
1055 tcg_out_b_noaddr(s
, cond
);
1059 #ifdef CONFIG_SOFTMMU
1061 #include "exec/softmmu_defs.h"
1063 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
1065 static const void * const qemu_ld_helpers
[4] = {
1072 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
1073 uintxx_t val, int mmu_idx) */
1074 static const void * const qemu_st_helpers
[4] = {
1081 /* Helper routines for marshalling helper function arguments into
1082 * the correct registers and stack.
1083 * argreg is where we want to put this argument, arg is the argument itself.
1084 * Return value is the updated argreg ready for the next call.
1085 * Note that argreg 0..3 is real registers, 4+ on stack.
1087 * We provide routines for arguments which are: immediate, 32 bit
1088 * value in register, 16 and 8 bit values in register (which must be zero
1089 * extended before use) and 64 bit value in a lo:hi register pair.
1091 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1092 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1095 MOV_ARG(s, COND_AL, argreg, arg); \
1097 int ofs = (argreg - 4) * 4; \
1099 assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1100 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1102 return argreg + 1; \
1105 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32
, uint32_t, tcg_out_movi32
,
1106 (tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1107 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8
, TCGReg
, tcg_out_ext8u
,
1108 (tcg_out_ext8u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1109 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16
, TCGReg
, tcg_out_ext16u
,
1110 (tcg_out_ext16u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1111 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32
, TCGReg
, tcg_out_mov_reg
, )
1113 static TCGReg
tcg_out_arg_reg64(TCGContext
*s
, TCGReg argreg
,
1114 TCGReg arglo
, TCGReg arghi
)
1116 /* 64 bit arguments must go in even/odd register pairs
1117 * and in 8-aligned stack slots.
1122 argreg
= tcg_out_arg_reg32(s
, argreg
, arglo
);
1123 argreg
= tcg_out_arg_reg32(s
, argreg
, arghi
);
1127 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1129 /* Load and compare a TLB entry, leaving the flags set. Leaves R2 pointing
1130 to the tlb entry. Clobbers R1 and TMP. */
1132 static void tcg_out_tlb_read(TCGContext
*s
, TCGReg addrlo
, TCGReg addrhi
,
1133 int s_bits
, int tlb_offset
)
1135 TCGReg base
= TCG_AREG0
;
1137 /* Should generate something like the following:
1139 * shr tmp, addr_reg, #TARGET_PAGE_BITS (1)
1140 * add r2, env, #off & 0xff00
1141 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1142 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1143 * ldr r0, [r2, #off & 0xff]! (4)
1144 * tst addr_reg, #s_mask
1145 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS (5)
1147 * v7 (not implemented yet):
1148 * ubfx r2, addr_reg, #TARGET_PAGE_BITS, #CPU_TLB_BITS (1)
1149 * movw tmp, #~TARGET_PAGE_MASK & ~s_mask
1151 * add r2, env, r2, lsl #CPU_TLB_ENTRY_BITS (2)
1152 * bic tmp, addr_reg, tmp
1153 * ldr r0, [r2, r0]! (3)
1156 # if CPU_TLB_BITS > 8
1159 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, TCG_REG_TMP
,
1160 0, addrlo
, SHIFT_IMM_LSR(TARGET_PAGE_BITS
));
1162 /* We assume that the offset is contained within 16 bits. */
1163 assert((tlb_offset
& ~0xffff) == 0);
1164 if (tlb_offset
> 0xff) {
1165 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1166 (24 << 7) | (tlb_offset
>> 8));
1171 tcg_out_dat_imm(s
, COND_AL
, ARITH_AND
,
1172 TCG_REG_R0
, TCG_REG_TMP
, CPU_TLB_SIZE
- 1);
1173 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1174 TCG_REG_R0
, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS
));
1176 /* Load the tlb comparator. Use ldrd if needed and available,
1177 but due to how the pointer needs setting up, ldm isn't useful.
1178 Base arm5 doesn't have ldrd, but armv5te does. */
1179 if (use_armv6_instructions
&& TARGET_LONG_BITS
== 64) {
1180 tcg_out_memop_8(s
, COND_AL
, INSN_LDRD_IMM
, TCG_REG_R0
,
1181 TCG_REG_R2
, tlb_offset
, 1, 1);
1183 tcg_out_memop_12(s
, COND_AL
, INSN_LDR_IMM
, TCG_REG_R0
,
1184 TCG_REG_R2
, tlb_offset
, 1, 1);
1185 if (TARGET_LONG_BITS
== 64) {
1186 tcg_out_memop_12(s
, COND_AL
, INSN_LDR_IMM
, TCG_REG_R1
,
1187 TCG_REG_R2
, 4, 1, 0);
1191 /* Check alignment. */
1193 tcg_out_dat_imm(s
, COND_AL
, ARITH_TST
,
1194 0, addrlo
, (1 << s_bits
) - 1);
1197 tcg_out_dat_reg(s
, (s_bits
? COND_EQ
: COND_AL
), ARITH_CMP
, 0,
1198 TCG_REG_R0
, TCG_REG_TMP
, SHIFT_IMM_LSL(TARGET_PAGE_BITS
));
1200 if (TARGET_LONG_BITS
== 64) {
1201 tcg_out_dat_reg(s
, COND_EQ
, ARITH_CMP
, 0,
1202 TCG_REG_R1
, addrhi
, SHIFT_IMM_LSL(0));
1206 /* Record the context of a call to the out of line helper code for the slow
1207 path for a load or store, so that we can later generate the correct
1209 static void add_qemu_ldst_label(TCGContext
*s
, int is_ld
, int opc
,
1210 int data_reg
, int data_reg2
, int addrlo_reg
,
1211 int addrhi_reg
, int mem_index
,
1212 uint8_t *raddr
, uint8_t *label_ptr
)
1215 TCGLabelQemuLdst
*label
;
1217 if (s
->nb_qemu_ldst_labels
>= TCG_MAX_QEMU_LDST
) {
1221 idx
= s
->nb_qemu_ldst_labels
++;
1222 label
= (TCGLabelQemuLdst
*)&s
->qemu_ldst_labels
[idx
];
1223 label
->is_ld
= is_ld
;
1225 label
->datalo_reg
= data_reg
;
1226 label
->datahi_reg
= data_reg2
;
1227 label
->addrlo_reg
= addrlo_reg
;
1228 label
->addrhi_reg
= addrhi_reg
;
1229 label
->mem_index
= mem_index
;
1230 label
->raddr
= raddr
;
1231 label
->label_ptr
[0] = label_ptr
;
1234 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1236 TCGReg argreg
, data_reg
, data_reg2
;
1239 reloc_pc24(lb
->label_ptr
[0], (tcg_target_long
)s
->code_ptr
);
1241 argreg
= tcg_out_arg_reg32(s
, TCG_REG_R0
, TCG_AREG0
);
1242 if (TARGET_LONG_BITS
== 64) {
1243 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1245 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1247 argreg
= tcg_out_arg_imm32(s
, argreg
, lb
->mem_index
);
1248 tcg_out_call(s
, (tcg_target_long
) qemu_ld_helpers
[lb
->opc
& 3]);
1250 data_reg
= lb
->datalo_reg
;
1251 data_reg2
= lb
->datahi_reg
;
1253 start
= s
->code_ptr
;
1256 tcg_out_ext8s(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1259 tcg_out_ext16s(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1265 tcg_out_mov_reg(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1268 tcg_out_mov_reg(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1269 tcg_out_mov_reg(s
, COND_AL
, data_reg2
, TCG_REG_R1
);
1273 /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
1274 the call and the branch back to straight-line code. Note that the
1275 moves above could be elided by register allocation, nor do we know
1276 which code alternative we chose for extension. */
1277 switch (s
->code_ptr
- start
) {
1290 tcg_out_goto(s
, COND_AL
, (tcg_target_long
)lb
->raddr
);
1293 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1295 TCGReg argreg
, data_reg
, data_reg2
;
1297 reloc_pc24(lb
->label_ptr
[0], (tcg_target_long
)s
->code_ptr
);
1299 argreg
= TCG_REG_R0
;
1300 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_AREG0
);
1301 if (TARGET_LONG_BITS
== 64) {
1302 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1304 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1307 data_reg
= lb
->datalo_reg
;
1308 data_reg2
= lb
->datahi_reg
;
1311 argreg
= tcg_out_arg_reg8(s
, argreg
, data_reg
);
1314 argreg
= tcg_out_arg_reg16(s
, argreg
, data_reg
);
1317 argreg
= tcg_out_arg_reg32(s
, argreg
, data_reg
);
1320 argreg
= tcg_out_arg_reg64(s
, argreg
, data_reg
, data_reg2
);
1324 argreg
= tcg_out_arg_imm32(s
, argreg
, lb
->mem_index
);
1325 tcg_out_call(s
, (tcg_target_long
) qemu_st_helpers
[lb
->opc
& 3]);
1327 /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
1328 the call and the branch back to straight-line code. */
1331 tcg_out_goto(s
, COND_AL
, (tcg_target_long
)lb
->raddr
);
1333 #endif /* SOFTMMU */
1335 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, int opc
)
1337 TCGReg addr_reg
, data_reg
, data_reg2
;
1339 #ifdef CONFIG_SOFTMMU
1340 int mem_index
, s_bits
;
1344 #ifdef TARGET_WORDS_BIGENDIAN
1351 data_reg2
= (opc
== 3 ? *args
++ : 0);
1353 #ifdef CONFIG_SOFTMMU
1354 addr_reg2
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1358 tcg_out_tlb_read(s
, addr_reg
, addr_reg2
, s_bits
,
1359 offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
));
1361 label_ptr
= s
->code_ptr
;
1362 tcg_out_b_noaddr(s
, COND_NE
);
1364 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R1
, TCG_REG_R2
,
1365 offsetof(CPUTLBEntry
, addend
)
1366 - offsetof(CPUTLBEntry
, addr_read
));
1370 tcg_out_ld8_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1373 tcg_out_ld8s_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1376 tcg_out_ld16u_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1378 tcg_out_bswap16(s
, COND_AL
, data_reg
, data_reg
);
1383 tcg_out_ld16u_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1384 tcg_out_bswap16s(s
, COND_AL
, data_reg
, data_reg
);
1386 tcg_out_ld16s_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1391 tcg_out_ld32_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1393 tcg_out_bswap32(s
, COND_AL
, data_reg
, data_reg
);
1398 tcg_out_ld32_rwb(s
, COND_AL
, data_reg2
, TCG_REG_R1
, addr_reg
);
1399 tcg_out_ld32_12(s
, COND_AL
, data_reg
, TCG_REG_R1
, 4);
1400 tcg_out_bswap32(s
, COND_AL
, data_reg2
, data_reg2
);
1401 tcg_out_bswap32(s
, COND_AL
, data_reg
, data_reg
);
1403 tcg_out_ld32_rwb(s
, COND_AL
, data_reg
, TCG_REG_R1
, addr_reg
);
1404 tcg_out_ld32_12(s
, COND_AL
, data_reg2
, TCG_REG_R1
, 4);
1409 add_qemu_ldst_label(s
, 1, opc
, data_reg
, data_reg2
, addr_reg
, addr_reg2
,
1410 mem_index
, s
->code_ptr
, label_ptr
);
1411 #else /* !CONFIG_SOFTMMU */
1413 uint32_t offset
= GUEST_BASE
;
1417 i
= ctz32(offset
) & ~1;
1418 rot
= ((32 - i
) << 7) & 0xf00;
1420 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_TMP
, addr_reg
,
1421 ((offset
>> i
) & 0xff) | rot
);
1422 addr_reg
= TCG_REG_TMP
;
1423 offset
&= ~(0xff << i
);
1428 tcg_out_ld8_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1431 tcg_out_ld8s_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1434 tcg_out_ld16u_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1436 tcg_out_bswap16(s
, COND_AL
, data_reg
, data_reg
);
1441 tcg_out_ld16u_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1442 tcg_out_bswap16s(s
, COND_AL
, data_reg
, data_reg
);
1444 tcg_out_ld16s_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1449 tcg_out_ld32_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1451 tcg_out_bswap32(s
, COND_AL
, data_reg
, data_reg
);
1455 /* TODO: use block load -
1456 * check that data_reg2 > data_reg or the other way */
1457 if (data_reg
== addr_reg
) {
1458 tcg_out_ld32_12(s
, COND_AL
, data_reg2
, addr_reg
, bswap
? 0 : 4);
1459 tcg_out_ld32_12(s
, COND_AL
, data_reg
, addr_reg
, bswap
? 4 : 0);
1461 tcg_out_ld32_12(s
, COND_AL
, data_reg
, addr_reg
, bswap
? 4 : 0);
1462 tcg_out_ld32_12(s
, COND_AL
, data_reg2
, addr_reg
, bswap
? 0 : 4);
1465 tcg_out_bswap32(s
, COND_AL
, data_reg
, data_reg
);
1466 tcg_out_bswap32(s
, COND_AL
, data_reg2
, data_reg2
);
1473 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, int opc
)
1475 TCGReg addr_reg
, data_reg
, data_reg2
;
1477 #ifdef CONFIG_SOFTMMU
1478 int mem_index
, s_bits
;
1482 #ifdef TARGET_WORDS_BIGENDIAN
1489 data_reg2
= (opc
== 3 ? *args
++ : 0);
1491 #ifdef CONFIG_SOFTMMU
1492 addr_reg2
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1496 tcg_out_tlb_read(s
, addr_reg
, addr_reg2
, s_bits
,
1497 offsetof(CPUArchState
,
1498 tlb_table
[mem_index
][0].addr_write
));
1500 label_ptr
= s
->code_ptr
;
1501 tcg_out_b_noaddr(s
, COND_NE
);
1503 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R1
, TCG_REG_R2
,
1504 offsetof(CPUTLBEntry
, addend
)
1505 - offsetof(CPUTLBEntry
, addr_write
));
1509 tcg_out_st8_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1513 tcg_out_bswap16st(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1514 tcg_out_st16_r(s
, COND_AL
, TCG_REG_R0
, addr_reg
, TCG_REG_R1
);
1516 tcg_out_st16_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1522 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1523 tcg_out_st32_r(s
, COND_AL
, TCG_REG_R0
, addr_reg
, TCG_REG_R1
);
1525 tcg_out_st32_r(s
, COND_AL
, data_reg
, addr_reg
, TCG_REG_R1
);
1530 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg2
);
1531 tcg_out_st32_rwb(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R1
, addr_reg
);
1532 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1533 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R1
, 4);
1535 tcg_out_st32_rwb(s
, COND_AL
, data_reg
, TCG_REG_R1
, addr_reg
);
1536 tcg_out_st32_12(s
, COND_AL
, data_reg2
, TCG_REG_R1
, 4);
1541 add_qemu_ldst_label(s
, 0, opc
, data_reg
, data_reg2
, addr_reg
, addr_reg2
,
1542 mem_index
, s
->code_ptr
, label_ptr
);
1543 #else /* !CONFIG_SOFTMMU */
1545 uint32_t offset
= GUEST_BASE
;
1550 i
= ctz32(offset
) & ~1;
1551 rot
= ((32 - i
) << 7) & 0xf00;
1553 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R1
, addr_reg
,
1554 ((offset
>> i
) & 0xff) | rot
);
1555 addr_reg
= TCG_REG_R1
;
1556 offset
&= ~(0xff << i
);
1561 tcg_out_st8_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1565 tcg_out_bswap16st(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1566 tcg_out_st16_8(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 0);
1568 tcg_out_st16_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1574 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1575 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 0);
1577 tcg_out_st32_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1581 /* TODO: use block store -
1582 * check that data_reg2 > data_reg or the other way */
1584 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg2
);
1585 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 0);
1586 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1587 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 4);
1589 tcg_out_st32_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1590 tcg_out_st32_12(s
, COND_AL
, data_reg2
, addr_reg
, 4);
1597 static uint8_t *tb_ret_addr
;
1599 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1600 const TCGArg
*args
, const int *const_args
)
1602 TCGArg a0
, a1
, a2
, a3
, a4
, a5
;
1606 case INDEX_op_exit_tb
:
1607 if (use_armv7_instructions
|| check_fit_imm(args
[0])) {
1608 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
, args
[0]);
1609 tcg_out_goto(s
, COND_AL
, (tcg_target_ulong
) tb_ret_addr
);
1611 uint8_t *ld_ptr
= s
->code_ptr
;
1612 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_PC
, 0);
1613 tcg_out_goto(s
, COND_AL
, (tcg_target_ulong
) tb_ret_addr
);
1614 *ld_ptr
= (uint8_t) (s
->code_ptr
- ld_ptr
) - 8;
1615 tcg_out32(s
, args
[0]);
1618 case INDEX_op_goto_tb
:
1619 if (s
->tb_jmp_offset
) {
1620 /* Direct jump method */
1621 #if defined(USE_DIRECT_JUMP)
1622 s
->tb_jmp_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1623 tcg_out_b_noaddr(s
, COND_AL
);
1625 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1626 s
->tb_jmp_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1630 /* Indirect jump method */
1632 c
= (int) (s
->tb_next
+ args
[0]) - ((int) s
->code_ptr
+ 8);
1633 if (c
> 0xfff || c
< -0xfff) {
1634 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
,
1635 (tcg_target_long
) (s
->tb_next
+ args
[0]));
1636 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_R0
, 0);
1638 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, c
);
1640 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_PC
, 0);
1641 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_R0
, 0);
1642 tcg_out32(s
, (tcg_target_long
) (s
->tb_next
+ args
[0]));
1645 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1649 tcg_out_call(s
, args
[0]);
1651 tcg_out_callr(s
, COND_AL
, args
[0]);
1654 tcg_out_goto_label(s
, COND_AL
, args
[0]);
1657 case INDEX_op_ld8u_i32
:
1658 tcg_out_ld8u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1660 case INDEX_op_ld8s_i32
:
1661 tcg_out_ld8s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1663 case INDEX_op_ld16u_i32
:
1664 tcg_out_ld16u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1666 case INDEX_op_ld16s_i32
:
1667 tcg_out_ld16s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1669 case INDEX_op_ld_i32
:
1670 tcg_out_ld32u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1672 case INDEX_op_st8_i32
:
1673 tcg_out_st8(s
, COND_AL
, args
[0], args
[1], args
[2]);
1675 case INDEX_op_st16_i32
:
1676 tcg_out_st16(s
, COND_AL
, args
[0], args
[1], args
[2]);
1678 case INDEX_op_st_i32
:
1679 tcg_out_st32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1682 case INDEX_op_mov_i32
:
1683 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
,
1684 args
[0], 0, args
[1], SHIFT_IMM_LSL(0));
1686 case INDEX_op_movi_i32
:
1687 tcg_out_movi32(s
, COND_AL
, args
[0], args
[1]);
1689 case INDEX_op_movcond_i32
:
1690 /* Constraints mean that v2 is always in the same register as dest,
1691 * so we only need to do "if condition passed, move v1 to dest".
1693 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1694 args
[1], args
[2], const_args
[2]);
1695 tcg_out_dat_rIK(s
, tcg_cond_to_arm_cond
[args
[5]], ARITH_MOV
,
1696 ARITH_MVN
, args
[0], 0, args
[3], const_args
[3]);
1698 case INDEX_op_add_i32
:
1699 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
, ARITH_SUB
,
1700 args
[0], args
[1], args
[2], const_args
[2]);
1702 case INDEX_op_sub_i32
:
1703 if (const_args
[1]) {
1704 if (const_args
[2]) {
1705 tcg_out_movi32(s
, COND_AL
, args
[0], args
[1] - args
[2]);
1707 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
,
1708 args
[0], args
[2], args
[1], 1);
1711 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
, ARITH_ADD
,
1712 args
[0], args
[1], args
[2], const_args
[2]);
1715 case INDEX_op_and_i32
:
1716 tcg_out_dat_rIK(s
, COND_AL
, ARITH_AND
, ARITH_BIC
,
1717 args
[0], args
[1], args
[2], const_args
[2]);
1719 case INDEX_op_andc_i32
:
1720 tcg_out_dat_rIK(s
, COND_AL
, ARITH_BIC
, ARITH_AND
,
1721 args
[0], args
[1], args
[2], const_args
[2]);
1723 case INDEX_op_or_i32
:
1726 case INDEX_op_xor_i32
:
1730 tcg_out_dat_rI(s
, COND_AL
, c
, args
[0], args
[1], args
[2], const_args
[2]);
1732 case INDEX_op_add2_i32
:
1733 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1734 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1735 if (a0
== a3
|| (a0
== a5
&& !const_args
[5])) {
1738 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
| TO_CPSR
, ARITH_SUB
| TO_CPSR
,
1739 a0
, a2
, a4
, const_args
[4]);
1740 tcg_out_dat_rIK(s
, COND_AL
, ARITH_ADC
, ARITH_SBC
,
1741 a1
, a3
, a5
, const_args
[5]);
1742 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1744 case INDEX_op_sub2_i32
:
1745 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1746 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1747 if ((a0
== a3
&& !const_args
[3]) || (a0
== a5
&& !const_args
[5])) {
1750 if (const_args
[2]) {
1751 if (const_args
[4]) {
1752 tcg_out_movi32(s
, COND_AL
, a0
, a4
);
1755 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
| TO_CPSR
, a0
, a4
, a2
, 1);
1757 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
| TO_CPSR
,
1758 ARITH_ADD
| TO_CPSR
, a0
, a2
, a4
, const_args
[4]);
1760 if (const_args
[3]) {
1761 if (const_args
[5]) {
1762 tcg_out_movi32(s
, COND_AL
, a1
, a5
);
1765 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSC
, a1
, a5
, a3
, 1);
1767 tcg_out_dat_rIK(s
, COND_AL
, ARITH_SBC
, ARITH_ADC
,
1768 a1
, a3
, a5
, const_args
[5]);
1770 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1772 case INDEX_op_neg_i32
:
1773 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, args
[0], args
[1], 0);
1775 case INDEX_op_not_i32
:
1776 tcg_out_dat_reg(s
, COND_AL
,
1777 ARITH_MVN
, args
[0], 0, args
[1], SHIFT_IMM_LSL(0));
1779 case INDEX_op_mul_i32
:
1780 tcg_out_mul32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1782 case INDEX_op_mulu2_i32
:
1783 tcg_out_umull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1785 case INDEX_op_muls2_i32
:
1786 tcg_out_smull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1788 /* XXX: Perhaps args[2] & 0x1f is wrong */
1789 case INDEX_op_shl_i32
:
1791 SHIFT_IMM_LSL(args
[2] & 0x1f) : SHIFT_REG_LSL(args
[2]);
1793 case INDEX_op_shr_i32
:
1794 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_LSR(args
[2] & 0x1f) :
1795 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args
[2]);
1797 case INDEX_op_sar_i32
:
1798 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ASR(args
[2] & 0x1f) :
1799 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args
[2]);
1801 case INDEX_op_rotr_i32
:
1802 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ROR(args
[2] & 0x1f) :
1803 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args
[2]);
1806 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1], c
);
1809 case INDEX_op_rotl_i32
:
1810 if (const_args
[2]) {
1811 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1812 ((0x20 - args
[2]) & 0x1f) ?
1813 SHIFT_IMM_ROR((0x20 - args
[2]) & 0x1f) :
1816 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, TCG_REG_TMP
, args
[1], 0x20);
1817 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1818 SHIFT_REG_ROR(TCG_REG_TMP
));
1822 case INDEX_op_brcond_i32
:
1823 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1824 args
[0], args
[1], const_args
[1]);
1825 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[2]], args
[3]);
1827 case INDEX_op_brcond2_i32
:
1828 /* The resulting conditions are:
1829 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1830 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1831 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1832 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1833 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1834 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1836 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1837 args
[1], args
[3], const_args
[3]);
1838 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1839 args
[0], args
[2], const_args
[2]);
1840 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[4]], args
[5]);
1842 case INDEX_op_setcond_i32
:
1843 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1844 args
[1], args
[2], const_args
[2]);
1845 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[3]],
1846 ARITH_MOV
, args
[0], 0, 1);
1847 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[3])],
1848 ARITH_MOV
, args
[0], 0, 0);
1850 case INDEX_op_setcond2_i32
:
1851 /* See brcond2_i32 comment */
1852 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1853 args
[2], args
[4], const_args
[4]);
1854 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1855 args
[1], args
[3], const_args
[3]);
1856 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[5]],
1857 ARITH_MOV
, args
[0], 0, 1);
1858 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[5])],
1859 ARITH_MOV
, args
[0], 0, 0);
1862 case INDEX_op_qemu_ld8u
:
1863 tcg_out_qemu_ld(s
, args
, 0);
1865 case INDEX_op_qemu_ld8s
:
1866 tcg_out_qemu_ld(s
, args
, 0 | 4);
1868 case INDEX_op_qemu_ld16u
:
1869 tcg_out_qemu_ld(s
, args
, 1);
1871 case INDEX_op_qemu_ld16s
:
1872 tcg_out_qemu_ld(s
, args
, 1 | 4);
1874 case INDEX_op_qemu_ld32
:
1875 tcg_out_qemu_ld(s
, args
, 2);
1877 case INDEX_op_qemu_ld64
:
1878 tcg_out_qemu_ld(s
, args
, 3);
1881 case INDEX_op_qemu_st8
:
1882 tcg_out_qemu_st(s
, args
, 0);
1884 case INDEX_op_qemu_st16
:
1885 tcg_out_qemu_st(s
, args
, 1);
1887 case INDEX_op_qemu_st32
:
1888 tcg_out_qemu_st(s
, args
, 2);
1890 case INDEX_op_qemu_st64
:
1891 tcg_out_qemu_st(s
, args
, 3);
1894 case INDEX_op_bswap16_i32
:
1895 tcg_out_bswap16(s
, COND_AL
, args
[0], args
[1]);
1897 case INDEX_op_bswap32_i32
:
1898 tcg_out_bswap32(s
, COND_AL
, args
[0], args
[1]);
1901 case INDEX_op_ext8s_i32
:
1902 tcg_out_ext8s(s
, COND_AL
, args
[0], args
[1]);
1904 case INDEX_op_ext16s_i32
:
1905 tcg_out_ext16s(s
, COND_AL
, args
[0], args
[1]);
1907 case INDEX_op_ext16u_i32
:
1908 tcg_out_ext16u(s
, COND_AL
, args
[0], args
[1]);
1911 case INDEX_op_deposit_i32
:
1912 tcg_out_deposit(s
, COND_AL
, args
[0], args
[2],
1913 args
[3], args
[4], const_args
[2]);
1916 case INDEX_op_div_i32
:
1917 tcg_out_sdiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
1919 case INDEX_op_divu_i32
:
1920 tcg_out_udiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
1928 #ifdef CONFIG_SOFTMMU
1929 /* Generate TB finalization at the end of block. */
1930 void tcg_out_tb_finalize(TCGContext
*s
)
1933 for (i
= 0; i
< s
->nb_qemu_ldst_labels
; i
++) {
1934 TCGLabelQemuLdst
*label
= &s
->qemu_ldst_labels
[i
];
1936 tcg_out_qemu_ld_slow_path(s
, label
);
1938 tcg_out_qemu_st_slow_path(s
, label
);
1942 #endif /* SOFTMMU */
1944 static const TCGTargetOpDef arm_op_defs
[] = {
1945 { INDEX_op_exit_tb
, { } },
1946 { INDEX_op_goto_tb
, { } },
1947 { INDEX_op_call
, { "ri" } },
1948 { INDEX_op_br
, { } },
1950 { INDEX_op_mov_i32
, { "r", "r" } },
1951 { INDEX_op_movi_i32
, { "r" } },
1953 { INDEX_op_ld8u_i32
, { "r", "r" } },
1954 { INDEX_op_ld8s_i32
, { "r", "r" } },
1955 { INDEX_op_ld16u_i32
, { "r", "r" } },
1956 { INDEX_op_ld16s_i32
, { "r", "r" } },
1957 { INDEX_op_ld_i32
, { "r", "r" } },
1958 { INDEX_op_st8_i32
, { "r", "r" } },
1959 { INDEX_op_st16_i32
, { "r", "r" } },
1960 { INDEX_op_st_i32
, { "r", "r" } },
1962 /* TODO: "r", "r", "ri" */
1963 { INDEX_op_add_i32
, { "r", "r", "rIN" } },
1964 { INDEX_op_sub_i32
, { "r", "rI", "rIN" } },
1965 { INDEX_op_mul_i32
, { "r", "r", "r" } },
1966 { INDEX_op_mulu2_i32
, { "r", "r", "r", "r" } },
1967 { INDEX_op_muls2_i32
, { "r", "r", "r", "r" } },
1968 { INDEX_op_and_i32
, { "r", "r", "rIK" } },
1969 { INDEX_op_andc_i32
, { "r", "r", "rIK" } },
1970 { INDEX_op_or_i32
, { "r", "r", "rI" } },
1971 { INDEX_op_xor_i32
, { "r", "r", "rI" } },
1972 { INDEX_op_neg_i32
, { "r", "r" } },
1973 { INDEX_op_not_i32
, { "r", "r" } },
1975 { INDEX_op_shl_i32
, { "r", "r", "ri" } },
1976 { INDEX_op_shr_i32
, { "r", "r", "ri" } },
1977 { INDEX_op_sar_i32
, { "r", "r", "ri" } },
1978 { INDEX_op_rotl_i32
, { "r", "r", "ri" } },
1979 { INDEX_op_rotr_i32
, { "r", "r", "ri" } },
1981 { INDEX_op_brcond_i32
, { "r", "rIN" } },
1982 { INDEX_op_setcond_i32
, { "r", "r", "rIN" } },
1983 { INDEX_op_movcond_i32
, { "r", "r", "rIN", "rIK", "0" } },
1985 { INDEX_op_add2_i32
, { "r", "r", "r", "r", "rIN", "rIK" } },
1986 { INDEX_op_sub2_i32
, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1987 { INDEX_op_brcond2_i32
, { "r", "r", "rIN", "rIN" } },
1988 { INDEX_op_setcond2_i32
, { "r", "r", "r", "rIN", "rIN" } },
1990 #if TARGET_LONG_BITS == 32
1991 { INDEX_op_qemu_ld8u
, { "r", "l" } },
1992 { INDEX_op_qemu_ld8s
, { "r", "l" } },
1993 { INDEX_op_qemu_ld16u
, { "r", "l" } },
1994 { INDEX_op_qemu_ld16s
, { "r", "l" } },
1995 { INDEX_op_qemu_ld32
, { "r", "l" } },
1996 { INDEX_op_qemu_ld64
, { "L", "L", "l" } },
1998 { INDEX_op_qemu_st8
, { "s", "s" } },
1999 { INDEX_op_qemu_st16
, { "s", "s" } },
2000 { INDEX_op_qemu_st32
, { "s", "s" } },
2001 { INDEX_op_qemu_st64
, { "s", "s", "s" } },
2003 { INDEX_op_qemu_ld8u
, { "r", "l", "l" } },
2004 { INDEX_op_qemu_ld8s
, { "r", "l", "l" } },
2005 { INDEX_op_qemu_ld16u
, { "r", "l", "l" } },
2006 { INDEX_op_qemu_ld16s
, { "r", "l", "l" } },
2007 { INDEX_op_qemu_ld32
, { "r", "l", "l" } },
2008 { INDEX_op_qemu_ld64
, { "L", "L", "l", "l" } },
2010 { INDEX_op_qemu_st8
, { "s", "s", "s" } },
2011 { INDEX_op_qemu_st16
, { "s", "s", "s" } },
2012 { INDEX_op_qemu_st32
, { "s", "s", "s" } },
2013 { INDEX_op_qemu_st64
, { "s", "s", "s", "s" } },
2016 { INDEX_op_bswap16_i32
, { "r", "r" } },
2017 { INDEX_op_bswap32_i32
, { "r", "r" } },
2019 { INDEX_op_ext8s_i32
, { "r", "r" } },
2020 { INDEX_op_ext16s_i32
, { "r", "r" } },
2021 { INDEX_op_ext16u_i32
, { "r", "r" } },
2023 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
2025 { INDEX_op_div_i32
, { "r", "r", "r" } },
2026 { INDEX_op_divu_i32
, { "r", "r", "r" } },
2031 static void tcg_target_init(TCGContext
*s
)
2033 #if defined(CONFIG_GETAUXVAL)
2034 /* Only probe for the platform and capabilities if we havn't already
2035 determined maximum values at compile time. */
2036 # if !defined(use_idiv_instructions)
2038 unsigned long hwcap
= getauxval(AT_HWCAP
);
2039 use_idiv_instructions
= (hwcap
& HWCAP_ARM_IDIVA
) != 0;
2042 if (__ARM_ARCH
< 7) {
2043 const char *pl
= (const char *)getauxval(AT_PLATFORM
);
2044 if (pl
!= NULL
&& pl
[0] == 'v' && pl
[1] >= '4' && pl
[1] <= '9') {
2045 arm_arch
= pl
[1] - '0';
2048 #endif /* GETAUXVAL */
2050 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I32
], 0, 0xffff);
2051 tcg_regset_set32(tcg_target_call_clobber_regs
, 0,
2056 (1 << TCG_REG_R12
) |
2057 (1 << TCG_REG_R14
));
2059 tcg_regset_clear(s
->reserved_regs
);
2060 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_CALL_STACK
);
2061 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_TMP
);
2062 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_PC
);
2064 tcg_add_target_add_op_defs(arm_op_defs
);
2067 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
2068 TCGReg arg1
, tcg_target_long arg2
)
2070 tcg_out_ld32u(s
, COND_AL
, arg
, arg1
, arg2
);
2073 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
2074 TCGReg arg1
, tcg_target_long arg2
)
2076 tcg_out_st32(s
, COND_AL
, arg
, arg1
, arg2
);
2079 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
2080 TCGReg ret
, TCGReg arg
)
2082 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, ret
, 0, arg
, SHIFT_IMM_LSL(0));
2085 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
2086 TCGReg ret
, tcg_target_long arg
)
2088 tcg_out_movi32(s
, COND_AL
, ret
, arg
);
2091 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2092 and tcg_register_jit. */
2094 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2096 #define FRAME_SIZE \
2098 + TCG_STATIC_CALL_ARGS_SIZE \
2099 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2100 + TCG_TARGET_STACK_ALIGN - 1) \
2101 & -TCG_TARGET_STACK_ALIGN)
2103 static void tcg_target_qemu_prologue(TCGContext
*s
)
2107 /* Calling convention requires us to save r4-r11 and lr. */
2108 /* stmdb sp!, { r4 - r11, lr } */
2109 tcg_out32(s
, (COND_AL
<< 28) | 0x092d4ff0);
2111 /* Reserve callee argument and tcg temp space. */
2112 stack_addend
= FRAME_SIZE
- PUSH_SIZE
;
2114 tcg_out_dat_rI(s
, COND_AL
, ARITH_SUB
, TCG_REG_CALL_STACK
,
2115 TCG_REG_CALL_STACK
, stack_addend
, 1);
2116 tcg_set_frame(s
, TCG_REG_CALL_STACK
, TCG_STATIC_CALL_ARGS_SIZE
,
2117 CPU_TEMP_BUF_NLONGS
* sizeof(long));
2119 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
2121 tcg_out_bx(s
, COND_AL
, tcg_target_call_iarg_regs
[1]);
2122 tb_ret_addr
= s
->code_ptr
;
2124 /* Epilogue. We branch here via tb_ret_addr. */
2125 tcg_out_dat_rI(s
, COND_AL
, ARITH_ADD
, TCG_REG_CALL_STACK
,
2126 TCG_REG_CALL_STACK
, stack_addend
, 1);
2128 /* ldmia sp!, { r4 - r11, pc } */
2129 tcg_out32(s
, (COND_AL
<< 28) | 0x08bd8ff0);
2134 DebugFrameFDEHeader fde
;
2135 uint8_t fde_def_cfa
[4];
2136 uint8_t fde_reg_ofs
[18];
2139 #define ELF_HOST_MACHINE EM_ARM
2141 /* We're expecting a 2 byte uleb128 encoded value. */
2142 QEMU_BUILD_BUG_ON(FRAME_SIZE
>= (1 << 14));
2144 static DebugFrame debug_frame
= {
2145 .cie
.len
= sizeof(DebugFrameCIE
)-4, /* length after .len member */
2148 .cie
.code_align
= 1,
2149 .cie
.data_align
= 0x7c, /* sleb128 -4 */
2150 .cie
.return_column
= 14,
2152 /* Total FDE size does not include the "len" member. */
2153 .fde
.len
= sizeof(DebugFrame
) - offsetof(DebugFrame
, fde
.cie_offset
),
2156 12, 13, /* DW_CFA_def_cfa sp, ... */
2157 (FRAME_SIZE
& 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2161 /* The following must match the stmdb in the prologue. */
2162 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2163 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2164 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2165 0x89, 4, /* DW_CFA_offset, r9, -16 */
2166 0x88, 5, /* DW_CFA_offset, r8, -20 */
2167 0x87, 6, /* DW_CFA_offset, r7, -24 */
2168 0x86, 7, /* DW_CFA_offset, r6, -28 */
2169 0x85, 8, /* DW_CFA_offset, r5, -32 */
2170 0x84, 9, /* DW_CFA_offset, r4, -36 */
2174 void tcg_register_jit(void *buf
, size_t buf_size
)
2176 debug_frame
.fde
.func_start
= (tcg_target_long
) buf
;
2177 debug_frame
.fde
.func_len
= buf_size
;
2179 tcg_register_jit_int(buf
, buf_size
, &debug_frame
, sizeof(debug_frame
));