2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Andrzej Zaborowski
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "tcg-be-ldst.h"
28 /* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
30 # if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
31 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
32 || defined(__ARM_ARCH_7EM__)
34 # elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
35 || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
36 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
38 # elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
39 || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
40 || defined(__ARM_ARCH_5TEJ__)
47 static int arm_arch
= __ARM_ARCH
;
49 #if defined(__ARM_ARCH_5T__) \
50 || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
51 # define use_armv5t_instructions 1
53 # define use_armv5t_instructions use_armv6_instructions
56 #define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6)
57 #define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7)
59 #ifndef use_idiv_instructions
60 bool use_idiv_instructions
;
63 /* ??? Ought to think about changing CONFIG_SOFTMMU to always defined. */
65 # define USING_SOFTMMU 1
67 # define USING_SOFTMMU 0
70 #ifdef CONFIG_DEBUG_TCG
71 static const char * const tcg_target_reg_names
[TCG_TARGET_NB_REGS
] = {
91 static const int tcg_target_reg_alloc_order
[] = {
109 static const int tcg_target_call_iarg_regs
[4] = {
110 TCG_REG_R0
, TCG_REG_R1
, TCG_REG_R2
, TCG_REG_R3
112 static const int tcg_target_call_oarg_regs
[2] = {
113 TCG_REG_R0
, TCG_REG_R1
116 #define TCG_REG_TMP TCG_REG_R12
118 static inline void reloc_pc24(tcg_insn_unit
*code_ptr
, tcg_insn_unit
*target
)
120 ptrdiff_t offset
= (tcg_ptr_byte_diff(target
, code_ptr
) - 8) >> 2;
121 *code_ptr
= (*code_ptr
& ~0xffffff) | (offset
& 0xffffff);
124 static inline void reloc_pc24_atomic(tcg_insn_unit
*code_ptr
, tcg_insn_unit
*target
)
126 ptrdiff_t offset
= (tcg_ptr_byte_diff(target
, code_ptr
) - 8) >> 2;
127 tcg_insn_unit insn
= atomic_read(code_ptr
);
128 tcg_debug_assert(offset
== sextract32(offset
, 0, 24));
129 atomic_set(code_ptr
, deposit32(insn
, 0, 24, offset
));
132 static void patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
133 intptr_t value
, intptr_t addend
)
135 tcg_debug_assert(type
== R_ARM_PC24
);
136 tcg_debug_assert(addend
== 0);
137 reloc_pc24(code_ptr
, (tcg_insn_unit
*)value
);
140 #define TCG_CT_CONST_ARM 0x100
141 #define TCG_CT_CONST_INV 0x200
142 #define TCG_CT_CONST_NEG 0x400
143 #define TCG_CT_CONST_ZERO 0x800
145 /* parse target specific constraints */
146 static int target_parse_constraint(TCGArgConstraint
*ct
, const char **pct_str
)
153 ct
->ct
|= TCG_CT_CONST_ARM
;
156 ct
->ct
|= TCG_CT_CONST_INV
;
158 case 'N': /* The gcc constraint letter is L, already used here. */
159 ct
->ct
|= TCG_CT_CONST_NEG
;
162 ct
->ct
|= TCG_CT_CONST_ZERO
;
166 ct
->ct
|= TCG_CT_REG
;
167 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
170 /* qemu_ld address */
172 ct
->ct
|= TCG_CT_REG
;
173 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
174 #ifdef CONFIG_SOFTMMU
175 /* r0-r2,lr will be overwritten when reading the tlb entry,
176 so don't use these. */
177 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
178 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
179 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
180 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R14
);
184 /* qemu_st address & data */
186 ct
->ct
|= TCG_CT_REG
;
187 tcg_regset_set32(ct
->u
.regs
, 0, (1 << TCG_TARGET_NB_REGS
) - 1);
188 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
189 and r0-r1 doing the byte swapping, so don't use these. */
190 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R0
);
191 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R1
);
192 #if defined(CONFIG_SOFTMMU)
193 /* Avoid clashes with registers being used for helper args */
194 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R2
);
195 #if TARGET_LONG_BITS == 64
196 /* Avoid clashes with registers being used for helper args */
197 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R3
);
199 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_R14
);
212 static inline uint32_t rotl(uint32_t val
, int n
)
214 return (val
<< n
) | (val
>> (32 - n
));
217 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
218 right-rotated by an even amount between 0 and 30. */
219 static inline int encode_imm(uint32_t imm
)
223 /* simple case, only lower bits */
224 if ((imm
& ~0xff) == 0)
226 /* then try a simple even shift */
227 shift
= ctz32(imm
) & ~1;
228 if (((imm
>> shift
) & ~0xff) == 0)
230 /* now try harder with rotations */
231 if ((rotl(imm
, 2) & ~0xff) == 0)
233 if ((rotl(imm
, 4) & ~0xff) == 0)
235 if ((rotl(imm
, 6) & ~0xff) == 0)
237 /* imm can't be encoded */
241 static inline int check_fit_imm(uint32_t imm
)
243 return encode_imm(imm
) >= 0;
246 /* Test if a constant matches the constraint.
247 * TODO: define constraints for:
249 * ldr/str offset: between -0xfff and 0xfff
250 * ldrh/strh offset: between -0xff and 0xff
251 * mov operand2: values represented with x << (2 * y), x < 0x100
252 * add, sub, eor...: ditto
254 static inline int tcg_target_const_match(tcg_target_long val
, TCGType type
,
255 const TCGArgConstraint
*arg_ct
)
259 if (ct
& TCG_CT_CONST
) {
261 } else if ((ct
& TCG_CT_CONST_ARM
) && check_fit_imm(val
)) {
263 } else if ((ct
& TCG_CT_CONST_INV
) && check_fit_imm(~val
)) {
265 } else if ((ct
& TCG_CT_CONST_NEG
) && check_fit_imm(-val
)) {
267 } else if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
274 #define TO_CPSR (1 << 20)
277 ARITH_AND
= 0x0 << 21,
278 ARITH_EOR
= 0x1 << 21,
279 ARITH_SUB
= 0x2 << 21,
280 ARITH_RSB
= 0x3 << 21,
281 ARITH_ADD
= 0x4 << 21,
282 ARITH_ADC
= 0x5 << 21,
283 ARITH_SBC
= 0x6 << 21,
284 ARITH_RSC
= 0x7 << 21,
285 ARITH_TST
= 0x8 << 21 | TO_CPSR
,
286 ARITH_CMP
= 0xa << 21 | TO_CPSR
,
287 ARITH_CMN
= 0xb << 21 | TO_CPSR
,
288 ARITH_ORR
= 0xc << 21,
289 ARITH_MOV
= 0xd << 21,
290 ARITH_BIC
= 0xe << 21,
291 ARITH_MVN
= 0xf << 21,
293 INSN_LDR_IMM
= 0x04100000,
294 INSN_LDR_REG
= 0x06100000,
295 INSN_STR_IMM
= 0x04000000,
296 INSN_STR_REG
= 0x06000000,
298 INSN_LDRH_IMM
= 0x005000b0,
299 INSN_LDRH_REG
= 0x001000b0,
300 INSN_LDRSH_IMM
= 0x005000f0,
301 INSN_LDRSH_REG
= 0x001000f0,
302 INSN_STRH_IMM
= 0x004000b0,
303 INSN_STRH_REG
= 0x000000b0,
305 INSN_LDRB_IMM
= 0x04500000,
306 INSN_LDRB_REG
= 0x06500000,
307 INSN_LDRSB_IMM
= 0x005000d0,
308 INSN_LDRSB_REG
= 0x001000d0,
309 INSN_STRB_IMM
= 0x04400000,
310 INSN_STRB_REG
= 0x06400000,
312 INSN_LDRD_IMM
= 0x004000d0,
313 INSN_LDRD_REG
= 0x000000d0,
314 INSN_STRD_IMM
= 0x004000f0,
315 INSN_STRD_REG
= 0x000000f0,
318 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
319 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
320 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
321 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
322 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
323 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
324 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
325 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
327 enum arm_cond_code_e
{
330 COND_CS
= 0x2, /* Unsigned greater or equal */
331 COND_CC
= 0x3, /* Unsigned less than */
332 COND_MI
= 0x4, /* Negative */
333 COND_PL
= 0x5, /* Zero or greater */
334 COND_VS
= 0x6, /* Overflow */
335 COND_VC
= 0x7, /* No overflow */
336 COND_HI
= 0x8, /* Unsigned greater than */
337 COND_LS
= 0x9, /* Unsigned less or equal */
345 static const uint8_t tcg_cond_to_arm_cond
[] = {
346 [TCG_COND_EQ
] = COND_EQ
,
347 [TCG_COND_NE
] = COND_NE
,
348 [TCG_COND_LT
] = COND_LT
,
349 [TCG_COND_GE
] = COND_GE
,
350 [TCG_COND_LE
] = COND_LE
,
351 [TCG_COND_GT
] = COND_GT
,
353 [TCG_COND_LTU
] = COND_CC
,
354 [TCG_COND_GEU
] = COND_CS
,
355 [TCG_COND_LEU
] = COND_LS
,
356 [TCG_COND_GTU
] = COND_HI
,
359 static inline void tcg_out_bx(TCGContext
*s
, int cond
, int rn
)
361 tcg_out32(s
, (cond
<< 28) | 0x012fff10 | rn
);
364 static inline void tcg_out_b(TCGContext
*s
, int cond
, int32_t offset
)
366 tcg_out32(s
, (cond
<< 28) | 0x0a000000 |
367 (((offset
- 8) >> 2) & 0x00ffffff));
370 static inline void tcg_out_b_noaddr(TCGContext
*s
, int cond
)
372 /* We pay attention here to not modify the branch target by masking
373 the corresponding bytes. This ensure that caches and memory are
374 kept coherent during retranslation. */
375 tcg_out32(s
, deposit32(*s
->code_ptr
, 24, 8, (cond
<< 4) | 0x0a));
378 static inline void tcg_out_bl_noaddr(TCGContext
*s
, int cond
)
380 /* We pay attention here to not modify the branch target by masking
381 the corresponding bytes. This ensure that caches and memory are
382 kept coherent during retranslation. */
383 tcg_out32(s
, deposit32(*s
->code_ptr
, 24, 8, (cond
<< 4) | 0x0b));
386 static inline void tcg_out_bl(TCGContext
*s
, int cond
, int32_t offset
)
388 tcg_out32(s
, (cond
<< 28) | 0x0b000000 |
389 (((offset
- 8) >> 2) & 0x00ffffff));
392 static inline void tcg_out_blx(TCGContext
*s
, int cond
, int rn
)
394 tcg_out32(s
, (cond
<< 28) | 0x012fff30 | rn
);
397 static inline void tcg_out_blx_imm(TCGContext
*s
, int32_t offset
)
399 tcg_out32(s
, 0xfa000000 | ((offset
& 2) << 23) |
400 (((offset
- 8) >> 2) & 0x00ffffff));
403 static inline void tcg_out_dat_reg(TCGContext
*s
,
404 int cond
, int opc
, int rd
, int rn
, int rm
, int shift
)
406 tcg_out32(s
, (cond
<< 28) | (0 << 25) | opc
|
407 (rn
<< 16) | (rd
<< 12) | shift
| rm
);
410 static inline void tcg_out_nop(TCGContext
*s
)
412 if (use_armv7_instructions
) {
413 /* Architected nop introduced in v6k. */
414 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
415 also Just So Happened to do nothing on pre-v6k so that we
416 don't need to conditionalize it? */
417 tcg_out32(s
, 0xe320f000);
419 /* Prior to that the assembler uses mov r0, r0. */
420 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, 0, 0, 0, SHIFT_IMM_LSL(0));
424 static inline void tcg_out_mov_reg(TCGContext
*s
, int cond
, int rd
, int rm
)
426 /* Simple reg-reg move, optimising out the 'do nothing' case */
428 tcg_out_dat_reg(s
, cond
, ARITH_MOV
, rd
, 0, rm
, SHIFT_IMM_LSL(0));
432 static inline void tcg_out_dat_imm(TCGContext
*s
,
433 int cond
, int opc
, int rd
, int rn
, int im
)
435 tcg_out32(s
, (cond
<< 28) | (1 << 25) | opc
|
436 (rn
<< 16) | (rd
<< 12) | im
);
439 static void tcg_out_movi32(TCGContext
*s
, int cond
, int rd
, uint32_t arg
)
443 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
444 Speed things up by only checking when movt would be required.
445 Prior to armv7, have one go at fully rotated immediates before
446 doing the decomposition thing below. */
447 if (!use_armv7_instructions
|| (arg
& 0xffff0000)) {
448 rot
= encode_imm(arg
);
450 tcg_out_dat_imm(s
, cond
, ARITH_MOV
, rd
, 0,
451 rotl(arg
, rot
) | (rot
<< 7));
454 rot
= encode_imm(~arg
);
456 tcg_out_dat_imm(s
, cond
, ARITH_MVN
, rd
, 0,
457 rotl(~arg
, rot
) | (rot
<< 7));
462 /* Use movw + movt. */
463 if (use_armv7_instructions
) {
465 tcg_out32(s
, (cond
<< 28) | 0x03000000 | (rd
<< 12)
466 | ((arg
<< 4) & 0x000f0000) | (arg
& 0xfff));
467 if (arg
& 0xffff0000) {
469 tcg_out32(s
, (cond
<< 28) | 0x03400000 | (rd
<< 12)
470 | ((arg
>> 12) & 0x000f0000) | ((arg
>> 16) & 0xfff));
475 /* TODO: This is very suboptimal, we can easily have a constant
476 pool somewhere after all the instructions. */
479 /* If we have lots of leading 1's, we can shorten the sequence by
480 beginning with mvn and then clearing higher bits with eor. */
481 if (clz32(~arg
) > clz32(arg
)) {
482 opc
= ARITH_MVN
, arg
= ~arg
;
485 int i
= ctz32(arg
) & ~1;
486 rot
= ((32 - i
) << 7) & 0xf00;
487 tcg_out_dat_imm(s
, cond
, opc
, rd
, rn
, ((arg
>> i
) & 0xff) | rot
);
495 static inline void tcg_out_dat_rI(TCGContext
*s
, int cond
, int opc
, TCGArg dst
,
496 TCGArg lhs
, TCGArg rhs
, int rhs_is_const
)
498 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
499 * rhs must satisfy the "rI" constraint.
502 int rot
= encode_imm(rhs
);
503 tcg_debug_assert(rot
>= 0);
504 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
506 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
510 static void tcg_out_dat_rIK(TCGContext
*s
, int cond
, int opc
, int opinv
,
511 TCGReg dst
, TCGReg lhs
, TCGArg rhs
,
514 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
515 * rhs must satisfy the "rIK" constraint.
518 int rot
= encode_imm(rhs
);
521 rot
= encode_imm(rhs
);
522 tcg_debug_assert(rot
>= 0);
525 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
527 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
531 static void tcg_out_dat_rIN(TCGContext
*s
, int cond
, int opc
, int opneg
,
532 TCGArg dst
, TCGArg lhs
, TCGArg rhs
,
535 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
536 * rhs must satisfy the "rIN" constraint.
539 int rot
= encode_imm(rhs
);
542 rot
= encode_imm(rhs
);
543 tcg_debug_assert(rot
>= 0);
546 tcg_out_dat_imm(s
, cond
, opc
, dst
, lhs
, rotl(rhs
, rot
) | (rot
<< 7));
548 tcg_out_dat_reg(s
, cond
, opc
, dst
, lhs
, rhs
, SHIFT_IMM_LSL(0));
552 static inline void tcg_out_mul32(TCGContext
*s
, int cond
, TCGReg rd
,
553 TCGReg rn
, TCGReg rm
)
555 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
556 if (!use_armv6_instructions
&& rd
== rn
) {
558 /* rd == rn == rm; copy an input to tmp first. */
559 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
560 rm
= rn
= TCG_REG_TMP
;
567 tcg_out32(s
, (cond
<< 28) | 0x90 | (rd
<< 16) | (rm
<< 8) | rn
);
570 static inline void tcg_out_umull32(TCGContext
*s
, int cond
, TCGReg rd0
,
571 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
573 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
574 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
575 if (rd0
== rm
|| rd1
== rm
) {
576 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
585 tcg_out32(s
, (cond
<< 28) | 0x00800090 |
586 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
589 static inline void tcg_out_smull32(TCGContext
*s
, int cond
, TCGReg rd0
,
590 TCGReg rd1
, TCGReg rn
, TCGReg rm
)
592 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
593 if (!use_armv6_instructions
&& (rd0
== rn
|| rd1
== rn
)) {
594 if (rd0
== rm
|| rd1
== rm
) {
595 tcg_out_mov_reg(s
, cond
, TCG_REG_TMP
, rn
);
604 tcg_out32(s
, (cond
<< 28) | 0x00c00090 |
605 (rd1
<< 16) | (rd0
<< 12) | (rm
<< 8) | rn
);
608 static inline void tcg_out_sdiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
610 tcg_out32(s
, 0x0710f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
613 static inline void tcg_out_udiv(TCGContext
*s
, int cond
, int rd
, int rn
, int rm
)
615 tcg_out32(s
, 0x0730f010 | (cond
<< 28) | (rd
<< 16) | rn
| (rm
<< 8));
618 static inline void tcg_out_ext8s(TCGContext
*s
, int cond
,
621 if (use_armv6_instructions
) {
623 tcg_out32(s
, 0x06af0070 | (cond
<< 28) | (rd
<< 12) | rn
);
625 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
626 rd
, 0, rn
, SHIFT_IMM_LSL(24));
627 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
628 rd
, 0, rd
, SHIFT_IMM_ASR(24));
632 static inline void tcg_out_ext8u(TCGContext
*s
, int cond
,
635 tcg_out_dat_imm(s
, cond
, ARITH_AND
, rd
, rn
, 0xff);
638 static inline void tcg_out_ext16s(TCGContext
*s
, int cond
,
641 if (use_armv6_instructions
) {
643 tcg_out32(s
, 0x06bf0070 | (cond
<< 28) | (rd
<< 12) | rn
);
645 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
646 rd
, 0, rn
, SHIFT_IMM_LSL(16));
647 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
648 rd
, 0, rd
, SHIFT_IMM_ASR(16));
652 static inline void tcg_out_ext16u(TCGContext
*s
, int cond
,
655 if (use_armv6_instructions
) {
657 tcg_out32(s
, 0x06ff0070 | (cond
<< 28) | (rd
<< 12) | rn
);
659 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
660 rd
, 0, rn
, SHIFT_IMM_LSL(16));
661 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
662 rd
, 0, rd
, SHIFT_IMM_LSR(16));
666 static inline void tcg_out_bswap16s(TCGContext
*s
, int cond
, int rd
, int rn
)
668 if (use_armv6_instructions
) {
670 tcg_out32(s
, 0x06ff0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
672 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
673 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
674 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
675 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_ASR(16));
676 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
677 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
681 static inline void tcg_out_bswap16(TCGContext
*s
, int cond
, int rd
, int rn
)
683 if (use_armv6_instructions
) {
685 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
687 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
688 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSL(24));
689 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
690 TCG_REG_TMP
, 0, TCG_REG_TMP
, SHIFT_IMM_LSR(16));
691 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
692 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSR(8));
696 /* swap the two low bytes assuming that the two high input bytes and the
697 two high output bit can hold any value. */
698 static inline void tcg_out_bswap16st(TCGContext
*s
, int cond
, int rd
, int rn
)
700 if (use_armv6_instructions
) {
702 tcg_out32(s
, 0x06bf0fb0 | (cond
<< 28) | (rd
<< 12) | rn
);
704 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
705 TCG_REG_TMP
, 0, rn
, SHIFT_IMM_LSR(8));
706 tcg_out_dat_imm(s
, cond
, ARITH_AND
, TCG_REG_TMP
, TCG_REG_TMP
, 0xff);
707 tcg_out_dat_reg(s
, cond
, ARITH_ORR
,
708 rd
, TCG_REG_TMP
, rn
, SHIFT_IMM_LSL(8));
712 static inline void tcg_out_bswap32(TCGContext
*s
, int cond
, int rd
, int rn
)
714 if (use_armv6_instructions
) {
716 tcg_out32(s
, 0x06bf0f30 | (cond
<< 28) | (rd
<< 12) | rn
);
718 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
719 TCG_REG_TMP
, rn
, rn
, SHIFT_IMM_ROR(16));
720 tcg_out_dat_imm(s
, cond
, ARITH_BIC
,
721 TCG_REG_TMP
, TCG_REG_TMP
, 0xff | 0x800);
722 tcg_out_dat_reg(s
, cond
, ARITH_MOV
,
723 rd
, 0, rn
, SHIFT_IMM_ROR(8));
724 tcg_out_dat_reg(s
, cond
, ARITH_EOR
,
725 rd
, rd
, TCG_REG_TMP
, SHIFT_IMM_LSR(8));
729 bool tcg_target_deposit_valid(int ofs
, int len
)
731 /* ??? Without bfi, we could improve over generic code by combining
732 the right-shift from a non-zero ofs with the orr. We do run into
733 problems when rd == rs, and the mask generated from ofs+len doesn't
734 fit into an immediate. We would have to be careful not to pessimize
735 wrt the optimizations performed on the expanded code. */
736 return use_armv7_instructions
;
739 static inline void tcg_out_deposit(TCGContext
*s
, int cond
, TCGReg rd
,
740 TCGArg a1
, int ofs
, int len
, bool const_a1
)
743 /* bfi becomes bfc with rn == 15. */
747 tcg_out32(s
, 0x07c00010 | (cond
<< 28) | (rd
<< 12) | a1
748 | (ofs
<< 7) | ((ofs
+ len
- 1) << 16));
751 /* Note that this routine is used for both LDR and LDRH formats, so we do
752 not wish to include an immediate shift at this point. */
753 static void tcg_out_memop_r(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
754 TCGReg rn
, TCGReg rm
, bool u
, bool p
, bool w
)
756 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24)
757 | (w
<< 21) | (rn
<< 16) | (rt
<< 12) | rm
);
760 static void tcg_out_memop_8(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
761 TCGReg rn
, int imm8
, bool p
, bool w
)
768 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
769 (rn
<< 16) | (rt
<< 12) | ((imm8
& 0xf0) << 4) | (imm8
& 0xf));
772 static void tcg_out_memop_12(TCGContext
*s
, int cond
, ARMInsn opc
, TCGReg rt
,
773 TCGReg rn
, int imm12
, bool p
, bool w
)
780 tcg_out32(s
, (cond
<< 28) | opc
| (u
<< 23) | (p
<< 24) | (w
<< 21) |
781 (rn
<< 16) | (rt
<< 12) | imm12
);
784 static inline void tcg_out_ld32_12(TCGContext
*s
, int cond
, TCGReg rt
,
785 TCGReg rn
, int imm12
)
787 tcg_out_memop_12(s
, cond
, INSN_LDR_IMM
, rt
, rn
, imm12
, 1, 0);
790 static inline void tcg_out_st32_12(TCGContext
*s
, int cond
, TCGReg rt
,
791 TCGReg rn
, int imm12
)
793 tcg_out_memop_12(s
, cond
, INSN_STR_IMM
, rt
, rn
, imm12
, 1, 0);
796 static inline void tcg_out_ld32_r(TCGContext
*s
, int cond
, TCGReg rt
,
797 TCGReg rn
, TCGReg rm
)
799 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 0);
802 static inline void tcg_out_st32_r(TCGContext
*s
, int cond
, TCGReg rt
,
803 TCGReg rn
, TCGReg rm
)
805 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 0);
808 static inline void tcg_out_ldrd_8(TCGContext
*s
, int cond
, TCGReg rt
,
811 tcg_out_memop_8(s
, cond
, INSN_LDRD_IMM
, rt
, rn
, imm8
, 1, 0);
814 static inline void tcg_out_ldrd_r(TCGContext
*s
, int cond
, TCGReg rt
,
815 TCGReg rn
, TCGReg rm
)
817 tcg_out_memop_r(s
, cond
, INSN_LDRD_REG
, rt
, rn
, rm
, 1, 1, 0);
820 static inline void tcg_out_strd_8(TCGContext
*s
, int cond
, TCGReg rt
,
823 tcg_out_memop_8(s
, cond
, INSN_STRD_IMM
, rt
, rn
, imm8
, 1, 0);
826 static inline void tcg_out_strd_r(TCGContext
*s
, int cond
, TCGReg rt
,
827 TCGReg rn
, TCGReg rm
)
829 tcg_out_memop_r(s
, cond
, INSN_STRD_REG
, rt
, rn
, rm
, 1, 1, 0);
832 /* Register pre-increment with base writeback. */
833 static inline void tcg_out_ld32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
834 TCGReg rn
, TCGReg rm
)
836 tcg_out_memop_r(s
, cond
, INSN_LDR_REG
, rt
, rn
, rm
, 1, 1, 1);
839 static inline void tcg_out_st32_rwb(TCGContext
*s
, int cond
, TCGReg rt
,
840 TCGReg rn
, TCGReg rm
)
842 tcg_out_memop_r(s
, cond
, INSN_STR_REG
, rt
, rn
, rm
, 1, 1, 1);
845 static inline void tcg_out_ld16u_8(TCGContext
*s
, int cond
, TCGReg rt
,
848 tcg_out_memop_8(s
, cond
, INSN_LDRH_IMM
, rt
, rn
, imm8
, 1, 0);
851 static inline void tcg_out_st16_8(TCGContext
*s
, int cond
, TCGReg rt
,
854 tcg_out_memop_8(s
, cond
, INSN_STRH_IMM
, rt
, rn
, imm8
, 1, 0);
857 static inline void tcg_out_ld16u_r(TCGContext
*s
, int cond
, TCGReg rt
,
858 TCGReg rn
, TCGReg rm
)
860 tcg_out_memop_r(s
, cond
, INSN_LDRH_REG
, rt
, rn
, rm
, 1, 1, 0);
863 static inline void tcg_out_st16_r(TCGContext
*s
, int cond
, TCGReg rt
,
864 TCGReg rn
, TCGReg rm
)
866 tcg_out_memop_r(s
, cond
, INSN_STRH_REG
, rt
, rn
, rm
, 1, 1, 0);
869 static inline void tcg_out_ld16s_8(TCGContext
*s
, int cond
, TCGReg rt
,
872 tcg_out_memop_8(s
, cond
, INSN_LDRSH_IMM
, rt
, rn
, imm8
, 1, 0);
875 static inline void tcg_out_ld16s_r(TCGContext
*s
, int cond
, TCGReg rt
,
876 TCGReg rn
, TCGReg rm
)
878 tcg_out_memop_r(s
, cond
, INSN_LDRSH_REG
, rt
, rn
, rm
, 1, 1, 0);
881 static inline void tcg_out_ld8_12(TCGContext
*s
, int cond
, TCGReg rt
,
882 TCGReg rn
, int imm12
)
884 tcg_out_memop_12(s
, cond
, INSN_LDRB_IMM
, rt
, rn
, imm12
, 1, 0);
887 static inline void tcg_out_st8_12(TCGContext
*s
, int cond
, TCGReg rt
,
888 TCGReg rn
, int imm12
)
890 tcg_out_memop_12(s
, cond
, INSN_STRB_IMM
, rt
, rn
, imm12
, 1, 0);
893 static inline void tcg_out_ld8_r(TCGContext
*s
, int cond
, TCGReg rt
,
894 TCGReg rn
, TCGReg rm
)
896 tcg_out_memop_r(s
, cond
, INSN_LDRB_REG
, rt
, rn
, rm
, 1, 1, 0);
899 static inline void tcg_out_st8_r(TCGContext
*s
, int cond
, TCGReg rt
,
900 TCGReg rn
, TCGReg rm
)
902 tcg_out_memop_r(s
, cond
, INSN_STRB_REG
, rt
, rn
, rm
, 1, 1, 0);
905 static inline void tcg_out_ld8s_8(TCGContext
*s
, int cond
, TCGReg rt
,
908 tcg_out_memop_8(s
, cond
, INSN_LDRSB_IMM
, rt
, rn
, imm8
, 1, 0);
911 static inline void tcg_out_ld8s_r(TCGContext
*s
, int cond
, TCGReg rt
,
912 TCGReg rn
, TCGReg rm
)
914 tcg_out_memop_r(s
, cond
, INSN_LDRSB_REG
, rt
, rn
, rm
, 1, 1, 0);
917 static inline void tcg_out_ld32u(TCGContext
*s
, int cond
,
918 int rd
, int rn
, int32_t offset
)
920 if (offset
> 0xfff || offset
< -0xfff) {
921 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
922 tcg_out_ld32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
924 tcg_out_ld32_12(s
, cond
, rd
, rn
, offset
);
927 static inline void tcg_out_st32(TCGContext
*s
, int cond
,
928 int rd
, int rn
, int32_t offset
)
930 if (offset
> 0xfff || offset
< -0xfff) {
931 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
932 tcg_out_st32_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
934 tcg_out_st32_12(s
, cond
, rd
, rn
, offset
);
937 static inline void tcg_out_ld16u(TCGContext
*s
, int cond
,
938 int rd
, int rn
, int32_t offset
)
940 if (offset
> 0xff || offset
< -0xff) {
941 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
942 tcg_out_ld16u_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
944 tcg_out_ld16u_8(s
, cond
, rd
, rn
, offset
);
947 static inline void tcg_out_ld16s(TCGContext
*s
, int cond
,
948 int rd
, int rn
, int32_t offset
)
950 if (offset
> 0xff || offset
< -0xff) {
951 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
952 tcg_out_ld16s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
954 tcg_out_ld16s_8(s
, cond
, rd
, rn
, offset
);
957 static inline void tcg_out_st16(TCGContext
*s
, int cond
,
958 int rd
, int rn
, int32_t offset
)
960 if (offset
> 0xff || offset
< -0xff) {
961 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
962 tcg_out_st16_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
964 tcg_out_st16_8(s
, cond
, rd
, rn
, offset
);
967 static inline void tcg_out_ld8u(TCGContext
*s
, int cond
,
968 int rd
, int rn
, int32_t offset
)
970 if (offset
> 0xfff || offset
< -0xfff) {
971 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
972 tcg_out_ld8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
974 tcg_out_ld8_12(s
, cond
, rd
, rn
, offset
);
977 static inline void tcg_out_ld8s(TCGContext
*s
, int cond
,
978 int rd
, int rn
, int32_t offset
)
980 if (offset
> 0xff || offset
< -0xff) {
981 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
982 tcg_out_ld8s_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
984 tcg_out_ld8s_8(s
, cond
, rd
, rn
, offset
);
987 static inline void tcg_out_st8(TCGContext
*s
, int cond
,
988 int rd
, int rn
, int32_t offset
)
990 if (offset
> 0xfff || offset
< -0xfff) {
991 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, offset
);
992 tcg_out_st8_r(s
, cond
, rd
, rn
, TCG_REG_TMP
);
994 tcg_out_st8_12(s
, cond
, rd
, rn
, offset
);
997 /* The _goto case is normally between TBs within the same code buffer, and
998 * with the code buffer limited to 16MB we wouldn't need the long case.
999 * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
1001 static inline void tcg_out_goto(TCGContext
*s
, int cond
, tcg_insn_unit
*addr
)
1003 intptr_t addri
= (intptr_t)addr
;
1004 ptrdiff_t disp
= tcg_pcrel_diff(s
, addr
);
1006 if ((addri
& 1) == 0 && disp
- 8 < 0x01fffffd && disp
- 8 > -0x01fffffd) {
1007 tcg_out_b(s
, cond
, disp
);
1011 tcg_out_movi32(s
, cond
, TCG_REG_TMP
, addri
);
1012 if (use_armv5t_instructions
) {
1013 tcg_out_bx(s
, cond
, TCG_REG_TMP
);
1018 tcg_out_mov_reg(s
, cond
, TCG_REG_PC
, TCG_REG_TMP
);
1022 /* The call case is mostly used for helpers - so it's not unreasonable
1023 * for them to be beyond branch range */
1024 static void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*addr
)
1026 intptr_t addri
= (intptr_t)addr
;
1027 ptrdiff_t disp
= tcg_pcrel_diff(s
, addr
);
1029 if (disp
- 8 < 0x02000000 && disp
- 8 >= -0x02000000) {
1031 /* Use BLX if the target is in Thumb mode */
1032 if (!use_armv5t_instructions
) {
1035 tcg_out_blx_imm(s
, disp
);
1037 tcg_out_bl(s
, COND_AL
, disp
);
1039 } else if (use_armv7_instructions
) {
1040 tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, addri
);
1041 tcg_out_blx(s
, COND_AL
, TCG_REG_TMP
);
1043 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R14
, TCG_REG_PC
, 4);
1044 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_PC
, -4);
1045 tcg_out32(s
, addri
);
1049 void arm_tb_set_jmp_target(uintptr_t jmp_addr
, uintptr_t addr
)
1051 tcg_insn_unit
*code_ptr
= (tcg_insn_unit
*)jmp_addr
;
1052 tcg_insn_unit
*target
= (tcg_insn_unit
*)addr
;
1054 /* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
1055 reloc_pc24_atomic(code_ptr
, target
);
1056 flush_icache_range(jmp_addr
, jmp_addr
+ 4);
1059 static inline void tcg_out_goto_label(TCGContext
*s
, int cond
, TCGLabel
*l
)
1062 tcg_out_goto(s
, cond
, l
->u
.value_ptr
);
1064 tcg_out_reloc(s
, s
->code_ptr
, R_ARM_PC24
, l
, 0);
1065 tcg_out_b_noaddr(s
, cond
);
1069 #ifdef CONFIG_SOFTMMU
1070 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1071 * int mmu_idx, uintptr_t ra)
1073 static void * const qemu_ld_helpers
[16] = {
1074 [MO_UB
] = helper_ret_ldub_mmu
,
1075 [MO_SB
] = helper_ret_ldsb_mmu
,
1077 [MO_LEUW
] = helper_le_lduw_mmu
,
1078 [MO_LEUL
] = helper_le_ldul_mmu
,
1079 [MO_LEQ
] = helper_le_ldq_mmu
,
1080 [MO_LESW
] = helper_le_ldsw_mmu
,
1081 [MO_LESL
] = helper_le_ldul_mmu
,
1083 [MO_BEUW
] = helper_be_lduw_mmu
,
1084 [MO_BEUL
] = helper_be_ldul_mmu
,
1085 [MO_BEQ
] = helper_be_ldq_mmu
,
1086 [MO_BESW
] = helper_be_ldsw_mmu
,
1087 [MO_BESL
] = helper_be_ldul_mmu
,
1090 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1091 * uintxx_t val, int mmu_idx, uintptr_t ra)
1093 static void * const qemu_st_helpers
[16] = {
1094 [MO_UB
] = helper_ret_stb_mmu
,
1095 [MO_LEUW
] = helper_le_stw_mmu
,
1096 [MO_LEUL
] = helper_le_stl_mmu
,
1097 [MO_LEQ
] = helper_le_stq_mmu
,
1098 [MO_BEUW
] = helper_be_stw_mmu
,
1099 [MO_BEUL
] = helper_be_stl_mmu
,
1100 [MO_BEQ
] = helper_be_stq_mmu
,
1103 /* Helper routines for marshalling helper function arguments into
1104 * the correct registers and stack.
1105 * argreg is where we want to put this argument, arg is the argument itself.
1106 * Return value is the updated argreg ready for the next call.
1107 * Note that argreg 0..3 is real registers, 4+ on stack.
1109 * We provide routines for arguments which are: immediate, 32 bit
1110 * value in register, 16 and 8 bit values in register (which must be zero
1111 * extended before use) and 64 bit value in a lo:hi register pair.
1113 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1114 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1117 MOV_ARG(s, COND_AL, argreg, arg); \
1119 int ofs = (argreg - 4) * 4; \
1121 tcg_debug_assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1122 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1124 return argreg + 1; \
1127 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32
, uint32_t, tcg_out_movi32
,
1128 (tcg_out_movi32(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1129 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8
, TCGReg
, tcg_out_ext8u
,
1130 (tcg_out_ext8u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1131 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16
, TCGReg
, tcg_out_ext16u
,
1132 (tcg_out_ext16u(s
, COND_AL
, TCG_REG_TMP
, arg
), arg
= TCG_REG_TMP
))
1133 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32
, TCGReg
, tcg_out_mov_reg
, )
1135 static TCGReg
tcg_out_arg_reg64(TCGContext
*s
, TCGReg argreg
,
1136 TCGReg arglo
, TCGReg arghi
)
1138 /* 64 bit arguments must go in even/odd register pairs
1139 * and in 8-aligned stack slots.
1144 if (use_armv6_instructions
&& argreg
>= 4
1145 && (arglo
& 1) == 0 && arghi
== arglo
+ 1) {
1146 tcg_out_strd_8(s
, COND_AL
, arglo
,
1147 TCG_REG_CALL_STACK
, (argreg
- 4) * 4);
1150 argreg
= tcg_out_arg_reg32(s
, argreg
, arglo
);
1151 argreg
= tcg_out_arg_reg32(s
, argreg
, arghi
);
1156 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1158 /* We're expecting to use an 8-bit immediate and to mask. */
1159 QEMU_BUILD_BUG_ON(CPU_TLB_BITS
> 8);
1161 /* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset.
1162 Using the offset of the second entry in the last tlb table ensures
1163 that we can index all of the elements of the first entry. */
1164 QEMU_BUILD_BUG_ON(offsetof(CPUArchState
, tlb_table
[NB_MMU_MODES
- 1][1])
1167 /* Load and compare a TLB entry, leaving the flags set. Returns the register
1168 containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
1170 static TCGReg
tcg_out_tlb_read(TCGContext
*s
, TCGReg addrlo
, TCGReg addrhi
,
1171 TCGMemOp s_bits
, int mem_index
, bool is_load
)
1173 TCGReg base
= TCG_AREG0
;
1176 ? offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1177 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
));
1178 int add_off
= offsetof(CPUArchState
, tlb_table
[mem_index
][0].addend
);
1180 /* Should generate something like the following:
1181 * shr tmp, addrlo, #TARGET_PAGE_BITS (1)
1182 * add r2, env, #high
1183 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1184 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1185 * ldr r0, [r2, #cmp] (4)
1186 * tst addrlo, #s_mask
1187 * ldr r2, [r2, #add] (5)
1188 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS
1190 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, TCG_REG_TMP
,
1191 0, addrlo
, SHIFT_IMM_LSR(TARGET_PAGE_BITS
));
1193 /* We checked that the offset is contained within 16 bits above. */
1194 if (add_off
> 0xfff || (use_armv6_instructions
&& cmp_off
> 0xff)) {
1195 tcg_out_dat_imm(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1196 (24 << 7) | (cmp_off
>> 8));
1198 add_off
-= cmp_off
& 0xff00;
1202 tcg_out_dat_imm(s
, COND_AL
, ARITH_AND
,
1203 TCG_REG_R0
, TCG_REG_TMP
, CPU_TLB_SIZE
- 1);
1204 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_R2
, base
,
1205 TCG_REG_R0
, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS
));
1207 /* Load the tlb comparator. Use ldrd if needed and available,
1208 but due to how the pointer needs setting up, ldm isn't useful.
1209 Base arm5 doesn't have ldrd, but armv5te does. */
1210 if (use_armv6_instructions
&& TARGET_LONG_BITS
== 64) {
1211 tcg_out_ldrd_8(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R2
, cmp_off
);
1213 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R0
, TCG_REG_R2
, cmp_off
);
1214 if (TARGET_LONG_BITS
== 64) {
1215 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R1
, TCG_REG_R2
, cmp_off
+ 4);
1219 /* Check alignment. */
1221 tcg_out_dat_imm(s
, COND_AL
, ARITH_TST
,
1222 0, addrlo
, (1 << s_bits
) - 1);
1225 /* Load the tlb addend. */
1226 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_R2
, TCG_REG_R2
, add_off
);
1228 tcg_out_dat_reg(s
, (s_bits
? COND_EQ
: COND_AL
), ARITH_CMP
, 0,
1229 TCG_REG_R0
, TCG_REG_TMP
, SHIFT_IMM_LSL(TARGET_PAGE_BITS
));
1231 if (TARGET_LONG_BITS
== 64) {
1232 tcg_out_dat_reg(s
, COND_EQ
, ARITH_CMP
, 0,
1233 TCG_REG_R1
, addrhi
, SHIFT_IMM_LSL(0));
1239 /* Record the context of a call to the out of line helper code for the slow
1240 path for a load or store, so that we can later generate the correct
1242 static void add_qemu_ldst_label(TCGContext
*s
, bool is_ld
, TCGMemOpIdx oi
,
1243 TCGReg datalo
, TCGReg datahi
, TCGReg addrlo
,
1244 TCGReg addrhi
, tcg_insn_unit
*raddr
,
1245 tcg_insn_unit
*label_ptr
)
1247 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1249 label
->is_ld
= is_ld
;
1251 label
->datalo_reg
= datalo
;
1252 label
->datahi_reg
= datahi
;
1253 label
->addrlo_reg
= addrlo
;
1254 label
->addrhi_reg
= addrhi
;
1255 label
->raddr
= raddr
;
1256 label
->label_ptr
[0] = label_ptr
;
1259 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1261 TCGReg argreg
, datalo
, datahi
;
1262 TCGMemOpIdx oi
= lb
->oi
;
1263 TCGMemOp opc
= get_memop(oi
);
1266 reloc_pc24(lb
->label_ptr
[0], s
->code_ptr
);
1268 argreg
= tcg_out_arg_reg32(s
, TCG_REG_R0
, TCG_AREG0
);
1269 if (TARGET_LONG_BITS
== 64) {
1270 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1272 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1274 argreg
= tcg_out_arg_imm32(s
, argreg
, oi
);
1275 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_REG_R14
);
1277 /* For armv6 we can use the canonical unsigned helpers and minimize
1278 icache usage. For pre-armv6, use the signed helpers since we do
1279 not have a single insn sign-extend. */
1280 if (use_armv6_instructions
) {
1281 func
= qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)];
1283 func
= qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SSIZE
)];
1284 if (opc
& MO_SIGN
) {
1288 tcg_out_call(s
, func
);
1290 datalo
= lb
->datalo_reg
;
1291 datahi
= lb
->datahi_reg
;
1292 switch (opc
& MO_SSIZE
) {
1294 tcg_out_ext8s(s
, COND_AL
, datalo
, TCG_REG_R0
);
1297 tcg_out_ext16s(s
, COND_AL
, datalo
, TCG_REG_R0
);
1300 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1303 if (datalo
!= TCG_REG_R1
) {
1304 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1305 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1306 } else if (datahi
!= TCG_REG_R0
) {
1307 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1308 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_R0
);
1310 tcg_out_mov_reg(s
, COND_AL
, TCG_REG_TMP
, TCG_REG_R0
);
1311 tcg_out_mov_reg(s
, COND_AL
, datahi
, TCG_REG_R1
);
1312 tcg_out_mov_reg(s
, COND_AL
, datalo
, TCG_REG_TMP
);
1317 tcg_out_goto(s
, COND_AL
, lb
->raddr
);
1320 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1322 TCGReg argreg
, datalo
, datahi
;
1323 TCGMemOpIdx oi
= lb
->oi
;
1324 TCGMemOp opc
= get_memop(oi
);
1326 reloc_pc24(lb
->label_ptr
[0], s
->code_ptr
);
1328 argreg
= TCG_REG_R0
;
1329 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_AREG0
);
1330 if (TARGET_LONG_BITS
== 64) {
1331 argreg
= tcg_out_arg_reg64(s
, argreg
, lb
->addrlo_reg
, lb
->addrhi_reg
);
1333 argreg
= tcg_out_arg_reg32(s
, argreg
, lb
->addrlo_reg
);
1336 datalo
= lb
->datalo_reg
;
1337 datahi
= lb
->datahi_reg
;
1338 switch (opc
& MO_SIZE
) {
1340 argreg
= tcg_out_arg_reg8(s
, argreg
, datalo
);
1343 argreg
= tcg_out_arg_reg16(s
, argreg
, datalo
);
1347 argreg
= tcg_out_arg_reg32(s
, argreg
, datalo
);
1350 argreg
= tcg_out_arg_reg64(s
, argreg
, datalo
, datahi
);
1354 argreg
= tcg_out_arg_imm32(s
, argreg
, oi
);
1355 argreg
= tcg_out_arg_reg32(s
, argreg
, TCG_REG_R14
);
1357 /* Tail-call to the helper, which will return to the fast path. */
1358 tcg_out_goto(s
, COND_AL
, qemu_st_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)]);
1360 #endif /* SOFTMMU */
1362 static inline void tcg_out_qemu_ld_index(TCGContext
*s
, TCGMemOp opc
,
1363 TCGReg datalo
, TCGReg datahi
,
1364 TCGReg addrlo
, TCGReg addend
)
1366 TCGMemOp bswap
= opc
& MO_BSWAP
;
1368 switch (opc
& MO_SSIZE
) {
1370 tcg_out_ld8_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1373 tcg_out_ld8s_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1376 tcg_out_ld16u_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1378 tcg_out_bswap16(s
, COND_AL
, datalo
, datalo
);
1383 tcg_out_ld16u_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1384 tcg_out_bswap16s(s
, COND_AL
, datalo
, datalo
);
1386 tcg_out_ld16s_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1391 tcg_out_ld32_r(s
, COND_AL
, datalo
, addrlo
, addend
);
1393 tcg_out_bswap32(s
, COND_AL
, datalo
, datalo
);
1398 TCGReg dl
= (bswap
? datahi
: datalo
);
1399 TCGReg dh
= (bswap
? datalo
: datahi
);
1401 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1402 if (USING_SOFTMMU
&& use_armv6_instructions
1403 && (dl
& 1) == 0 && dh
== dl
+ 1) {
1404 tcg_out_ldrd_r(s
, COND_AL
, dl
, addrlo
, addend
);
1405 } else if (dl
!= addend
) {
1406 tcg_out_ld32_rwb(s
, COND_AL
, dl
, addend
, addrlo
);
1407 tcg_out_ld32_12(s
, COND_AL
, dh
, addend
, 4);
1409 tcg_out_dat_reg(s
, COND_AL
, ARITH_ADD
, TCG_REG_TMP
,
1410 addend
, addrlo
, SHIFT_IMM_LSL(0));
1411 tcg_out_ld32_12(s
, COND_AL
, dl
, TCG_REG_TMP
, 0);
1412 tcg_out_ld32_12(s
, COND_AL
, dh
, TCG_REG_TMP
, 4);
1415 tcg_out_bswap32(s
, COND_AL
, dl
, dl
);
1416 tcg_out_bswap32(s
, COND_AL
, dh
, dh
);
1423 static inline void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGMemOp opc
,
1424 TCGReg datalo
, TCGReg datahi
,
1427 TCGMemOp bswap
= opc
& MO_BSWAP
;
1429 switch (opc
& MO_SSIZE
) {
1431 tcg_out_ld8_12(s
, COND_AL
, datalo
, addrlo
, 0);
1434 tcg_out_ld8s_8(s
, COND_AL
, datalo
, addrlo
, 0);
1437 tcg_out_ld16u_8(s
, COND_AL
, datalo
, addrlo
, 0);
1439 tcg_out_bswap16(s
, COND_AL
, datalo
, datalo
);
1444 tcg_out_ld16u_8(s
, COND_AL
, datalo
, addrlo
, 0);
1445 tcg_out_bswap16s(s
, COND_AL
, datalo
, datalo
);
1447 tcg_out_ld16s_8(s
, COND_AL
, datalo
, addrlo
, 0);
1452 tcg_out_ld32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1454 tcg_out_bswap32(s
, COND_AL
, datalo
, datalo
);
1459 TCGReg dl
= (bswap
? datahi
: datalo
);
1460 TCGReg dh
= (bswap
? datalo
: datahi
);
1462 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1463 if (USING_SOFTMMU
&& use_armv6_instructions
1464 && (dl
& 1) == 0 && dh
== dl
+ 1) {
1465 tcg_out_ldrd_8(s
, COND_AL
, dl
, addrlo
, 0);
1466 } else if (dl
== addrlo
) {
1467 tcg_out_ld32_12(s
, COND_AL
, dh
, addrlo
, bswap
? 0 : 4);
1468 tcg_out_ld32_12(s
, COND_AL
, dl
, addrlo
, bswap
? 4 : 0);
1470 tcg_out_ld32_12(s
, COND_AL
, dl
, addrlo
, bswap
? 4 : 0);
1471 tcg_out_ld32_12(s
, COND_AL
, dh
, addrlo
, bswap
? 0 : 4);
1474 tcg_out_bswap32(s
, COND_AL
, dl
, dl
);
1475 tcg_out_bswap32(s
, COND_AL
, dh
, dh
);
1482 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, bool is64
)
1484 TCGReg addrlo
, datalo
, datahi
, addrhi
__attribute__((unused
));
1487 #ifdef CONFIG_SOFTMMU
1490 tcg_insn_unit
*label_ptr
;
1494 datahi
= (is64
? *args
++ : 0);
1496 addrhi
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1498 opc
= get_memop(oi
);
1500 #ifdef CONFIG_SOFTMMU
1501 mem_index
= get_mmuidx(oi
);
1502 addend
= tcg_out_tlb_read(s
, addrlo
, addrhi
, opc
& MO_SIZE
, mem_index
, 1);
1504 /* This a conditional BL only to load a pointer within this opcode into LR
1505 for the slow path. We will not be using the value for a tail call. */
1506 label_ptr
= s
->code_ptr
;
1507 tcg_out_bl_noaddr(s
, COND_NE
);
1509 tcg_out_qemu_ld_index(s
, opc
, datalo
, datahi
, addrlo
, addend
);
1511 add_qemu_ldst_label(s
, true, oi
, datalo
, datahi
, addrlo
, addrhi
,
1512 s
->code_ptr
, label_ptr
);
1513 #else /* !CONFIG_SOFTMMU */
1515 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_TMP
, guest_base
);
1516 tcg_out_qemu_ld_index(s
, opc
, datalo
, datahi
, addrlo
, TCG_REG_TMP
);
1518 tcg_out_qemu_ld_direct(s
, opc
, datalo
, datahi
, addrlo
);
1523 static inline void tcg_out_qemu_st_index(TCGContext
*s
, int cond
, TCGMemOp opc
,
1524 TCGReg datalo
, TCGReg datahi
,
1525 TCGReg addrlo
, TCGReg addend
)
1527 TCGMemOp bswap
= opc
& MO_BSWAP
;
1529 switch (opc
& MO_SIZE
) {
1531 tcg_out_st8_r(s
, cond
, datalo
, addrlo
, addend
);
1535 tcg_out_bswap16st(s
, cond
, TCG_REG_R0
, datalo
);
1536 tcg_out_st16_r(s
, cond
, TCG_REG_R0
, addrlo
, addend
);
1538 tcg_out_st16_r(s
, cond
, datalo
, addrlo
, addend
);
1544 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datalo
);
1545 tcg_out_st32_r(s
, cond
, TCG_REG_R0
, addrlo
, addend
);
1547 tcg_out_st32_r(s
, cond
, datalo
, addrlo
, addend
);
1551 /* Avoid strd for user-only emulation, to handle unaligned. */
1553 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datahi
);
1554 tcg_out_st32_rwb(s
, cond
, TCG_REG_R0
, addend
, addrlo
);
1555 tcg_out_bswap32(s
, cond
, TCG_REG_R0
, datalo
);
1556 tcg_out_st32_12(s
, cond
, TCG_REG_R0
, addend
, 4);
1557 } else if (USING_SOFTMMU
&& use_armv6_instructions
1558 && (datalo
& 1) == 0 && datahi
== datalo
+ 1) {
1559 tcg_out_strd_r(s
, cond
, datalo
, addrlo
, addend
);
1561 tcg_out_st32_rwb(s
, cond
, datalo
, addend
, addrlo
);
1562 tcg_out_st32_12(s
, cond
, datahi
, addend
, 4);
1568 static inline void tcg_out_qemu_st_direct(TCGContext
*s
, TCGMemOp opc
,
1569 TCGReg datalo
, TCGReg datahi
,
1572 TCGMemOp bswap
= opc
& MO_BSWAP
;
1574 switch (opc
& MO_SIZE
) {
1576 tcg_out_st8_12(s
, COND_AL
, datalo
, addrlo
, 0);
1580 tcg_out_bswap16st(s
, COND_AL
, TCG_REG_R0
, datalo
);
1581 tcg_out_st16_8(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1583 tcg_out_st16_8(s
, COND_AL
, datalo
, addrlo
, 0);
1589 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datalo
);
1590 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1592 tcg_out_st32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1596 /* Avoid strd for user-only emulation, to handle unaligned. */
1598 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datahi
);
1599 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 0);
1600 tcg_out_bswap32(s
, COND_AL
, TCG_REG_R0
, datalo
);
1601 tcg_out_st32_12(s
, COND_AL
, TCG_REG_R0
, addrlo
, 4);
1602 } else if (USING_SOFTMMU
&& use_armv6_instructions
1603 && (datalo
& 1) == 0 && datahi
== datalo
+ 1) {
1604 tcg_out_strd_8(s
, COND_AL
, datalo
, addrlo
, 0);
1606 tcg_out_st32_12(s
, COND_AL
, datalo
, addrlo
, 0);
1607 tcg_out_st32_12(s
, COND_AL
, datahi
, addrlo
, 4);
1613 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, bool is64
)
1615 TCGReg addrlo
, datalo
, datahi
, addrhi
__attribute__((unused
));
1618 #ifdef CONFIG_SOFTMMU
1621 tcg_insn_unit
*label_ptr
;
1625 datahi
= (is64
? *args
++ : 0);
1627 addrhi
= (TARGET_LONG_BITS
== 64 ? *args
++ : 0);
1629 opc
= get_memop(oi
);
1631 #ifdef CONFIG_SOFTMMU
1632 mem_index
= get_mmuidx(oi
);
1633 addend
= tcg_out_tlb_read(s
, addrlo
, addrhi
, opc
& MO_SIZE
, mem_index
, 0);
1635 tcg_out_qemu_st_index(s
, COND_EQ
, opc
, datalo
, datahi
, addrlo
, addend
);
1637 /* The conditional call must come last, as we're going to return here. */
1638 label_ptr
= s
->code_ptr
;
1639 tcg_out_bl_noaddr(s
, COND_NE
);
1641 add_qemu_ldst_label(s
, false, oi
, datalo
, datahi
, addrlo
, addrhi
,
1642 s
->code_ptr
, label_ptr
);
1643 #else /* !CONFIG_SOFTMMU */
1645 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_TMP
, guest_base
);
1646 tcg_out_qemu_st_index(s
, COND_AL
, opc
, datalo
,
1647 datahi
, addrlo
, TCG_REG_TMP
);
1649 tcg_out_qemu_st_direct(s
, opc
, datalo
, datahi
, addrlo
);
1654 static tcg_insn_unit
*tb_ret_addr
;
1656 static inline void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1657 const TCGArg
*args
, const int *const_args
)
1659 TCGArg a0
, a1
, a2
, a3
, a4
, a5
;
1663 case INDEX_op_exit_tb
:
1664 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
, args
[0]);
1665 tcg_out_goto(s
, COND_AL
, tb_ret_addr
);
1667 case INDEX_op_goto_tb
:
1668 if (s
->tb_jmp_insn_offset
) {
1669 /* Direct jump method */
1670 s
->tb_jmp_insn_offset
[args
[0]] = tcg_current_code_size(s
);
1671 tcg_out_b_noaddr(s
, COND_AL
);
1673 /* Indirect jump method */
1674 intptr_t ptr
= (intptr_t)(s
->tb_jmp_target_addr
+ args
[0]);
1675 tcg_out_movi32(s
, COND_AL
, TCG_REG_R0
, ptr
& ~0xfff);
1676 tcg_out_ld32_12(s
, COND_AL
, TCG_REG_PC
, TCG_REG_R0
, ptr
& 0xfff);
1678 s
->tb_jmp_reset_offset
[args
[0]] = tcg_current_code_size(s
);
1681 tcg_out_goto_label(s
, COND_AL
, arg_label(args
[0]));
1684 case INDEX_op_ld8u_i32
:
1685 tcg_out_ld8u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1687 case INDEX_op_ld8s_i32
:
1688 tcg_out_ld8s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1690 case INDEX_op_ld16u_i32
:
1691 tcg_out_ld16u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1693 case INDEX_op_ld16s_i32
:
1694 tcg_out_ld16s(s
, COND_AL
, args
[0], args
[1], args
[2]);
1696 case INDEX_op_ld_i32
:
1697 tcg_out_ld32u(s
, COND_AL
, args
[0], args
[1], args
[2]);
1699 case INDEX_op_st8_i32
:
1700 tcg_out_st8(s
, COND_AL
, args
[0], args
[1], args
[2]);
1702 case INDEX_op_st16_i32
:
1703 tcg_out_st16(s
, COND_AL
, args
[0], args
[1], args
[2]);
1705 case INDEX_op_st_i32
:
1706 tcg_out_st32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1709 case INDEX_op_movcond_i32
:
1710 /* Constraints mean that v2 is always in the same register as dest,
1711 * so we only need to do "if condition passed, move v1 to dest".
1713 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1714 args
[1], args
[2], const_args
[2]);
1715 tcg_out_dat_rIK(s
, tcg_cond_to_arm_cond
[args
[5]], ARITH_MOV
,
1716 ARITH_MVN
, args
[0], 0, args
[3], const_args
[3]);
1718 case INDEX_op_add_i32
:
1719 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
, ARITH_SUB
,
1720 args
[0], args
[1], args
[2], const_args
[2]);
1722 case INDEX_op_sub_i32
:
1723 if (const_args
[1]) {
1724 if (const_args
[2]) {
1725 tcg_out_movi32(s
, COND_AL
, args
[0], args
[1] - args
[2]);
1727 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
,
1728 args
[0], args
[2], args
[1], 1);
1731 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
, ARITH_ADD
,
1732 args
[0], args
[1], args
[2], const_args
[2]);
1735 case INDEX_op_and_i32
:
1736 tcg_out_dat_rIK(s
, COND_AL
, ARITH_AND
, ARITH_BIC
,
1737 args
[0], args
[1], args
[2], const_args
[2]);
1739 case INDEX_op_andc_i32
:
1740 tcg_out_dat_rIK(s
, COND_AL
, ARITH_BIC
, ARITH_AND
,
1741 args
[0], args
[1], args
[2], const_args
[2]);
1743 case INDEX_op_or_i32
:
1746 case INDEX_op_xor_i32
:
1750 tcg_out_dat_rI(s
, COND_AL
, c
, args
[0], args
[1], args
[2], const_args
[2]);
1752 case INDEX_op_add2_i32
:
1753 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1754 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1755 if (a0
== a3
|| (a0
== a5
&& !const_args
[5])) {
1758 tcg_out_dat_rIN(s
, COND_AL
, ARITH_ADD
| TO_CPSR
, ARITH_SUB
| TO_CPSR
,
1759 a0
, a2
, a4
, const_args
[4]);
1760 tcg_out_dat_rIK(s
, COND_AL
, ARITH_ADC
, ARITH_SBC
,
1761 a1
, a3
, a5
, const_args
[5]);
1762 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1764 case INDEX_op_sub2_i32
:
1765 a0
= args
[0], a1
= args
[1], a2
= args
[2];
1766 a3
= args
[3], a4
= args
[4], a5
= args
[5];
1767 if ((a0
== a3
&& !const_args
[3]) || (a0
== a5
&& !const_args
[5])) {
1770 if (const_args
[2]) {
1771 if (const_args
[4]) {
1772 tcg_out_movi32(s
, COND_AL
, a0
, a4
);
1775 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSB
| TO_CPSR
, a0
, a4
, a2
, 1);
1777 tcg_out_dat_rIN(s
, COND_AL
, ARITH_SUB
| TO_CPSR
,
1778 ARITH_ADD
| TO_CPSR
, a0
, a2
, a4
, const_args
[4]);
1780 if (const_args
[3]) {
1781 if (const_args
[5]) {
1782 tcg_out_movi32(s
, COND_AL
, a1
, a5
);
1785 tcg_out_dat_rI(s
, COND_AL
, ARITH_RSC
, a1
, a5
, a3
, 1);
1787 tcg_out_dat_rIK(s
, COND_AL
, ARITH_SBC
, ARITH_ADC
,
1788 a1
, a3
, a5
, const_args
[5]);
1790 tcg_out_mov_reg(s
, COND_AL
, args
[0], a0
);
1792 case INDEX_op_neg_i32
:
1793 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, args
[0], args
[1], 0);
1795 case INDEX_op_not_i32
:
1796 tcg_out_dat_reg(s
, COND_AL
,
1797 ARITH_MVN
, args
[0], 0, args
[1], SHIFT_IMM_LSL(0));
1799 case INDEX_op_mul_i32
:
1800 tcg_out_mul32(s
, COND_AL
, args
[0], args
[1], args
[2]);
1802 case INDEX_op_mulu2_i32
:
1803 tcg_out_umull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1805 case INDEX_op_muls2_i32
:
1806 tcg_out_smull32(s
, COND_AL
, args
[0], args
[1], args
[2], args
[3]);
1808 /* XXX: Perhaps args[2] & 0x1f is wrong */
1809 case INDEX_op_shl_i32
:
1811 SHIFT_IMM_LSL(args
[2] & 0x1f) : SHIFT_REG_LSL(args
[2]);
1813 case INDEX_op_shr_i32
:
1814 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_LSR(args
[2] & 0x1f) :
1815 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args
[2]);
1817 case INDEX_op_sar_i32
:
1818 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ASR(args
[2] & 0x1f) :
1819 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args
[2]);
1821 case INDEX_op_rotr_i32
:
1822 c
= const_args
[2] ? (args
[2] & 0x1f) ? SHIFT_IMM_ROR(args
[2] & 0x1f) :
1823 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args
[2]);
1826 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1], c
);
1829 case INDEX_op_rotl_i32
:
1830 if (const_args
[2]) {
1831 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1832 ((0x20 - args
[2]) & 0x1f) ?
1833 SHIFT_IMM_ROR((0x20 - args
[2]) & 0x1f) :
1836 tcg_out_dat_imm(s
, COND_AL
, ARITH_RSB
, TCG_REG_TMP
, args
[2], 0x20);
1837 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, args
[0], 0, args
[1],
1838 SHIFT_REG_ROR(TCG_REG_TMP
));
1842 case INDEX_op_brcond_i32
:
1843 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1844 args
[0], args
[1], const_args
[1]);
1845 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[2]],
1846 arg_label(args
[3]));
1848 case INDEX_op_brcond2_i32
:
1849 /* The resulting conditions are:
1850 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1851 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1852 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1853 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1854 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1855 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1857 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1858 args
[1], args
[3], const_args
[3]);
1859 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1860 args
[0], args
[2], const_args
[2]);
1861 tcg_out_goto_label(s
, tcg_cond_to_arm_cond
[args
[4]],
1862 arg_label(args
[5]));
1864 case INDEX_op_setcond_i32
:
1865 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1866 args
[1], args
[2], const_args
[2]);
1867 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[3]],
1868 ARITH_MOV
, args
[0], 0, 1);
1869 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[3])],
1870 ARITH_MOV
, args
[0], 0, 0);
1872 case INDEX_op_setcond2_i32
:
1873 /* See brcond2_i32 comment */
1874 tcg_out_dat_rIN(s
, COND_AL
, ARITH_CMP
, ARITH_CMN
, 0,
1875 args
[2], args
[4], const_args
[4]);
1876 tcg_out_dat_rIN(s
, COND_EQ
, ARITH_CMP
, ARITH_CMN
, 0,
1877 args
[1], args
[3], const_args
[3]);
1878 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[args
[5]],
1879 ARITH_MOV
, args
[0], 0, 1);
1880 tcg_out_dat_imm(s
, tcg_cond_to_arm_cond
[tcg_invert_cond(args
[5])],
1881 ARITH_MOV
, args
[0], 0, 0);
1884 case INDEX_op_qemu_ld_i32
:
1885 tcg_out_qemu_ld(s
, args
, 0);
1887 case INDEX_op_qemu_ld_i64
:
1888 tcg_out_qemu_ld(s
, args
, 1);
1890 case INDEX_op_qemu_st_i32
:
1891 tcg_out_qemu_st(s
, args
, 0);
1893 case INDEX_op_qemu_st_i64
:
1894 tcg_out_qemu_st(s
, args
, 1);
1897 case INDEX_op_bswap16_i32
:
1898 tcg_out_bswap16(s
, COND_AL
, args
[0], args
[1]);
1900 case INDEX_op_bswap32_i32
:
1901 tcg_out_bswap32(s
, COND_AL
, args
[0], args
[1]);
1904 case INDEX_op_ext8s_i32
:
1905 tcg_out_ext8s(s
, COND_AL
, args
[0], args
[1]);
1907 case INDEX_op_ext16s_i32
:
1908 tcg_out_ext16s(s
, COND_AL
, args
[0], args
[1]);
1910 case INDEX_op_ext16u_i32
:
1911 tcg_out_ext16u(s
, COND_AL
, args
[0], args
[1]);
1914 case INDEX_op_deposit_i32
:
1915 tcg_out_deposit(s
, COND_AL
, args
[0], args
[2],
1916 args
[3], args
[4], const_args
[2]);
1919 case INDEX_op_div_i32
:
1920 tcg_out_sdiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
1922 case INDEX_op_divu_i32
:
1923 tcg_out_udiv(s
, COND_AL
, args
[0], args
[1], args
[2]);
1926 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
1927 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
1928 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
1934 static const TCGTargetOpDef arm_op_defs
[] = {
1935 { INDEX_op_exit_tb
, { } },
1936 { INDEX_op_goto_tb
, { } },
1937 { INDEX_op_br
, { } },
1939 { INDEX_op_ld8u_i32
, { "r", "r" } },
1940 { INDEX_op_ld8s_i32
, { "r", "r" } },
1941 { INDEX_op_ld16u_i32
, { "r", "r" } },
1942 { INDEX_op_ld16s_i32
, { "r", "r" } },
1943 { INDEX_op_ld_i32
, { "r", "r" } },
1944 { INDEX_op_st8_i32
, { "r", "r" } },
1945 { INDEX_op_st16_i32
, { "r", "r" } },
1946 { INDEX_op_st_i32
, { "r", "r" } },
1948 /* TODO: "r", "r", "ri" */
1949 { INDEX_op_add_i32
, { "r", "r", "rIN" } },
1950 { INDEX_op_sub_i32
, { "r", "rI", "rIN" } },
1951 { INDEX_op_mul_i32
, { "r", "r", "r" } },
1952 { INDEX_op_mulu2_i32
, { "r", "r", "r", "r" } },
1953 { INDEX_op_muls2_i32
, { "r", "r", "r", "r" } },
1954 { INDEX_op_and_i32
, { "r", "r", "rIK" } },
1955 { INDEX_op_andc_i32
, { "r", "r", "rIK" } },
1956 { INDEX_op_or_i32
, { "r", "r", "rI" } },
1957 { INDEX_op_xor_i32
, { "r", "r", "rI" } },
1958 { INDEX_op_neg_i32
, { "r", "r" } },
1959 { INDEX_op_not_i32
, { "r", "r" } },
1961 { INDEX_op_shl_i32
, { "r", "r", "ri" } },
1962 { INDEX_op_shr_i32
, { "r", "r", "ri" } },
1963 { INDEX_op_sar_i32
, { "r", "r", "ri" } },
1964 { INDEX_op_rotl_i32
, { "r", "r", "ri" } },
1965 { INDEX_op_rotr_i32
, { "r", "r", "ri" } },
1967 { INDEX_op_brcond_i32
, { "r", "rIN" } },
1968 { INDEX_op_setcond_i32
, { "r", "r", "rIN" } },
1969 { INDEX_op_movcond_i32
, { "r", "r", "rIN", "rIK", "0" } },
1971 { INDEX_op_add2_i32
, { "r", "r", "r", "r", "rIN", "rIK" } },
1972 { INDEX_op_sub2_i32
, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1973 { INDEX_op_brcond2_i32
, { "r", "r", "rIN", "rIN" } },
1974 { INDEX_op_setcond2_i32
, { "r", "r", "r", "rIN", "rIN" } },
1976 #if TARGET_LONG_BITS == 32
1977 { INDEX_op_qemu_ld_i32
, { "r", "l" } },
1978 { INDEX_op_qemu_ld_i64
, { "r", "r", "l" } },
1979 { INDEX_op_qemu_st_i32
, { "s", "s" } },
1980 { INDEX_op_qemu_st_i64
, { "s", "s", "s" } },
1982 { INDEX_op_qemu_ld_i32
, { "r", "l", "l" } },
1983 { INDEX_op_qemu_ld_i64
, { "r", "r", "l", "l" } },
1984 { INDEX_op_qemu_st_i32
, { "s", "s", "s" } },
1985 { INDEX_op_qemu_st_i64
, { "s", "s", "s", "s" } },
1988 { INDEX_op_bswap16_i32
, { "r", "r" } },
1989 { INDEX_op_bswap32_i32
, { "r", "r" } },
1991 { INDEX_op_ext8s_i32
, { "r", "r" } },
1992 { INDEX_op_ext16s_i32
, { "r", "r" } },
1993 { INDEX_op_ext16u_i32
, { "r", "r" } },
1995 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
1997 { INDEX_op_div_i32
, { "r", "r", "r" } },
1998 { INDEX_op_divu_i32
, { "r", "r", "r" } },
2003 static void tcg_target_init(TCGContext
*s
)
2005 /* Only probe for the platform and capabilities if we havn't already
2006 determined maximum values at compile time. */
2007 #ifndef use_idiv_instructions
2009 unsigned long hwcap
= qemu_getauxval(AT_HWCAP
);
2010 use_idiv_instructions
= (hwcap
& HWCAP_ARM_IDIVA
) != 0;
2013 if (__ARM_ARCH
< 7) {
2014 const char *pl
= (const char *)qemu_getauxval(AT_PLATFORM
);
2015 if (pl
!= NULL
&& pl
[0] == 'v' && pl
[1] >= '4' && pl
[1] <= '9') {
2016 arm_arch
= pl
[1] - '0';
2020 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I32
], 0, 0xffff);
2021 tcg_regset_set32(tcg_target_call_clobber_regs
, 0,
2026 (1 << TCG_REG_R12
) |
2027 (1 << TCG_REG_R14
));
2029 tcg_regset_clear(s
->reserved_regs
);
2030 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_CALL_STACK
);
2031 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_TMP
);
2032 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_PC
);
2034 tcg_add_target_add_op_defs(arm_op_defs
);
2037 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
2038 TCGReg arg1
, intptr_t arg2
)
2040 tcg_out_ld32u(s
, COND_AL
, arg
, arg1
, arg2
);
2043 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
2044 TCGReg arg1
, intptr_t arg2
)
2046 tcg_out_st32(s
, COND_AL
, arg
, arg1
, arg2
);
2049 static inline void tcg_out_mov(TCGContext
*s
, TCGType type
,
2050 TCGReg ret
, TCGReg arg
)
2052 tcg_out_dat_reg(s
, COND_AL
, ARITH_MOV
, ret
, 0, arg
, SHIFT_IMM_LSL(0));
2055 static inline void tcg_out_movi(TCGContext
*s
, TCGType type
,
2056 TCGReg ret
, tcg_target_long arg
)
2058 tcg_out_movi32(s
, COND_AL
, ret
, arg
);
2061 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2062 and tcg_register_jit. */
2064 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2066 #define FRAME_SIZE \
2068 + TCG_STATIC_CALL_ARGS_SIZE \
2069 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2070 + TCG_TARGET_STACK_ALIGN - 1) \
2071 & -TCG_TARGET_STACK_ALIGN)
2073 static void tcg_target_qemu_prologue(TCGContext
*s
)
2077 /* Calling convention requires us to save r4-r11 and lr. */
2078 /* stmdb sp!, { r4 - r11, lr } */
2079 tcg_out32(s
, (COND_AL
<< 28) | 0x092d4ff0);
2081 /* Reserve callee argument and tcg temp space. */
2082 stack_addend
= FRAME_SIZE
- PUSH_SIZE
;
2084 tcg_out_dat_rI(s
, COND_AL
, ARITH_SUB
, TCG_REG_CALL_STACK
,
2085 TCG_REG_CALL_STACK
, stack_addend
, 1);
2086 tcg_set_frame(s
, TCG_REG_CALL_STACK
, TCG_STATIC_CALL_ARGS_SIZE
,
2087 CPU_TEMP_BUF_NLONGS
* sizeof(long));
2089 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
2091 tcg_out_bx(s
, COND_AL
, tcg_target_call_iarg_regs
[1]);
2092 tb_ret_addr
= s
->code_ptr
;
2094 /* Epilogue. We branch here via tb_ret_addr. */
2095 tcg_out_dat_rI(s
, COND_AL
, ARITH_ADD
, TCG_REG_CALL_STACK
,
2096 TCG_REG_CALL_STACK
, stack_addend
, 1);
2098 /* ldmia sp!, { r4 - r11, pc } */
2099 tcg_out32(s
, (COND_AL
<< 28) | 0x08bd8ff0);
2104 uint8_t fde_def_cfa
[4];
2105 uint8_t fde_reg_ofs
[18];
2108 #define ELF_HOST_MACHINE EM_ARM
2110 /* We're expecting a 2 byte uleb128 encoded value. */
2111 QEMU_BUILD_BUG_ON(FRAME_SIZE
>= (1 << 14));
2113 static const DebugFrame debug_frame
= {
2114 .h
.cie
.len
= sizeof(DebugFrameCIE
)-4, /* length after .len member */
2117 .h
.cie
.code_align
= 1,
2118 .h
.cie
.data_align
= 0x7c, /* sleb128 -4 */
2119 .h
.cie
.return_column
= 14,
2121 /* Total FDE size does not include the "len" member. */
2122 .h
.fde
.len
= sizeof(DebugFrame
) - offsetof(DebugFrame
, h
.fde
.cie_offset
),
2125 12, 13, /* DW_CFA_def_cfa sp, ... */
2126 (FRAME_SIZE
& 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2130 /* The following must match the stmdb in the prologue. */
2131 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2132 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2133 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2134 0x89, 4, /* DW_CFA_offset, r9, -16 */
2135 0x88, 5, /* DW_CFA_offset, r8, -20 */
2136 0x87, 6, /* DW_CFA_offset, r7, -24 */
2137 0x86, 7, /* DW_CFA_offset, r6, -28 */
2138 0x85, 8, /* DW_CFA_offset, r5, -32 */
2139 0x84, 9, /* DW_CFA_offset, r4, -36 */
2143 void tcg_register_jit(void *buf
, size_t buf_size
)
2145 tcg_register_jit_int(buf
, buf_size
, &debug_frame
, sizeof(debug_frame
));