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 #if defined(__ARM_ARCH_7__) || \
26 defined(__ARM_ARCH_7A__) || \
27 defined(__ARM_ARCH_7EM__) || \
28 defined(__ARM_ARCH_7M__) || \
29 defined(__ARM_ARCH_7R__)
30 #define USE_ARMV7_INSTRUCTIONS
33 #if defined(USE_ARMV7_INSTRUCTIONS) || \
34 defined(__ARM_ARCH_6J__) || \
35 defined(__ARM_ARCH_6K__) || \
36 defined(__ARM_ARCH_6T2__) || \
37 defined(__ARM_ARCH_6Z__) || \
38 defined(__ARM_ARCH_6ZK__)
39 #define USE_ARMV6_INSTRUCTIONS
42 #if defined(USE_ARMV6_INSTRUCTIONS) || \
43 defined(__ARM_ARCH_5T__) || \
44 defined(__ARM_ARCH_5TE__) || \
45 defined(__ARM_ARCH_5TEJ__)
46 #define USE_ARMV5_INSTRUCTIONS
49 #ifdef USE_ARMV5_INSTRUCTIONS
50 static const int use_armv5_instructions
= 1;
52 static const int use_armv5_instructions
= 0;
54 #undef USE_ARMV5_INSTRUCTIONS
56 #ifdef USE_ARMV6_INSTRUCTIONS
57 static const int use_armv6_instructions
= 1;
59 static const int use_armv6_instructions
= 0;
61 #undef USE_ARMV6_INSTRUCTIONS
63 #ifdef USE_ARMV7_INSTRUCTIONS
64 static const int use_armv7_instructions
= 1;
66 static const int use_armv7_instructions
= 0;
68 #undef USE_ARMV7_INSTRUCTIONS
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 static inline void reloc_abs32(void *code_ptr
, tcg_target_long target
)
118 *(uint32_t *) code_ptr
= target
;
121 static inline void reloc_pc24(void *code_ptr
, tcg_target_long target
)
123 uint32_t offset
= ((target
- ((tcg_target_long
) code_ptr
+ 8)) >> 2);
125 *(uint32_t *) code_ptr
= ((*(uint32_t *) code_ptr
) & ~0xffffff)
126 | (offset
& 0xffffff);
129 static void patch_reloc(uint8_t *code_ptr
, int type
,
130 tcg_target_long value
, tcg_target_long addend
)
134 reloc_abs32(code_ptr
, value
);
143 reloc_pc24(code_ptr
, value
);
148 #define TCG_CT_CONST_ARM 0x100
149 #define TCG_CT_CONST_INV 0x200
150 #define TCG_CT_CONST_NEG 0x400
151 #define TCG_CT_CONST_ZERO 0x800
153 /* parse target specific constraints */
154 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
161 ct
->ct
|= TCG_CT_CONST_ARM
;
164 ct
->ct
|= TCG_CT_CONST_INV
;
166 case 'N': /* The gcc constraint letter is L, already used here. */
167 ct
->ct
|= TCG_CT_CONST_NEG
;
170 ct
->ct
|= TCG_CT_CONST_ZERO
;
174 ct
->ct
|= TCG_CT_REG
;
175 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
178 /* qemu_ld address */
180 ct
->ct
|= TCG_CT_REG
;
181 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
182 #ifdef CONFIG_SOFTMMU
183 /* r0 and r1 will be overwritten when reading the tlb entry,
184 so don't use these. */
185 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
186 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
187 #if TARGET_LONG_BITS == 64
188 /* If we're passing env to the helper as r0 and need a regpair
189 * for the address then r2 will be overwritten as we're setting
190 * up the args to the helper.
192 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
197 ct
->ct
|= TCG_CT_REG
;
198 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
199 #ifdef CONFIG_SOFTMMU
200 /* r1 is still needed to load data_reg or data_reg2,
202 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
206 /* qemu_st address & data_reg */
208 ct
->ct
|= TCG_CT_REG
;
209 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
210 /* r0 and r1 will be overwritten when reading the tlb entry
211 (softmmu only) and doing the byte swapping, so don't
213 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
214 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
215 #if defined(CONFIG_SOFTMMU) && (TARGET_LONG_BITS == 64)
216 /* Avoid clashes with registers being used for helper args */
217 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
218 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R3
);
221 /* qemu_st64 data_reg2 */
223 ct
->ct
|= TCG_CT_REG
;
224 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
225 /* r0 and r1 will be overwritten when reading the tlb entry
226 (softmmu only) and doing the byte swapping, so don't
228 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
229 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
230 #ifdef CONFIG_SOFTMMU
231 /* r2 is still needed to load data_reg, so don't use it. */
232 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
233 #if TARGET_LONG_BITS == 64
234 /* Avoid clashes with registers being used for helper args */
235 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R3
);
249 static inline uint32_t rotl(uint32_t val
, int n
)
251 return (val
<< n
) | (val
>> (32 - n
));
254 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
255 right-rotated by an even amount between 0 and 30. */
256 static inline int encode_imm(uint32_t imm
)
260 /* simple case, only lower bits */
261 if ((imm
& ~0xff) == 0)
263 /* then try a simple even shift */
264 shift
= ctz32(imm
) & ~1;
265 if (((imm
>> shift
) & ~0xff) == 0)
267 /* now try harder with rotations */
268 if ((rotl(imm
, 2) & ~0xff) == 0)
270 if ((rotl(imm
, 4) & ~0xff) == 0)
272 if ((rotl(imm
, 6) & ~0xff) == 0)
274 /* imm can't be encoded */
278 static inline int check_fit_imm(uint32_t imm
)
280 return encode_imm(imm
) >= 0;
283 /* Test if a constant matches the constraint.
284 * TODO: define constraints for:
286 * ldr/str offset: between -0xfff and 0xfff
287 * ldrh/strh offset: between -0xff and 0xff
288 * mov operand2: values represented with x << (2 * y), x < 0x100
289 * add, sub, eor...: ditto
291 static inline int tcg_target_const_match(tcg_target_long val
,
292 const TCGArgConstraint
*arg_ct
)
296 if (ct
& TCG_CT_CONST
) {
298 } else if ((ct
& TCG_CT_CONST_ARM
) && check_fit_imm(val
)) {
300 } else if ((ct
& TCG_CT_CONST_INV
) && check_fit_imm(~val
)) {
302 } else if ((ct
& TCG_CT_CONST_NEG
) && check_fit_imm(-val
)) {
304 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
311 #define TO_CPSR (1 << 20)
313 enum arm_data_opc_e
{
314 ARITH_AND
= 0x0 << 21,
315 ARITH_EOR
= 0x1 << 21,
316 ARITH_SUB
= 0x2 << 21,
317 ARITH_RSB
= 0x3 << 21,
318 ARITH_ADD
= 0x4 << 21,
319 ARITH_ADC
= 0x5 << 21,
320 ARITH_SBC
= 0x6 << 21,
321 ARITH_RSC
= 0x7 << 21,
322 ARITH_TST
= 0x8 << 21 | TO_CPSR
,
323 ARITH_CMP
= 0xa << 21 | TO_CPSR
,
324 ARITH_CMN
= 0xb << 21 | TO_CPSR
,
325 ARITH_ORR
= 0xc << 21,
326 ARITH_MOV
= 0xd << 21,
327 ARITH_BIC
= 0xe << 21,
328 ARITH_MVN
= 0xf << 21,
331 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
332 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
333 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
334 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
335 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
336 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
337 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
338 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
340 enum arm_cond_code_e
{
343 COND_CS
= 0x2, /* Unsigned greater or equal */
344 COND_CC
= 0x3, /* Unsigned less than */
345 COND_MI
= 0x4, /* Negative */
346 COND_PL
= 0x5, /* Zero or greater */
347 COND_VS
= 0x6, /* Overflow */
348 COND_VC
= 0x7, /* No overflow */
349 COND_HI
= 0x8, /* Unsigned greater than */
350 COND_LS
= 0x9, /* Unsigned less or equal */
358 static const uint8_t tcg_cond_to_arm_cond
[] = {
359 [TCG_COND_EQ
] = COND_EQ
,
360 [TCG_COND_NE
] = COND_NE
,
361 [TCG_COND_LT
] = COND_LT
,
362 [TCG_COND_GE
] = COND_GE
,
363 [TCG_COND_LE
] = COND_LE
,
364 [TCG_COND_GT
] = COND_GT
,
366 [TCG_COND_LTU
] = COND_CC
,
367 [TCG_COND_GEU
] = COND_CS
,
368 [TCG_COND_LEU
] = COND_LS
,
369 [TCG_COND_GTU
] = COND_HI
,
372 static inline void tcg_out_bx(TCGContext
*s
, int cond
, int rn
)
374 tcg_out32(s
, (cond
<< 28) | 0x012fff10 | rn
);
377 static inline void tcg_out_b(TCGContext
*s
, int cond
, int32_t offset
)
379 tcg_out32(s
, (cond
<< 28) | 0x0a000000 |
380 (((offset
- 8) >> 2) & 0x00ffffff));
383 static inline void tcg_out_b_noaddr(TCGContext
*s
, int cond
)
385 /* We pay attention here to not modify the branch target by skipping
386 the corresponding bytes. This ensure that caches and memory are
387 kept coherent during retranslation. */
388 #ifdef HOST_WORDS_BIGENDIAN
389 tcg_out8(s
, (cond
<< 4) | 0x0a);
393 tcg_out8(s
, (cond
<< 4) | 0x0a);
397 static inline void tcg_out_bl(TCGContext
*s
, int cond
, int32_t offset
)
399 tcg_out32(s
, (cond
<< 28) | 0x0b000000 |
400 (((offset
- 8) >> 2) & 0x00ffffff));
403 static inline void tcg_out_blx(TCGContext
*s
, int cond
, int rn
)
405 tcg_out32(s
, (cond
<< 28) | 0x012fff30 | rn
);
408 static inline void tcg_out_blx_imm(TCGContext
*s
, int32_t offset
)
410 tcg_out32(s
, 0xfa000000 | ((offset
& 2) << 23) |
411 (((offset
- 8) >> 2) & 0x00ffffff));
414 static inline void tcg_out_dat_reg(TCGContext
*s
,
415 int cond
, int opc
, int rd
, int rn
, int rm
, int shift
)
417 tcg_out32(s
, (cond
<< 28) | (0 << 25) | opc
|
418 (rn
<< 16) | (rd
<< 12) | shift
| rm
);
421 static inline void tcg_out_mov_reg(TCGContext
*s
, int cond
, int rd
, int rm
)
423 /* Simple reg-reg move, optimising out the 'do nothing' case */
425 tcg_out_dat_reg(s
, cond
, ARITH_MOV
, rd
, 0, rm
, SHIFT_IMM_LSL(0));
429 static inline void tcg_out_dat_imm(TCGContext
*s
,
430 int cond
, int opc
, int rd
, int rn
, int im
)
432 tcg_out32(s
, (cond
<< 28) | (1 << 25) | opc
|
433 (rn
<< 16) | (rd
<< 12) | im
);
436 static void tcg_out_movi32(TCGContext
*s
, int cond
, int rd
, uint32_t arg
)
440 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
441 Speed things up by only checking when movt would be required.
442 Prior to armv7, have one go at fully rotated immediates before
443 doing the decomposition thing below. */
444 if (!use_armv7_instructions
|| (arg
& 0xffff0000)) {
445 rot
= encode_imm(arg
);
447 tcg_out_dat_imm(s
, cond
, ARITH_MOV
, rd
, 0,
448 rotl(arg
, rot
) | (rot
<< 7));
451 rot
= encode_imm(~arg
);
453 tcg_out_dat_imm(s
, cond
, ARITH_MVN
, rd
, 0,
454 rotl(~arg
, rot
) | (rot
<< 7));
459 /* Use movw + movt. */
460 if (use_armv7_instructions
) {
462 tcg_out32(s
, (cond
<< 28) | 0x03000000 | (rd
<< 12)
463 | ((arg
<< 4) & 0x000f0000) | (arg
& 0xfff));
464 if (arg
& 0xffff0000) {
466 tcg_out32(s
, (cond
<< 28) | 0x03400000 | (rd
<< 12)
467 | ((arg
>> 12) & 0x000f0000) | ((arg
>> 16) & 0xfff));
472 /* TODO: This is very suboptimal, we can easily have a constant
473 pool somewhere after all the instructions. */
476 /* If we have lots of leading 1's, we can shorten the sequence by
477 beginning with mvn and then clearing higher bits with eor. */
478 if (clz32(~arg
) > clz32(arg
)) {
479 opc
= ARITH_MVN
, arg
= ~arg
;
482 int i
= ctz32(arg
) & ~1;
483 rot
= ((32 - i
) << 7) & 0xf00;
484 tcg_out_dat_imm(s
, cond
, opc
, rd
, rn
, ((arg
>> i
) & 0xff) | rot
);
492 static inline void tcg_out_dat_rI(TCGContext
*s
, int cond
, int opc
, TCGArg dst
,
493 TCGArg lhs
, TCGArg rhs
, int rhs_is_const
)
495 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
496 * rhs must satisfy the "rI" constraint.
499 int rot
= encode_imm(rhs
);
501 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
503 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
507 static void tcg_out_dat_rIK(TCGContext
*s
, int cond
, int opc
, int opinv
,
508 TCGReg dst
, TCGReg lhs
, TCGArg rhs
,
511 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
512 * rhs must satisfy the "rIK" constraint.
515 int rot
= encode_imm(rhs
);
518 rot
= encode_imm(rhs
);
522 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
524 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
528 static void tcg_out_dat_rIN(TCGContext
*s
, int cond
, int opc
, int opneg
,
529 TCGArg dst
, TCGArg lhs
, TCGArg rhs
,
532 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
533 * rhs must satisfy the "rIN" constraint.
536 int rot
= encode_imm(rhs
);
539 rot
= encode_imm(rhs
);
543 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
545 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
549 static inline void tcg_out_mul32(TCGContext
*s
,
550 int cond
, int rd
, int rs
, int rm
)
553 tcg_out32(s
, (cond
<< 28) | (rd
<< 16) | (0 << 12) |
554 (rs
<< 8) | 0x90 | rm
);
556 tcg_out32(s
, (cond
<< 28) | (rd
<< 16) | (0 << 12) |
557 (rm
<< 8) | 0x90 | rs
);
559 tcg_out32(s
, (cond
<< 28) | ( 8 << 16) | (0 << 12) |
560 (rs
<< 8) | 0x90 | rm
);
561 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
562 rd
, 0, TCG_REG_R8
, SHIFT_IMM_LSL(0));
566 static inline void tcg_out_umull32(TCGContext
*s
,
567 int cond
, int rd0
, int rd1
, int rs
, int rm
)
569 if (rd0
!= rm
&& rd1
!= rm
)
570 tcg_out32(s
, (cond
<< 28) | 0x800090 |
571 (rd1
<< 16) | (rd0
<< 12) | (rs
<< 8) | rm
);
572 else if (rd0
!= rs
&& rd1
!= rs
)
573 tcg_out32(s
, (cond
<< 28) | 0x800090 |
574 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rs
);
576 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
577 TCG_REG_R8
, 0, rm
, SHIFT_IMM_LSL(0));
578 tcg_out32(s
, (cond
<< 28) | 0x800098 |
579 (rd1
<< 16) | (rd0
<< 12) | (rs
<< 8));
583 static inline void tcg_out_smull32(TCGContext
*s
,
584 int cond
, int rd0
, int rd1
, int rs
, int rm
)
586 if (rd0
!= rm
&& rd1
!= rm
)
587 tcg_out32(s
, (cond
<< 28) | 0xc00090 |
588 (rd1
<< 16) | (rd0
<< 12) | (rs
<< 8) | rm
);
589 else if (rd0
!= rs
&& rd1
!= rs
)
590 tcg_out32(s
, (cond
<< 28) | 0xc00090 |
591 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rs
);
593 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
594 TCG_REG_R8
, 0, rm
, SHIFT_IMM_LSL(0));
595 tcg_out32(s
, (cond
<< 28) | 0xc00098 |
596 (rd1
<< 16) | (rd0
<< 12) | (rs
<< 8));
600 static inline void tcg_out_ext8s(TCGContext
*s
, int cond
,
603 if (use_armv6_instructions
) {
605 tcg_out32(s
, 0x06af0070 | (cond
<< 28) | (rd
<< 12) | rn
);
607 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
608 rd
, 0, rn
, SHIFT_IMM_LSL(24));
609 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
610 rd
, 0, rd
, SHIFT_IMM_ASR(24));
614 static inline void tcg_out_ext8u(TCGContext
*s
, int cond
,
617 tcg_out_dat_imm(s
, cond
, ARITH_AND
, rd
, rn
, 0xff);
620 static inline void tcg_out_ext16s(TCGContext
*s
, int cond
,
623 if (use_armv6_instructions
) {
625 tcg_out32(s
, 0x06bf0070 | (cond
<< 28) | (rd
<< 12) | rn
);
627 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
628 rd
, 0, rn
, SHIFT_IMM_LSL(16));
629 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
630 rd
, 0, rd
, SHIFT_IMM_ASR(16));
634 static inline void tcg_out_ext16u(TCGContext
*s
, int cond
,
637 if (use_armv6_instructions
) {
639 tcg_out32(s
, 0x06ff0070 | (cond
<< 28) | (rd
<< 12) | rn
);
641 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
642 rd
, 0, rn
, SHIFT_IMM_LSL(16));
643 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
644 rd
, 0, rd
, SHIFT_IMM_LSR(16));
648 static inline void tcg_out_bswap16s(TCGContext
*s
, int cond
, int rd
, int rn
)
650 if (use_armv6_instructions
) {
652 tcg_out32(s
, 0x06ff0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
654 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
655 TCG_REG_R8
, 0, rn
, SHIFT_IMM_LSL(24));
656 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
657 TCG_REG_R8
, 0, TCG_REG_R8
, SHIFT_IMM_ASR(16));
658 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
659 rd
, TCG_REG_R8
, rn
, SHIFT_IMM_LSR(8));
663 static inline void tcg_out_bswap16(TCGContext
*s
, int cond
, int rd
, int rn
)
665 if (use_armv6_instructions
) {
667 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
669 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
670 TCG_REG_R8
, 0, rn
, SHIFT_IMM_LSL(24));
671 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
672 TCG_REG_R8
, 0, TCG_REG_R8
, SHIFT_IMM_LSR(16));
673 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
674 rd
, TCG_REG_R8
, rn
, SHIFT_IMM_LSR(8));
678 /* swap the two low bytes assuming that the two high input bytes and the
679 two high output bit can hold any value. */
680 static inline void tcg_out_bswap16st(TCGContext
*s
, int cond
, int rd
, int rn
)
682 if (use_armv6_instructions
) {
684 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
686 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
687 TCG_REG_R8
, 0, rn
, SHIFT_IMM_LSR(8));
688 tcg_out_dat_imm(s
, cond
, ARITH_AND
, TCG_REG_R8
, TCG_REG_R8
, 0xff);
689 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
690 rd
, TCG_REG_R8
, rn
, SHIFT_IMM_LSL(8));
694 static inline void tcg_out_bswap32(TCGContext
*s
, int cond
, int rd
, int rn
)
696 if (use_armv6_instructions
) {
698 tcg_out32(s
, 0x06bf0f30 | (cond
<< 28) | (rd
<< 12) | rn
);
700 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
701 TCG_REG_R8
, rn
, rn
, SHIFT_IMM_ROR(16));
702 tcg_out_dat_imm(s
, cond
, ARITH_BIC
,
703 TCG_REG_R8
, TCG_REG_R8
, 0xff | 0x800);
704 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
705 rd
, 0, rn
, SHIFT_IMM_ROR(8));
706 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
707 rd
, rd
, TCG_REG_R8
, SHIFT_IMM_LSR(8));
711 bool tcg_target_deposit_valid(int ofs
, int len
)
713 /* ??? Without bfi, we could improve over generic code by combining
714 the right-shift from a non-zero ofs with the orr. We do run into
715 problems when rd == rs, and the mask generated from ofs+len doesn't
716 fit into an immediate. We would have to be careful not to pessimize
717 wrt the optimizations performed on the expanded code. */
718 return use_armv7_instructions
;
721 static inline void tcg_out_deposit(TCGContext
*s
, int cond
, TCGReg rd
,
722 TCGArg a1
, int ofs
, int len
, bool const_a1
)
725 /* bfi becomes bfc with rn == 15. */
729 tcg_out32(s
, 0x07c00010 | (cond
<< 28) | (rd
<< 12) | a1
730 | (ofs
<< 7) | ((ofs
+ len
- 1) << 16));
733 static inline void tcg_out_ld32_12(TCGContext
*s
, int cond
,
734 int rd
, int rn
, tcg_target_long im
)
737 tcg_out32(s
, (cond
<< 28) | 0x05900000 |
738 (rn
<< 16) | (rd
<< 12) | (im
& 0xfff));
740 tcg_out32(s
, (cond
<< 28) | 0x05100000 |
741 (rn
<< 16) | (rd
<< 12) | ((-im
) & 0xfff));
744 /* Offset pre-increment with base writeback. */
745 static inline void tcg_out_ld32_12wb(TCGContext
*s
, int cond
,
746 int rd
, int rn
, tcg_target_long im
)
748 /* ldr with writeback and both register equals is UNPREDICTABLE */
752 tcg_out32(s
, (cond
<< 28) | 0x05b00000 |
753 (rn
<< 16) | (rd
<< 12) | (im
& 0xfff));
755 tcg_out32(s
, (cond
<< 28) | 0x05300000 |
756 (rn
<< 16) | (rd
<< 12) | ((-im
) & 0xfff));
760 static inline void tcg_out_st32_12(TCGContext
*s
, int cond
,
761 int rd
, int rn
, tcg_target_long im
)
764 tcg_out32(s
, (cond
<< 28) | 0x05800000 |
765 (rn
<< 16) | (rd
<< 12) | (im
& 0xfff));
767 tcg_out32(s
, (cond
<< 28) | 0x05000000 |
768 (rn
<< 16) | (rd
<< 12) | ((-im
) & 0xfff));
771 static inline void tcg_out_ld32_r(TCGContext
*s
, int cond
,
772 int rd
, int rn
, int rm
)
774 tcg_out32(s
, (cond
<< 28) | 0x07900000 |
775 (rn
<< 16) | (rd
<< 12) | rm
);
778 static inline void tcg_out_st32_r(TCGContext
*s
, int cond
,
779 int rd
, int rn
, int rm
)
781 tcg_out32(s
, (cond
<< 28) | 0x07800000 |
782 (rn
<< 16) | (rd
<< 12) | rm
);
785 /* Register pre-increment with base writeback. */
786 static inline void tcg_out_ld32_rwb(TCGContext
*s
, int cond
,
787 int rd
, int rn
, int rm
)
789 tcg_out32(s
, (cond
<< 28) | 0x07b00000 |
790 (rn
<< 16) | (rd
<< 12) | rm
);
793 static inline void tcg_out_st32_rwb(TCGContext
*s
, int cond
,
794 int rd
, int rn
, int rm
)
796 tcg_out32(s
, (cond
<< 28) | 0x07a00000 |
797 (rn
<< 16) | (rd
<< 12) | rm
);
800 static inline void tcg_out_ld16u_8(TCGContext
*s
, int cond
,
801 int rd
, int rn
, tcg_target_long im
)
804 tcg_out32(s
, (cond
<< 28) | 0x01d000b0 |
805 (rn
<< 16) | (rd
<< 12) |
806 ((im
& 0xf0) << 4) | (im
& 0xf));
808 tcg_out32(s
, (cond
<< 28) | 0x015000b0 |
809 (rn
<< 16) | (rd
<< 12) |
810 (((-im
) & 0xf0) << 4) | ((-im
) & 0xf));
813 static inline void tcg_out_st16_8(TCGContext
*s
, int cond
,
814 int rd
, int rn
, tcg_target_long im
)
817 tcg_out32(s
, (cond
<< 28) | 0x01c000b0 |
818 (rn
<< 16) | (rd
<< 12) |
819 ((im
& 0xf0) << 4) | (im
& 0xf));
821 tcg_out32(s
, (cond
<< 28) | 0x014000b0 |
822 (rn
<< 16) | (rd
<< 12) |
823 (((-im
) & 0xf0) << 4) | ((-im
) & 0xf));
826 static inline void tcg_out_ld16u_r(TCGContext
*s
, int cond
,
827 int rd
, int rn
, int rm
)
829 tcg_out32(s
, (cond
<< 28) | 0x019000b0 |
830 (rn
<< 16) | (rd
<< 12) | rm
);
833 static inline void tcg_out_st16_r(TCGContext
*s
, int cond
,
834 int rd
, int rn
, int rm
)
836 tcg_out32(s
, (cond
<< 28) | 0x018000b0 |
837 (rn
<< 16) | (rd
<< 12) | rm
);
840 static inline void tcg_out_ld16s_8(TCGContext
*s
, int cond
,
841 int rd
, int rn
, tcg_target_long im
)
844 tcg_out32(s
, (cond
<< 28) | 0x01d000f0 |
845 (rn
<< 16) | (rd
<< 12) |
846 ((im
& 0xf0) << 4) | (im
& 0xf));
848 tcg_out32(s
, (cond
<< 28) | 0x015000f0 |
849 (rn
<< 16) | (rd
<< 12) |
850 (((-im
) & 0xf0) << 4) | ((-im
) & 0xf));
853 static inline void tcg_out_ld16s_r(TCGContext
*s
, int cond
,
854 int rd
, int rn
, int rm
)
856 tcg_out32(s
, (cond
<< 28) | 0x019000f0 |
857 (rn
<< 16) | (rd
<< 12) | rm
);
860 static inline void tcg_out_ld8_12(TCGContext
*s
, int cond
,
861 int rd
, int rn
, tcg_target_long im
)
864 tcg_out32(s
, (cond
<< 28) | 0x05d00000 |
865 (rn
<< 16) | (rd
<< 12) | (im
& 0xfff));
867 tcg_out32(s
, (cond
<< 28) | 0x05500000 |
868 (rn
<< 16) | (rd
<< 12) | ((-im
) & 0xfff));
871 static inline void tcg_out_st8_12(TCGContext
*s
, int cond
,
872 int rd
, int rn
, tcg_target_long im
)
875 tcg_out32(s
, (cond
<< 28) | 0x05c00000 |
876 (rn
<< 16) | (rd
<< 12) | (im
& 0xfff));
878 tcg_out32(s
, (cond
<< 28) | 0x05400000 |
879 (rn
<< 16) | (rd
<< 12) | ((-im
) & 0xfff));
882 static inline void tcg_out_ld8_r(TCGContext
*s
, int cond
,
883 int rd
, int rn
, int rm
)
885 tcg_out32(s
, (cond
<< 28) | 0x07d00000 |
886 (rn
<< 16) | (rd
<< 12) | rm
);
889 static inline void tcg_out_st8_r(TCGContext
*s
, int cond
,
890 int rd
, int rn
, int rm
)
892 tcg_out32(s
, (cond
<< 28) | 0x07c00000 |
893 (rn
<< 16) | (rd
<< 12) | rm
);
896 static inline void tcg_out_ld8s_8(TCGContext
*s
, int cond
,
897 int rd
, int rn
, tcg_target_long im
)
900 tcg_out32(s
, (cond
<< 28) | 0x01d000d0 |
901 (rn
<< 16) | (rd
<< 12) |
902 ((im
& 0xf0) << 4) | (im
& 0xf));
904 tcg_out32(s
, (cond
<< 28) | 0x015000d0 |
905 (rn
<< 16) | (rd
<< 12) |
906 (((-im
) & 0xf0) << 4) | ((-im
) & 0xf));
909 static inline void tcg_out_ld8s_r(TCGContext
*s
, int cond
,
910 int rd
, int rn
, int rm
)
912 tcg_out32(s
, (cond
<< 28) | 0x019000d0 |
913 (rn
<< 16) | (rd
<< 12) | rm
);
916 static inline void tcg_out_ld32u(TCGContext
*s
, int cond
,
917 int rd
, int rn
, int32_t offset
)
919 if (offset
> 0xfff || offset
< -0xfff) {
920 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
921 tcg_out_ld32_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
923 tcg_out_ld32_12(s
, cond
, rd
, rn
, offset
);
926 static inline void tcg_out_st32(TCGContext
*s
, int cond
,
927 int rd
, int rn
, int32_t offset
)
929 if (offset
> 0xfff || offset
< -0xfff) {
930 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
931 tcg_out_st32_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
933 tcg_out_st32_12(s
, cond
, rd
, rn
, offset
);
936 static inline void tcg_out_ld16u(TCGContext
*s
, int cond
,
937 int rd
, int rn
, int32_t offset
)
939 if (offset
> 0xff || offset
< -0xff) {
940 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
941 tcg_out_ld16u_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
943 tcg_out_ld16u_8(s
, cond
, rd
, rn
, offset
);
946 static inline void tcg_out_ld16s(TCGContext
*s
, int cond
,
947 int rd
, int rn
, int32_t offset
)
949 if (offset
> 0xff || offset
< -0xff) {
950 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
951 tcg_out_ld16s_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
953 tcg_out_ld16s_8(s
, cond
, rd
, rn
, offset
);
956 static inline void tcg_out_st16(TCGContext
*s
, int cond
,
957 int rd
, int rn
, int32_t offset
)
959 if (offset
> 0xff || offset
< -0xff) {
960 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
961 tcg_out_st16_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
963 tcg_out_st16_8(s
, cond
, rd
, rn
, offset
);
966 static inline void tcg_out_ld8u(TCGContext
*s
, int cond
,
967 int rd
, int rn
, int32_t offset
)
969 if (offset
> 0xfff || offset
< -0xfff) {
970 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
971 tcg_out_ld8_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
973 tcg_out_ld8_12(s
, cond
, rd
, rn
, offset
);
976 static inline void tcg_out_ld8s(TCGContext
*s
, int cond
,
977 int rd
, int rn
, int32_t offset
)
979 if (offset
> 0xff || offset
< -0xff) {
980 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
981 tcg_out_ld8s_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
983 tcg_out_ld8s_8(s
, cond
, rd
, rn
, offset
);
986 static inline void tcg_out_st8(TCGContext
*s
, int cond
,
987 int rd
, int rn
, int32_t offset
)
989 if (offset
> 0xfff || offset
< -0xfff) {
990 tcg_out_movi32(s
, cond
, TCG_REG_R8
, offset
);
991 tcg_out_st8_r(s
, cond
, rd
, rn
, TCG_REG_R8
);
993 tcg_out_st8_12(s
, cond
, rd
, rn
, offset
);
996 /* The _goto case is normally between TBs within the same code buffer,
997 * and with the code buffer limited to 16MB we shouldn't need the long
1000 * .... except to the prologue that is in its own buffer.
1002 static inline void tcg_out_goto(TCGContext
*s
, int cond
, uint32_t addr
)
1007 /* goto to a Thumb destination isn't supported */
1011 val
= addr
- (tcg_target_long
) s
->code_ptr
;
1012 if (val
- 8 < 0x01fffffd && val
- 8 > -0x01fffffd)
1013 tcg_out_b(s
, cond
, val
);
1015 if (cond
== COND_AL
) {
1016 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1019 tcg_out_movi32(s
, cond
, TCG_REG_R8
, val
- 8);
1020 tcg_out_dat_reg(s
, cond
, ARITH_ADD
,
1021 TCG_REG_PC
, TCG_REG_PC
,
1022 TCG_REG_R8
, SHIFT_IMM_LSL(0));
1027 /* The call case is mostly used for helpers - so it's not unreasonable
1028 * for them to be beyond branch range */
1029 static inline void tcg_out_call(TCGContext
*s
, uint32_t addr
)
1033 val
= addr
- (tcg_target_long
) s
->code_ptr
;
1034 if (val
- 8 < 0x02000000 && val
- 8 >= -0x02000000) {
1036 /* Use BLX if the target is in Thumb mode */
1037 if (!use_armv5_instructions
) {
1040 tcg_out_blx_imm(s
, val
);
1042 tcg_out_bl(s
, COND_AL
, val
);
1045 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R14
, TCG_REG_PC
, 4);
1046 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1051 static inline void tcg_out_callr(TCGContext
*s
, int cond
, int arg
)
1053 if (use_armv5_instructions
) {
1054 tcg_out_blx(s
, cond
, arg
);
1056 tcg_out_dat_reg(s
, cond
, ARITH_MOV
, TCG_REG_R14
, 0,
1057 TCG_REG_PC
, SHIFT_IMM_LSL(0));
1058 tcg_out_bx(s
, cond
, arg
);
1062 static inline void tcg_out_goto_label(TCGContext
*s
, int cond
, int label_index
)
1064 TCGLabel
*l
= &s
->labels
[label_index
];
1067 tcg_out_goto(s
, cond
, l
->u
.value
);
1068 else if (cond
== COND_AL
) {
1069 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1070 tcg_out_reloc(s
, s
->code_ptr
, R_ARM_ABS32
, label_index
, 31337);
1073 /* Probably this should be preferred even for COND_AL... */
1074 tcg_out_reloc(s
, s
->code_ptr
, R_ARM_PC24
, label_index
, 31337);
1075 tcg_out_b_noaddr(s
, cond
);
1079 #ifdef CONFIG_SOFTMMU
1081 #include "exec/softmmu_defs.h"
1083 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
1085 static const void * const qemu_ld_helpers
[4] = {
1092 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
1093 uintxx_t val, int mmu_idx) */
1094 static const void * const qemu_st_helpers
[4] = {
1101 /* Helper routines for marshalling helper function arguments into
1102 * the correct registers and stack.
1103 * argreg is where we want to put this argument, arg is the argument itself.
1104 * Return value is the updated argreg ready for the next call.
1105 * Note that argreg 0..3 is real registers, 4+ on stack.
1107 * We provide routines for arguments which are: immediate, 32 bit
1108 * value in register, 16 and 8 bit values in register (which must be zero
1109 * extended before use) and 64 bit value in a lo:hi register pair.
1111 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1112 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1115 MOV_ARG(s, COND_AL, argreg, arg); \
1117 int ofs = (argreg - 4) * 4; \
1119 assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1120 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1122 return argreg + 1; \
1125 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32
, uint32_t, tcg_out_movi32
,
1126 (tcg_out_movi32(s
, COND_AL
, TCG_REG_R8
, arg
), arg
= TCG_REG_R8
))
1127 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8
, TCGReg
, tcg_out_ext8u
,
1128 (tcg_out_ext8u(s
, COND_AL
, TCG_REG_R8
, arg
), arg
= TCG_REG_R8
))
1129 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16
, TCGReg
, tcg_out_ext16u
,
1130 (tcg_out_ext16u(s
, COND_AL
, TCG_REG_R8
, arg
), arg
= TCG_REG_R8
))
1131 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32
, TCGReg
, tcg_out_mov_reg
, )
1133 static TCGReg
tcg_out_arg_reg64(TCGContext
*s
, TCGReg argreg
,
1134 TCGReg arglo
, TCGReg arghi
)
1136 /* 64 bit arguments must go in even/odd register pairs
1137 * and in 8-aligned stack slots.
1142 argreg
= tcg_out_arg_reg32(s
, argreg
, arglo
);
1143 argreg
= tcg_out_arg_reg32(s
, argreg
, arghi
);
1146 #endif /* SOFTMMU */
1148 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1150 static inline void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, int opc
)
1152 int addr_reg
, data_reg
, data_reg2
, bswap
;
1153 #ifdef CONFIG_SOFTMMU
1154 int mem_index
, s_bits
, tlb_offset
;
1156 # if TARGET_LONG_BITS == 64
1159 uint32_t *label_ptr
;
1162 #ifdef TARGET_WORDS_BIGENDIAN
1169 data_reg2
= *args
++;
1171 data_reg2
= 0; /* suppress warning */
1173 #ifdef CONFIG_SOFTMMU
1174 # if TARGET_LONG_BITS == 64
1175 addr_reg2
= *args
++;
1180 /* Should generate something like the following:
1181 * shr r8, addr_reg, #TARGET_PAGE_BITS
1182 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8
1183 * add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1185 # if CPU_TLB_BITS > 8
1188 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, TCG_REG_R8
,
1189 0, addr_reg
, SHIFT_IMM_LSR(TARGET_PAGE_BITS
));
1190 tcg_out_dat_imm(s
, COND_AL
, ARITH_AND
,
1191 TCG_REG_R0
, TCG_REG_R8
, CPU_TLB_SIZE
- 1);
1192 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_R0
, TCG_AREG0
,
1193 TCG_REG_R0
, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS
));
1194 /* We assume that the offset is contained within 20 bits. */
1195 tlb_offset
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
);
1196 assert((tlb_offset
& ~0xfffff) == 0);
1197 if (tlb_offset
> 0xfff) {
1198 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R0
, TCG_REG_R0
,
1199 0xa00 | (tlb_offset
>> 12));
1200 tlb_offset
&= 0xfff;
1202 tcg_out_ld32_12wb(s
, COND_AL
, TCG_REG_R1
, TCG_REG_R0
, tlb_offset
);
1203 tcg_out_dat_reg(s
, COND_AL
, ARITH_CMP
, 0, TCG_REG_R1
,
1204 TCG_REG_R8
, SHIFT_IMM_LSL(TARGET_PAGE_BITS
));
1205 /* Check alignment. */
1207 tcg_out_dat_imm(s
, COND_EQ
, ARITH_TST
,
1208 0, addr_reg
, (1 << s_bits
) - 1);
1209 # if TARGET_LONG_BITS == 64
1210 /* XXX: possibly we could use a block data load in the first access. */
1211 tcg_out_ld32_12(s
, COND_EQ
, TCG_REG_R1
, TCG_REG_R0
, 4);
1212 tcg_out_dat_reg(s
, COND_EQ
, ARITH_CMP
, 0,
1213 TCG_REG_R1
, addr_reg2
, SHIFT_IMM_LSL(0));
1215 tcg_out_ld32_12(s
, COND_EQ
, TCG_REG_R1
, TCG_REG_R0
,
1216 offsetof(CPUTLBEntry
, addend
)
1217 - offsetof(CPUTLBEntry
, addr_read
));
1221 tcg_out_ld8_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1224 tcg_out_ld8s_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1227 tcg_out_ld16u_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1229 tcg_out_bswap16(s
, COND_EQ
, data_reg
, data_reg
);
1234 tcg_out_ld16u_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1235 tcg_out_bswap16s(s
, COND_EQ
, data_reg
, data_reg
);
1237 tcg_out_ld16s_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1242 tcg_out_ld32_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1244 tcg_out_bswap32(s
, COND_EQ
, data_reg
, data_reg
);
1249 tcg_out_ld32_rwb(s
, COND_EQ
, data_reg2
, TCG_REG_R1
, addr_reg
);
1250 tcg_out_ld32_12(s
, COND_EQ
, data_reg
, TCG_REG_R1
, 4);
1251 tcg_out_bswap32(s
, COND_EQ
, data_reg2
, data_reg2
);
1252 tcg_out_bswap32(s
, COND_EQ
, data_reg
, data_reg
);
1254 tcg_out_ld32_rwb(s
, COND_EQ
, data_reg
, TCG_REG_R1
, addr_reg
);
1255 tcg_out_ld32_12(s
, COND_EQ
, data_reg2
, TCG_REG_R1
, 4);
1260 label_ptr
= (void *) s
->code_ptr
;
1261 tcg_out_b_noaddr(s
, COND_EQ
);
1263 /* TODO: move this code to where the constants pool will be */
1264 /* Note that this code relies on the constraints we set in arm_op_defs[]
1265 * to ensure that later arguments are not passed to us in registers we
1266 * trash by moving the earlier arguments into them.
1268 argreg
= TCG_REG_R0
;
1269 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_AREG0
);
1270 #if TARGET_LONG_BITS == 64
1271 argreg
= tcg_out_arg_reg64(s
, argreg
, addr_reg
, addr_reg2
);
1273 argreg
= tcg_out_arg_reg32(s
, argreg
, addr_reg
);
1275 argreg
= tcg_out_arg_imm32(s
, argreg
, mem_index
);
1276 tcg_out_call(s
, (tcg_target_long
) qemu_ld_helpers
[s_bits
]);
1280 tcg_out_ext8s(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1283 tcg_out_ext16s(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1289 tcg_out_mov_reg(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1292 tcg_out_mov_reg(s
, COND_AL
, data_reg
, TCG_REG_R0
);
1293 tcg_out_mov_reg(s
, COND_AL
, data_reg2
, TCG_REG_R1
);
1297 reloc_pc24(label_ptr
, (tcg_target_long
)s
->code_ptr
);
1298 #else /* !CONFIG_SOFTMMU */
1300 uint32_t offset
= GUEST_BASE
;
1305 i
= ctz32(offset
) & ~1;
1306 rot
= ((32 - i
) << 7) & 0xf00;
1308 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R8
, addr_reg
,
1309 ((offset
>> i
) & 0xff) | rot
);
1310 addr_reg
= TCG_REG_R8
;
1311 offset
&= ~(0xff << i
);
1316 tcg_out_ld8_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1319 tcg_out_ld8s_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1322 tcg_out_ld16u_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1324 tcg_out_bswap16(s
, COND_AL
, data_reg
, data_reg
);
1329 tcg_out_ld16u_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1330 tcg_out_bswap16s(s
, COND_AL
, data_reg
, data_reg
);
1332 tcg_out_ld16s_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1337 tcg_out_ld32_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1339 tcg_out_bswap32(s
, COND_AL
, data_reg
, data_reg
);
1343 /* TODO: use block load -
1344 * check that data_reg2 > data_reg or the other way */
1345 if (data_reg
== addr_reg
) {
1346 tcg_out_ld32_12(s
, COND_AL
, data_reg2
, addr_reg
, bswap
? 0 : 4);
1347 tcg_out_ld32_12(s
, COND_AL
, data_reg
, addr_reg
, bswap
? 4 : 0);
1349 tcg_out_ld32_12(s
, COND_AL
, data_reg
, addr_reg
, bswap
? 4 : 0);
1350 tcg_out_ld32_12(s
, COND_AL
, data_reg2
, addr_reg
, bswap
? 0 : 4);
1353 tcg_out_bswap32(s
, COND_AL
, data_reg
, data_reg
);
1354 tcg_out_bswap32(s
, COND_AL
, data_reg2
, data_reg2
);
1361 static inline void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, int opc
)
1363 int addr_reg
, data_reg
, data_reg2
, bswap
;
1364 #ifdef CONFIG_SOFTMMU
1365 int mem_index
, s_bits
, tlb_offset
;
1367 # if TARGET_LONG_BITS == 64
1370 uint32_t *label_ptr
;
1373 #ifdef TARGET_WORDS_BIGENDIAN
1380 data_reg2
= *args
++;
1382 data_reg2
= 0; /* suppress warning */
1384 #ifdef CONFIG_SOFTMMU
1385 # if TARGET_LONG_BITS == 64
1386 addr_reg2
= *args
++;
1391 /* Should generate something like the following:
1392 * shr r8, addr_reg, #TARGET_PAGE_BITS
1393 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8
1394 * add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1396 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
,
1397 TCG_REG_R8
, 0, addr_reg
, SHIFT_IMM_LSR(TARGET_PAGE_BITS
));
1398 tcg_out_dat_imm(s
, COND_AL
, ARITH_AND
,
1399 TCG_REG_R0
, TCG_REG_R8
, CPU_TLB_SIZE
- 1);
1400 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_R0
,
1401 TCG_AREG0
, TCG_REG_R0
, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS
));
1402 /* We assume that the offset is contained within 20 bits. */
1403 tlb_offset
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
);
1404 assert((tlb_offset
& ~0xfffff) == 0);
1405 if (tlb_offset
> 0xfff) {
1406 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R0
, TCG_REG_R0
,
1407 0xa00 | (tlb_offset
>> 12));
1408 tlb_offset
&= 0xfff;
1410 tcg_out_ld32_12wb(s
, COND_AL
, TCG_REG_R1
, TCG_REG_R0
, tlb_offset
);
1411 tcg_out_dat_reg(s
, COND_AL
, ARITH_CMP
, 0, TCG_REG_R1
,
1412 TCG_REG_R8
, SHIFT_IMM_LSL(TARGET_PAGE_BITS
));
1413 /* Check alignment. */
1415 tcg_out_dat_imm(s
, COND_EQ
, ARITH_TST
,
1416 0, addr_reg
, (1 << s_bits
) - 1);
1417 # if TARGET_LONG_BITS == 64
1418 /* XXX: possibly we could use a block data load in the first access. */
1419 tcg_out_ld32_12(s
, COND_EQ
, TCG_REG_R1
, TCG_REG_R0
, 4);
1420 tcg_out_dat_reg(s
, COND_EQ
, ARITH_CMP
, 0,
1421 TCG_REG_R1
, addr_reg2
, SHIFT_IMM_LSL(0));
1423 tcg_out_ld32_12(s
, COND_EQ
, TCG_REG_R1
, TCG_REG_R0
,
1424 offsetof(CPUTLBEntry
, addend
)
1425 - offsetof(CPUTLBEntry
, addr_write
));
1429 tcg_out_st8_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1433 tcg_out_bswap16st(s
, COND_EQ
, TCG_REG_R0
, data_reg
);
1434 tcg_out_st16_r(s
, COND_EQ
, TCG_REG_R0
, addr_reg
, TCG_REG_R1
);
1436 tcg_out_st16_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1442 tcg_out_bswap32(s
, COND_EQ
, TCG_REG_R0
, data_reg
);
1443 tcg_out_st32_r(s
, COND_EQ
, TCG_REG_R0
, addr_reg
, TCG_REG_R1
);
1445 tcg_out_st32_r(s
, COND_EQ
, data_reg
, addr_reg
, TCG_REG_R1
);
1450 tcg_out_bswap32(s
, COND_EQ
, TCG_REG_R0
, data_reg2
);
1451 tcg_out_st32_rwb(s
, COND_EQ
, TCG_REG_R0
, TCG_REG_R1
, addr_reg
);
1452 tcg_out_bswap32(s
, COND_EQ
, TCG_REG_R0
, data_reg
);
1453 tcg_out_st32_12(s
, COND_EQ
, TCG_REG_R0
, TCG_REG_R1
, 4);
1455 tcg_out_st32_rwb(s
, COND_EQ
, data_reg
, TCG_REG_R1
, addr_reg
);
1456 tcg_out_st32_12(s
, COND_EQ
, data_reg2
, TCG_REG_R1
, 4);
1461 label_ptr
= (void *) s
->code_ptr
;
1462 tcg_out_b_noaddr(s
, COND_EQ
);
1464 /* TODO: move this code to where the constants pool will be */
1465 /* Note that this code relies on the constraints we set in arm_op_defs[]
1466 * to ensure that later arguments are not passed to us in registers we
1467 * trash by moving the earlier arguments into them.
1469 argreg
= TCG_REG_R0
;
1470 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_AREG0
);
1471 #if TARGET_LONG_BITS == 64
1472 argreg
= tcg_out_arg_reg64(s
, argreg
, addr_reg
, addr_reg2
);
1474 argreg
= tcg_out_arg_reg32(s
, argreg
, addr_reg
);
1479 argreg
= tcg_out_arg_reg8(s
, argreg
, data_reg
);
1482 argreg
= tcg_out_arg_reg16(s
, argreg
, data_reg
);
1485 argreg
= tcg_out_arg_reg32(s
, argreg
, data_reg
);
1488 argreg
= tcg_out_arg_reg64(s
, argreg
, data_reg
, data_reg2
);
1492 argreg
= tcg_out_arg_imm32(s
, argreg
, mem_index
);
1493 tcg_out_call(s
, (tcg_target_long
) qemu_st_helpers
[s_bits
]);
1495 reloc_pc24(label_ptr
, (tcg_target_long
)s
->code_ptr
);
1496 #else /* !CONFIG_SOFTMMU */
1498 uint32_t offset
= GUEST_BASE
;
1503 i
= ctz32(offset
) & ~1;
1504 rot
= ((32 - i
) << 7) & 0xf00;
1506 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R1
, addr_reg
,
1507 ((offset
>> i
) & 0xff) | rot
);
1508 addr_reg
= TCG_REG_R1
;
1509 offset
&= ~(0xff << i
);
1514 tcg_out_st8_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1518 tcg_out_bswap16st(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1519 tcg_out_st16_8(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 0);
1521 tcg_out_st16_8(s
, COND_AL
, data_reg
, addr_reg
, 0);
1527 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1528 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 0);
1530 tcg_out_st32_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1534 /* TODO: use block store -
1535 * check that data_reg2 > data_reg or the other way */
1537 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg2
);
1538 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 0);
1539 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, data_reg
);
1540 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addr_reg
, 4);
1542 tcg_out_st32_12(s
, COND_AL
, data_reg
, addr_reg
, 0);
1543 tcg_out_st32_12(s
, COND_AL
, data_reg2
, addr_reg
, 4);
1550 static uint8_t *tb_ret_addr
;
1552 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1553 const TCGArg
*args
, const int *const_args
)
1555 TCGArg a0
, a1
, a2
, a3
, a4
, a5
;
1559 case INDEX_op_exit_tb
:
1561 uint8_t *ld_ptr
= s
->code_ptr
;
1563 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_PC
, 0);
1565 tcg_out_dat_imm(s
, COND_AL
, ARITH_MOV
, TCG_REG_R0
, 0, args
[0]);
1566 tcg_out_goto(s
, COND_AL
, (tcg_target_ulong
) tb_ret_addr
);
1568 *ld_ptr
= (uint8_t) (s
->code_ptr
- ld_ptr
) - 8;
1569 tcg_out32(s
, args
[0]);
1573 case INDEX_op_goto_tb
:
1574 if (s
->tb_jmp_offset
) {
1575 /* Direct jump method */
1576 #if defined(USE_DIRECT_JUMP)
1577 s
->tb_jmp_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1578 tcg_out_b_noaddr(s
, COND_AL
);
1580 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1581 s
->tb_jmp_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1585 /* Indirect jump method */
1587 c
= (int) (s
->tb_next
+ args
[0]) - ((int) s
->code_ptr
+ 8);
1588 if (c
> 0xfff || c
< -0xfff) {
1589 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
,
1590 (tcg_target_long
) (s
->tb_next
+ args
[0]));
1591 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_R0
, 0);
1593 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, c
);
1595 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_PC
, 0);
1596 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_R0
, 0);
1597 tcg_out32(s
, (tcg_target_long
) (s
->tb_next
+ args
[0]));
1600 s
->tb_next_offset
[args
[0]] = s
->code_ptr
- s
->code_buf
;
1604 tcg_out_call(s
, args
[0]);
1606 tcg_out_callr(s
, COND_AL
, args
[0]);
1609 tcg_out_goto_label(s
, COND_AL
, args
[0]);
1612 case INDEX_op_ld8u_i32
:
1613 tcg_out_ld8u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1615 case INDEX_op_ld8s_i32
:
1616 tcg_out_ld8s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1618 case INDEX_op_ld16u_i32
:
1619 tcg_out_ld16u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1621 case INDEX_op_ld16s_i32
:
1622 tcg_out_ld16s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1624 case INDEX_op_ld_i32
:
1625 tcg_out_ld32u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1627 case INDEX_op_st8_i32
:
1628 tcg_out_st8(s
, COND_AL
, args
[0], args
[1], args
[2]);
1630 case INDEX_op_st16_i32
:
1631 tcg_out_st16(s
, COND_AL
, args
[0], args
[1], args
[2]);
1633 case INDEX_op_st_i32
:
1634 tcg_out_st32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1637 case INDEX_op_mov_i32
:
1638 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
,
1639 args
[0], 0, args
[1], SHIFT_IMM_LSL(0));
1641 case INDEX_op_movi_i32
:
1642 tcg_out_movi32(s
, COND_AL
, args
[0], args
[1]);
1644 case INDEX_op_movcond_i32
:
1645 /* Constraints mean that v2 is always in the same register as dest,
1646 * so we only need to do "if condition passed, move v1 to dest".
1648 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1649 args
[1], args
[2], const_args
[2]);
1650 tcg_out_dat_rIK(s
, tcg_cond_to_arm_cond
[args
[5]], ARITH_MOV
,
1651 ARITH_MVN
, args
[0], 0, args
[3], const_args
[3]);
1653 case INDEX_op_add_i32
:
1654 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
, ARITH_SUB
,
1655 args
[0], args
[1], args
[2], const_args
[2]);
1657 case INDEX_op_sub_i32
:
1658 if (const_args
[1]) {
1659 if (const_args
[2]) {
1660 tcg_out_movi32(s
, COND_AL
, args
[0], args
[1] - args
[2]);
1662 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
,
1663 args
[0], args
[2], args
[1], 1);
1666 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
, ARITH_ADD
,
1667 args
[0], args
[1], args
[2], const_args
[2]);
1670 case INDEX_op_and_i32
:
1671 tcg_out_dat_rIK(s
, COND_AL
, ARITH_AND
, ARITH_BIC
,
1672 args
[0], args
[1], args
[2], const_args
[2]);
1674 case INDEX_op_andc_i32
:
1675 tcg_out_dat_rIK(s
, COND_AL
, ARITH_BIC
, ARITH_AND
,
1676 args
[0], args
[1], args
[2], const_args
[2]);
1678 case INDEX_op_or_i32
:
1681 case INDEX_op_xor_i32
:
1685 tcg_out_dat_rI(s
, COND_AL
, c
, args
[0], args
[1], args
[2], const_args
[2]);
1687 case INDEX_op_add2_i32
:
1688 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1689 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1690 if (a0
== a3
|| (a0
== a5
&& !const_args
[5])) {
1693 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
| TO_CPSR
, ARITH_SUB
| TO_CPSR
,
1694 a0
, a2
, a4
, const_args
[4]);
1695 tcg_out_dat_rIK(s
, COND_AL
, ARITH_ADC
, ARITH_SBC
,
1696 a1
, a3
, a5
, const_args
[5]);
1697 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1699 case INDEX_op_sub2_i32
:
1700 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1701 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1702 if ((a0
== a3
&& !const_args
[3]) || (a0
== a5
&& !const_args
[5])) {
1705 if (const_args
[2]) {
1706 if (const_args
[4]) {
1707 tcg_out_movi32(s
, COND_AL
, a0
, a4
);
1710 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
| TO_CPSR
, a0
, a4
, a2
, 1);
1712 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
| TO_CPSR
,
1713 ARITH_ADD
| TO_CPSR
, a0
, a2
, a4
, const_args
[4]);
1715 if (const_args
[3]) {
1716 if (const_args
[5]) {
1717 tcg_out_movi32(s
, COND_AL
, a1
, a5
);
1720 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSC
, a1
, a5
, a3
, 1);
1722 tcg_out_dat_rIK(s
, COND_AL
, ARITH_SBC
, ARITH_ADC
,
1723 a1
, a3
, a5
, const_args
[5]);
1725 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1727 case INDEX_op_neg_i32
:
1728 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, args
[0], args
[1], 0);
1730 case INDEX_op_not_i32
:
1731 tcg_out_dat_reg(s
, COND_AL
,
1732 ARITH_MVN
, args
[0], 0, args
[1], SHIFT_IMM_LSL(0));
1734 case INDEX_op_mul_i32
:
1735 tcg_out_mul32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1737 case INDEX_op_mulu2_i32
:
1738 tcg_out_umull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1740 case INDEX_op_muls2_i32
:
1741 tcg_out_smull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1743 /* XXX: Perhaps args[2] & 0x1f is wrong */
1744 case INDEX_op_shl_i32
:
1746 SHIFT_IMM_LSL(args
[2] & 0x1f) : SHIFT_REG_LSL(args
[2]);
1748 case INDEX_op_shr_i32
:
1749 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_LSR(args
[2] & 0x1f) :
1750 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args
[2]);
1752 case INDEX_op_sar_i32
:
1753 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ASR(args
[2] & 0x1f) :
1754 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args
[2]);
1756 case INDEX_op_rotr_i32
:
1757 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ROR(args
[2] & 0x1f) :
1758 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args
[2]);
1761 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1], c
);
1764 case INDEX_op_rotl_i32
:
1765 if (const_args
[2]) {
1766 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1767 ((0x20 - args
[2]) & 0x1f) ?
1768 SHIFT_IMM_ROR((0x20 - args
[2]) & 0x1f) :
1771 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, TCG_REG_R8
, args
[1], 0x20);
1772 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1773 SHIFT_REG_ROR(TCG_REG_R8
));
1777 case INDEX_op_brcond_i32
:
1778 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1779 args
[0], args
[1], const_args
[1]);
1780 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[2]], args
[3]);
1782 case INDEX_op_brcond2_i32
:
1783 /* The resulting conditions are:
1784 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1785 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1786 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1787 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1788 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1789 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1791 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1792 args
[1], args
[3], const_args
[3]);
1793 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1794 args
[0], args
[2], const_args
[2]);
1795 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[4]], args
[5]);
1797 case INDEX_op_setcond_i32
:
1798 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1799 args
[1], args
[2], const_args
[2]);
1800 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[3]],
1801 ARITH_MOV
, args
[0], 0, 1);
1802 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[3])],
1803 ARITH_MOV
, args
[0], 0, 0);
1805 case INDEX_op_setcond2_i32
:
1806 /* See brcond2_i32 comment */
1807 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1808 args
[2], args
[4], const_args
[4]);
1809 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1810 args
[1], args
[3], const_args
[3]);
1811 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[5]],
1812 ARITH_MOV
, args
[0], 0, 1);
1813 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[5])],
1814 ARITH_MOV
, args
[0], 0, 0);
1817 case INDEX_op_qemu_ld8u
:
1818 tcg_out_qemu_ld(s
, args
, 0);
1820 case INDEX_op_qemu_ld8s
:
1821 tcg_out_qemu_ld(s
, args
, 0 | 4);
1823 case INDEX_op_qemu_ld16u
:
1824 tcg_out_qemu_ld(s
, args
, 1);
1826 case INDEX_op_qemu_ld16s
:
1827 tcg_out_qemu_ld(s
, args
, 1 | 4);
1829 case INDEX_op_qemu_ld32
:
1830 tcg_out_qemu_ld(s
, args
, 2);
1832 case INDEX_op_qemu_ld64
:
1833 tcg_out_qemu_ld(s
, args
, 3);
1836 case INDEX_op_qemu_st8
:
1837 tcg_out_qemu_st(s
, args
, 0);
1839 case INDEX_op_qemu_st16
:
1840 tcg_out_qemu_st(s
, args
, 1);
1842 case INDEX_op_qemu_st32
:
1843 tcg_out_qemu_st(s
, args
, 2);
1845 case INDEX_op_qemu_st64
:
1846 tcg_out_qemu_st(s
, args
, 3);
1849 case INDEX_op_bswap16_i32
:
1850 tcg_out_bswap16(s
, COND_AL
, args
[0], args
[1]);
1852 case INDEX_op_bswap32_i32
:
1853 tcg_out_bswap32(s
, COND_AL
, args
[0], args
[1]);
1856 case INDEX_op_ext8s_i32
:
1857 tcg_out_ext8s(s
, COND_AL
, args
[0], args
[1]);
1859 case INDEX_op_ext16s_i32
:
1860 tcg_out_ext16s(s
, COND_AL
, args
[0], args
[1]);
1862 case INDEX_op_ext16u_i32
:
1863 tcg_out_ext16u(s
, COND_AL
, args
[0], args
[1]);
1866 case INDEX_op_deposit_i32
:
1867 tcg_out_deposit(s
, COND_AL
, args
[0], args
[2],
1868 args
[3], args
[4], const_args
[2]);
1876 static const TCGTargetOpDef arm_op_defs
[] = {
1877 { INDEX_op_exit_tb
, { } },
1878 { INDEX_op_goto_tb
, { } },
1879 { INDEX_op_call
, { "ri" } },
1880 { INDEX_op_br
, { } },
1882 { INDEX_op_mov_i32
, { "r", "r" } },
1883 { INDEX_op_movi_i32
, { "r" } },
1885 { INDEX_op_ld8u_i32
, { "r", "r" } },
1886 { INDEX_op_ld8s_i32
, { "r", "r" } },
1887 { INDEX_op_ld16u_i32
, { "r", "r" } },
1888 { INDEX_op_ld16s_i32
, { "r", "r" } },
1889 { INDEX_op_ld_i32
, { "r", "r" } },
1890 { INDEX_op_st8_i32
, { "r", "r" } },
1891 { INDEX_op_st16_i32
, { "r", "r" } },
1892 { INDEX_op_st_i32
, { "r", "r" } },
1894 /* TODO: "r", "r", "ri" */
1895 { INDEX_op_add_i32
, { "r", "r", "rIN" } },
1896 { INDEX_op_sub_i32
, { "r", "rI", "rIN" } },
1897 { INDEX_op_mul_i32
, { "r", "r", "r" } },
1898 { INDEX_op_mulu2_i32
, { "r", "r", "r", "r" } },
1899 { INDEX_op_muls2_i32
, { "r", "r", "r", "r" } },
1900 { INDEX_op_and_i32
, { "r", "r", "rIK" } },
1901 { INDEX_op_andc_i32
, { "r", "r", "rIK" } },
1902 { INDEX_op_or_i32
, { "r", "r", "rI" } },
1903 { INDEX_op_xor_i32
, { "r", "r", "rI" } },
1904 { INDEX_op_neg_i32
, { "r", "r" } },
1905 { INDEX_op_not_i32
, { "r", "r" } },
1907 { INDEX_op_shl_i32
, { "r", "r", "ri" } },
1908 { INDEX_op_shr_i32
, { "r", "r", "ri" } },
1909 { INDEX_op_sar_i32
, { "r", "r", "ri" } },
1910 { INDEX_op_rotl_i32
, { "r", "r", "ri" } },
1911 { INDEX_op_rotr_i32
, { "r", "r", "ri" } },
1913 { INDEX_op_brcond_i32
, { "r", "rIN" } },
1914 { INDEX_op_setcond_i32
, { "r", "r", "rIN" } },
1915 { INDEX_op_movcond_i32
, { "r", "r", "rIN", "rIK", "0" } },
1917 { INDEX_op_add2_i32
, { "r", "r", "r", "r", "rIN", "rIK" } },
1918 { INDEX_op_sub2_i32
, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1919 { INDEX_op_brcond2_i32
, { "r", "r", "rIN", "rIN" } },
1920 { INDEX_op_setcond2_i32
, { "r", "r", "r", "rIN", "rIN" } },
1922 #if TARGET_LONG_BITS == 32
1923 { INDEX_op_qemu_ld8u
, { "r", "l" } },
1924 { INDEX_op_qemu_ld8s
, { "r", "l" } },
1925 { INDEX_op_qemu_ld16u
, { "r", "l" } },
1926 { INDEX_op_qemu_ld16s
, { "r", "l" } },
1927 { INDEX_op_qemu_ld32
, { "r", "l" } },
1928 { INDEX_op_qemu_ld64
, { "L", "L", "l" } },
1930 { INDEX_op_qemu_st8
, { "s", "s" } },
1931 { INDEX_op_qemu_st16
, { "s", "s" } },
1932 { INDEX_op_qemu_st32
, { "s", "s" } },
1933 { INDEX_op_qemu_st64
, { "S", "S", "s" } },
1935 { INDEX_op_qemu_ld8u
, { "r", "l", "l" } },
1936 { INDEX_op_qemu_ld8s
, { "r", "l", "l" } },
1937 { INDEX_op_qemu_ld16u
, { "r", "l", "l" } },
1938 { INDEX_op_qemu_ld16s
, { "r", "l", "l" } },
1939 { INDEX_op_qemu_ld32
, { "r", "l", "l" } },
1940 { INDEX_op_qemu_ld64
, { "L", "L", "l", "l" } },
1942 { INDEX_op_qemu_st8
, { "s", "s", "s" } },
1943 { INDEX_op_qemu_st16
, { "s", "s", "s" } },
1944 { INDEX_op_qemu_st32
, { "s", "s", "s" } },
1945 { INDEX_op_qemu_st64
, { "S", "S", "s", "s" } },
1948 { INDEX_op_bswap16_i32
, { "r", "r" } },
1949 { INDEX_op_bswap32_i32
, { "r", "r" } },
1951 { INDEX_op_ext8s_i32
, { "r", "r" } },
1952 { INDEX_op_ext16s_i32
, { "r", "r" } },
1953 { INDEX_op_ext16u_i32
, { "r", "r" } },
1955 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
1960 static void tcg_target_init(TCGContext
*s
)
1962 #if !defined(CONFIG_USER_ONLY)
1964 if ((1 << CPU_TLB_ENTRY_BITS
) != sizeof(CPUTLBEntry
))
1968 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I32
], 0, 0xffff);
1969 tcg_regset_set32(tcg_target_call_clobber_regs
, 0,
1974 (1 << TCG_REG_R12
) |
1975 (1 << TCG_REG_R14
));
1977 tcg_regset_clear(s
->reserved_regs
);
1978 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_CALL_STACK
);
1979 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_R8
);
1980 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_PC
);
1982 tcg_add_target_add_op_defs(arm_op_defs
);
1985 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
1986 TCGReg arg1
, tcg_target_long arg2
)
1988 tcg_out_ld32u(s
, COND_AL
, arg
, arg1
, arg2
);
1991 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
1992 TCGReg arg1
, tcg_target_long arg2
)
1994 tcg_out_st32(s
, COND_AL
, arg
, arg1
, arg2
);
1997 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
1998 TCGReg ret
, TCGReg arg
)
2000 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, ret
, 0, arg
, SHIFT_IMM_LSL(0));
2003 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
2004 TCGReg ret
, tcg_target_long arg
)
2006 tcg_out_movi32(s
, COND_AL
, ret
, arg
);
2009 static void tcg_target_qemu_prologue(TCGContext
*s
)
2013 /* Calling convention requires us to save r4-r11 and lr. */
2014 /* stmdb sp!, { r4 - r11, lr } */
2015 tcg_out32(s
, (COND_AL
<< 28) | 0x092d4ff0);
2017 /* Allocate the local stack frame. */
2018 frame_size
= TCG_STATIC_CALL_ARGS_SIZE
;
2019 frame_size
+= CPU_TEMP_BUF_NLONGS
* sizeof(long);
2020 /* We saved an odd number of registers above; keep an 8 aligned stack. */
2021 frame_size
= ((frame_size
+ TCG_TARGET_STACK_ALIGN
- 1)
2022 & -TCG_TARGET_STACK_ALIGN
) + 4;
2024 tcg_out_dat_rI(s
, COND_AL
, ARITH_SUB
, TCG_REG_CALL_STACK
,
2025 TCG_REG_CALL_STACK
, frame_size
, 1);
2026 tcg_set_frame(s
, TCG_REG_CALL_STACK
, TCG_STATIC_CALL_ARGS_SIZE
,
2027 CPU_TEMP_BUF_NLONGS
* sizeof(long));
2029 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
2031 tcg_out_bx(s
, COND_AL
, tcg_target_call_iarg_regs
[1]);
2032 tb_ret_addr
= s
->code_ptr
;
2034 /* Epilogue. We branch here via tb_ret_addr. */
2035 tcg_out_dat_rI(s
, COND_AL
, ARITH_ADD
, TCG_REG_CALL_STACK
,
2036 TCG_REG_CALL_STACK
, frame_size
, 1);
2038 /* ldmia sp!, { r4 - r11, pc } */
2039 tcg_out32(s
, (COND_AL
<< 28) | 0x08bd8ff0);