tcg-arm: Fix 64-bit tlb load for pre-v6
[qemu/ar7.git] / tcg / arm / tcg-target.c
blob12edad4875b5e80ad0e932050da23eae167d3b53
1 /*
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
22 * THE SOFTWARE.
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
31 #endif
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
40 #endif
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
47 #endif
49 #ifdef USE_ARMV5_INSTRUCTIONS
50 static const int use_armv5_instructions = 1;
51 #else
52 static const int use_armv5_instructions = 0;
53 #endif
54 #undef USE_ARMV5_INSTRUCTIONS
56 #ifdef USE_ARMV6_INSTRUCTIONS
57 static const int use_armv6_instructions = 1;
58 #else
59 static const int use_armv6_instructions = 0;
60 #endif
61 #undef USE_ARMV6_INSTRUCTIONS
63 #ifdef USE_ARMV7_INSTRUCTIONS
64 static const int use_armv7_instructions = 1;
65 #else
66 static const int use_armv7_instructions = 0;
67 #endif
68 #undef USE_ARMV7_INSTRUCTIONS
70 #ifndef NDEBUG
71 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
72 "%r0",
73 "%r1",
74 "%r2",
75 "%r3",
76 "%r4",
77 "%r5",
78 "%r6",
79 "%r7",
80 "%r8",
81 "%r9",
82 "%r10",
83 "%r11",
84 "%r12",
85 "%r13",
86 "%r14",
87 "%pc",
89 #endif
91 static const int tcg_target_reg_alloc_order[] = {
92 TCG_REG_R4,
93 TCG_REG_R5,
94 TCG_REG_R6,
95 TCG_REG_R7,
96 TCG_REG_R8,
97 TCG_REG_R9,
98 TCG_REG_R10,
99 TCG_REG_R11,
100 TCG_REG_R13,
101 TCG_REG_R0,
102 TCG_REG_R1,
103 TCG_REG_R2,
104 TCG_REG_R3,
105 TCG_REG_R12,
106 TCG_REG_R14,
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_abs32(void *code_ptr, tcg_target_long target)
120 *(uint32_t *) code_ptr = target;
123 static inline void reloc_pc24(void *code_ptr, tcg_target_long target)
125 uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2);
127 *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
128 | (offset & 0xffffff);
131 static void patch_reloc(uint8_t *code_ptr, int type,
132 tcg_target_long value, tcg_target_long addend)
134 switch (type) {
135 case R_ARM_ABS32:
136 reloc_abs32(code_ptr, value);
137 break;
139 case R_ARM_CALL:
140 case R_ARM_JUMP24:
141 default:
142 tcg_abort();
144 case R_ARM_PC24:
145 reloc_pc24(code_ptr, value);
146 break;
150 #define TCG_CT_CONST_ARM 0x100
151 #define TCG_CT_CONST_INV 0x200
152 #define TCG_CT_CONST_NEG 0x400
153 #define TCG_CT_CONST_ZERO 0x800
155 /* parse target specific constraints */
156 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
158 const char *ct_str;
160 ct_str = *pct_str;
161 switch (ct_str[0]) {
162 case 'I':
163 ct->ct |= TCG_CT_CONST_ARM;
164 break;
165 case 'K':
166 ct->ct |= TCG_CT_CONST_INV;
167 break;
168 case 'N': /* The gcc constraint letter is L, already used here. */
169 ct->ct |= TCG_CT_CONST_NEG;
170 break;
171 case 'Z':
172 ct->ct |= TCG_CT_CONST_ZERO;
173 break;
175 case 'r':
176 ct->ct |= TCG_CT_REG;
177 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
178 break;
180 /* qemu_ld address */
181 case 'l':
182 ct->ct |= TCG_CT_REG;
183 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
184 #ifdef CONFIG_SOFTMMU
185 /* r0-r2 will be overwritten when reading the tlb entry,
186 so don't use these. */
187 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
188 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
189 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
190 #endif
191 break;
192 case 'L':
193 ct->ct |= TCG_CT_REG;
194 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
195 #ifdef CONFIG_SOFTMMU
196 /* r1 is still needed to load data_reg or data_reg2,
197 so don't use it. */
198 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
199 #endif
200 break;
202 /* qemu_st address & data_reg */
203 case 's':
204 ct->ct |= TCG_CT_REG;
205 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
206 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
207 and r0-r1 doing the byte swapping, so don't use these. */
208 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
209 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
210 #if defined(CONFIG_SOFTMMU)
211 /* Avoid clashes with registers being used for helper args */
212 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
213 #if TARGET_LONG_BITS == 64
214 /* Avoid clashes with registers being used for helper args */
215 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
216 #endif
217 #endif
218 break;
220 default:
221 return -1;
223 ct_str++;
224 *pct_str = ct_str;
226 return 0;
229 static inline uint32_t rotl(uint32_t val, int n)
231 return (val << n) | (val >> (32 - n));
234 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
235 right-rotated by an even amount between 0 and 30. */
236 static inline int encode_imm(uint32_t imm)
238 int shift;
240 /* simple case, only lower bits */
241 if ((imm & ~0xff) == 0)
242 return 0;
243 /* then try a simple even shift */
244 shift = ctz32(imm) & ~1;
245 if (((imm >> shift) & ~0xff) == 0)
246 return 32 - shift;
247 /* now try harder with rotations */
248 if ((rotl(imm, 2) & ~0xff) == 0)
249 return 2;
250 if ((rotl(imm, 4) & ~0xff) == 0)
251 return 4;
252 if ((rotl(imm, 6) & ~0xff) == 0)
253 return 6;
254 /* imm can't be encoded */
255 return -1;
258 static inline int check_fit_imm(uint32_t imm)
260 return encode_imm(imm) >= 0;
263 /* Test if a constant matches the constraint.
264 * TODO: define constraints for:
266 * ldr/str offset: between -0xfff and 0xfff
267 * ldrh/strh offset: between -0xff and 0xff
268 * mov operand2: values represented with x << (2 * y), x < 0x100
269 * add, sub, eor...: ditto
271 static inline int tcg_target_const_match(tcg_target_long val,
272 const TCGArgConstraint *arg_ct)
274 int ct;
275 ct = arg_ct->ct;
276 if (ct & TCG_CT_CONST) {
277 return 1;
278 } else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
279 return 1;
280 } else if ((ct & TCG_CT_CONST_INV) && check_fit_imm(~val)) {
281 return 1;
282 } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
283 return 1;
284 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
285 return 1;
286 } else {
287 return 0;
291 #define TO_CPSR (1 << 20)
293 typedef enum {
294 ARITH_AND = 0x0 << 21,
295 ARITH_EOR = 0x1 << 21,
296 ARITH_SUB = 0x2 << 21,
297 ARITH_RSB = 0x3 << 21,
298 ARITH_ADD = 0x4 << 21,
299 ARITH_ADC = 0x5 << 21,
300 ARITH_SBC = 0x6 << 21,
301 ARITH_RSC = 0x7 << 21,
302 ARITH_TST = 0x8 << 21 | TO_CPSR,
303 ARITH_CMP = 0xa << 21 | TO_CPSR,
304 ARITH_CMN = 0xb << 21 | TO_CPSR,
305 ARITH_ORR = 0xc << 21,
306 ARITH_MOV = 0xd << 21,
307 ARITH_BIC = 0xe << 21,
308 ARITH_MVN = 0xf << 21,
310 INSN_LDR_IMM = 0x04100000,
311 INSN_LDR_REG = 0x06100000,
312 INSN_STR_IMM = 0x04000000,
313 INSN_STR_REG = 0x06000000,
315 INSN_LDRH_IMM = 0x005000b0,
316 INSN_LDRH_REG = 0x001000b0,
317 INSN_LDRSH_IMM = 0x005000f0,
318 INSN_LDRSH_REG = 0x001000f0,
319 INSN_STRH_IMM = 0x004000b0,
320 INSN_STRH_REG = 0x000000b0,
322 INSN_LDRB_IMM = 0x04500000,
323 INSN_LDRB_REG = 0x06500000,
324 INSN_LDRSB_IMM = 0x005000d0,
325 INSN_LDRSB_REG = 0x001000d0,
326 INSN_STRB_IMM = 0x04400000,
327 INSN_STRB_REG = 0x06400000,
329 INSN_LDRD_IMM = 0x004000d0,
330 } ARMInsn;
332 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
333 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
334 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
335 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
336 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
337 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
338 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
339 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
341 enum arm_cond_code_e {
342 COND_EQ = 0x0,
343 COND_NE = 0x1,
344 COND_CS = 0x2, /* Unsigned greater or equal */
345 COND_CC = 0x3, /* Unsigned less than */
346 COND_MI = 0x4, /* Negative */
347 COND_PL = 0x5, /* Zero or greater */
348 COND_VS = 0x6, /* Overflow */
349 COND_VC = 0x7, /* No overflow */
350 COND_HI = 0x8, /* Unsigned greater than */
351 COND_LS = 0x9, /* Unsigned less or equal */
352 COND_GE = 0xa,
353 COND_LT = 0xb,
354 COND_GT = 0xc,
355 COND_LE = 0xd,
356 COND_AL = 0xe,
359 static const uint8_t tcg_cond_to_arm_cond[] = {
360 [TCG_COND_EQ] = COND_EQ,
361 [TCG_COND_NE] = COND_NE,
362 [TCG_COND_LT] = COND_LT,
363 [TCG_COND_GE] = COND_GE,
364 [TCG_COND_LE] = COND_LE,
365 [TCG_COND_GT] = COND_GT,
366 /* unsigned */
367 [TCG_COND_LTU] = COND_CC,
368 [TCG_COND_GEU] = COND_CS,
369 [TCG_COND_LEU] = COND_LS,
370 [TCG_COND_GTU] = COND_HI,
373 static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
375 tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
378 static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
380 tcg_out32(s, (cond << 28) | 0x0a000000 |
381 (((offset - 8) >> 2) & 0x00ffffff));
384 static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
386 /* We pay attention here to not modify the branch target by skipping
387 the corresponding bytes. This ensure that caches and memory are
388 kept coherent during retranslation. */
389 #ifdef HOST_WORDS_BIGENDIAN
390 tcg_out8(s, (cond << 4) | 0x0a);
391 s->code_ptr += 3;
392 #else
393 s->code_ptr += 3;
394 tcg_out8(s, (cond << 4) | 0x0a);
395 #endif
398 static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
400 tcg_out32(s, (cond << 28) | 0x0b000000 |
401 (((offset - 8) >> 2) & 0x00ffffff));
404 static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
406 tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
409 static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
411 tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
412 (((offset - 8) >> 2) & 0x00ffffff));
415 static inline void tcg_out_dat_reg(TCGContext *s,
416 int cond, int opc, int rd, int rn, int rm, int shift)
418 tcg_out32(s, (cond << 28) | (0 << 25) | opc |
419 (rn << 16) | (rd << 12) | shift | rm);
422 static inline void tcg_out_nop(TCGContext *s)
424 if (use_armv7_instructions) {
425 /* Architected nop introduced in v6k. */
426 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
427 also Just So Happened to do nothing on pre-v6k so that we
428 don't need to conditionalize it? */
429 tcg_out32(s, 0xe320f000);
430 } else {
431 /* Prior to that the assembler uses mov r0, r0. */
432 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 0, 0, 0, SHIFT_IMM_LSL(0));
436 static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
438 /* Simple reg-reg move, optimising out the 'do nothing' case */
439 if (rd != rm) {
440 tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, rm, SHIFT_IMM_LSL(0));
444 static inline void tcg_out_dat_imm(TCGContext *s,
445 int cond, int opc, int rd, int rn, int im)
447 tcg_out32(s, (cond << 28) | (1 << 25) | opc |
448 (rn << 16) | (rd << 12) | im);
451 static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
453 int rot, opc, rn;
455 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
456 Speed things up by only checking when movt would be required.
457 Prior to armv7, have one go at fully rotated immediates before
458 doing the decomposition thing below. */
459 if (!use_armv7_instructions || (arg & 0xffff0000)) {
460 rot = encode_imm(arg);
461 if (rot >= 0) {
462 tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
463 rotl(arg, rot) | (rot << 7));
464 return;
466 rot = encode_imm(~arg);
467 if (rot >= 0) {
468 tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
469 rotl(~arg, rot) | (rot << 7));
470 return;
474 /* Use movw + movt. */
475 if (use_armv7_instructions) {
476 /* movw */
477 tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
478 | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
479 if (arg & 0xffff0000) {
480 /* movt */
481 tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
482 | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
484 return;
487 /* TODO: This is very suboptimal, we can easily have a constant
488 pool somewhere after all the instructions. */
489 opc = ARITH_MOV;
490 rn = 0;
491 /* If we have lots of leading 1's, we can shorten the sequence by
492 beginning with mvn and then clearing higher bits with eor. */
493 if (clz32(~arg) > clz32(arg)) {
494 opc = ARITH_MVN, arg = ~arg;
496 do {
497 int i = ctz32(arg) & ~1;
498 rot = ((32 - i) << 7) & 0xf00;
499 tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
500 arg &= ~(0xff << i);
502 opc = ARITH_EOR;
503 rn = rd;
504 } while (arg);
507 static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
508 TCGArg lhs, TCGArg rhs, int rhs_is_const)
510 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
511 * rhs must satisfy the "rI" constraint.
513 if (rhs_is_const) {
514 int rot = encode_imm(rhs);
515 assert(rot >= 0);
516 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
517 } else {
518 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
522 static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
523 TCGReg dst, TCGReg lhs, TCGArg rhs,
524 bool rhs_is_const)
526 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
527 * rhs must satisfy the "rIK" constraint.
529 if (rhs_is_const) {
530 int rot = encode_imm(rhs);
531 if (rot < 0) {
532 rhs = ~rhs;
533 rot = encode_imm(rhs);
534 assert(rot >= 0);
535 opc = opinv;
537 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
538 } else {
539 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
543 static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
544 TCGArg dst, TCGArg lhs, TCGArg rhs,
545 bool rhs_is_const)
547 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
548 * rhs must satisfy the "rIN" constraint.
550 if (rhs_is_const) {
551 int rot = encode_imm(rhs);
552 if (rot < 0) {
553 rhs = -rhs;
554 rot = encode_imm(rhs);
555 assert(rot >= 0);
556 opc = opneg;
558 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
559 } else {
560 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
564 static inline void tcg_out_mul32(TCGContext *s, int cond, TCGReg rd,
565 TCGReg rn, TCGReg rm)
567 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
568 if (!use_armv6_instructions && rd == rn) {
569 if (rd == rm) {
570 /* rd == rn == rm; copy an input to tmp first. */
571 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
572 rm = rn = TCG_REG_TMP;
573 } else {
574 rn = rm;
575 rm = rd;
578 /* mul */
579 tcg_out32(s, (cond << 28) | 0x90 | (rd << 16) | (rm << 8) | rn);
582 static inline void tcg_out_umull32(TCGContext *s, int cond, TCGReg rd0,
583 TCGReg rd1, TCGReg rn, TCGReg rm)
585 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
586 if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
587 if (rd0 == rm || rd1 == rm) {
588 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
589 rn = TCG_REG_TMP;
590 } else {
591 TCGReg t = rn;
592 rn = rm;
593 rm = t;
596 /* umull */
597 tcg_out32(s, (cond << 28) | 0x00800090 |
598 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
601 static inline void tcg_out_smull32(TCGContext *s, int cond, TCGReg rd0,
602 TCGReg rd1, TCGReg rn, TCGReg rm)
604 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
605 if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
606 if (rd0 == rm || rd1 == rm) {
607 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
608 rn = TCG_REG_TMP;
609 } else {
610 TCGReg t = rn;
611 rn = rm;
612 rm = t;
615 /* smull */
616 tcg_out32(s, (cond << 28) | 0x00c00090 |
617 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
620 static inline void tcg_out_sdiv(TCGContext *s, int cond, int rd, int rn, int rm)
622 tcg_out32(s, 0x0710f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
625 static inline void tcg_out_udiv(TCGContext *s, int cond, int rd, int rn, int rm)
627 tcg_out32(s, 0x0730f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
630 static inline void tcg_out_ext8s(TCGContext *s, int cond,
631 int rd, int rn)
633 if (use_armv6_instructions) {
634 /* sxtb */
635 tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
636 } else {
637 tcg_out_dat_reg(s, cond, ARITH_MOV,
638 rd, 0, rn, SHIFT_IMM_LSL(24));
639 tcg_out_dat_reg(s, cond, ARITH_MOV,
640 rd, 0, rd, SHIFT_IMM_ASR(24));
644 static inline void tcg_out_ext8u(TCGContext *s, int cond,
645 int rd, int rn)
647 tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
650 static inline void tcg_out_ext16s(TCGContext *s, int cond,
651 int rd, int rn)
653 if (use_armv6_instructions) {
654 /* sxth */
655 tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
656 } else {
657 tcg_out_dat_reg(s, cond, ARITH_MOV,
658 rd, 0, rn, SHIFT_IMM_LSL(16));
659 tcg_out_dat_reg(s, cond, ARITH_MOV,
660 rd, 0, rd, SHIFT_IMM_ASR(16));
664 static inline void tcg_out_ext16u(TCGContext *s, int cond,
665 int rd, int rn)
667 if (use_armv6_instructions) {
668 /* uxth */
669 tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
670 } else {
671 tcg_out_dat_reg(s, cond, ARITH_MOV,
672 rd, 0, rn, SHIFT_IMM_LSL(16));
673 tcg_out_dat_reg(s, cond, ARITH_MOV,
674 rd, 0, rd, SHIFT_IMM_LSR(16));
678 static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
680 if (use_armv6_instructions) {
681 /* revsh */
682 tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
683 } else {
684 tcg_out_dat_reg(s, cond, ARITH_MOV,
685 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
686 tcg_out_dat_reg(s, cond, ARITH_MOV,
687 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_ASR(16));
688 tcg_out_dat_reg(s, cond, ARITH_ORR,
689 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
693 static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
695 if (use_armv6_instructions) {
696 /* rev16 */
697 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
698 } else {
699 tcg_out_dat_reg(s, cond, ARITH_MOV,
700 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
701 tcg_out_dat_reg(s, cond, ARITH_MOV,
702 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_LSR(16));
703 tcg_out_dat_reg(s, cond, ARITH_ORR,
704 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
708 /* swap the two low bytes assuming that the two high input bytes and the
709 two high output bit can hold any value. */
710 static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
712 if (use_armv6_instructions) {
713 /* rev16 */
714 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
715 } else {
716 tcg_out_dat_reg(s, cond, ARITH_MOV,
717 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSR(8));
718 tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, 0xff);
719 tcg_out_dat_reg(s, cond, ARITH_ORR,
720 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSL(8));
724 static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
726 if (use_armv6_instructions) {
727 /* rev */
728 tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
729 } else {
730 tcg_out_dat_reg(s, cond, ARITH_EOR,
731 TCG_REG_TMP, rn, rn, SHIFT_IMM_ROR(16));
732 tcg_out_dat_imm(s, cond, ARITH_BIC,
733 TCG_REG_TMP, TCG_REG_TMP, 0xff | 0x800);
734 tcg_out_dat_reg(s, cond, ARITH_MOV,
735 rd, 0, rn, SHIFT_IMM_ROR(8));
736 tcg_out_dat_reg(s, cond, ARITH_EOR,
737 rd, rd, TCG_REG_TMP, SHIFT_IMM_LSR(8));
741 bool tcg_target_deposit_valid(int ofs, int len)
743 /* ??? Without bfi, we could improve over generic code by combining
744 the right-shift from a non-zero ofs with the orr. We do run into
745 problems when rd == rs, and the mask generated from ofs+len doesn't
746 fit into an immediate. We would have to be careful not to pessimize
747 wrt the optimizations performed on the expanded code. */
748 return use_armv7_instructions;
751 static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd,
752 TCGArg a1, int ofs, int len, bool const_a1)
754 if (const_a1) {
755 /* bfi becomes bfc with rn == 15. */
756 a1 = 15;
758 /* bfi/bfc */
759 tcg_out32(s, 0x07c00010 | (cond << 28) | (rd << 12) | a1
760 | (ofs << 7) | ((ofs + len - 1) << 16));
763 /* Note that this routine is used for both LDR and LDRH formats, so we do
764 not wish to include an immediate shift at this point. */
765 static void tcg_out_memop_r(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
766 TCGReg rn, TCGReg rm, bool u, bool p, bool w)
768 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24)
769 | (w << 21) | (rn << 16) | (rt << 12) | rm);
772 static void tcg_out_memop_8(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
773 TCGReg rn, int imm8, bool p, bool w)
775 bool u = 1;
776 if (imm8 < 0) {
777 imm8 = -imm8;
778 u = 0;
780 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
781 (rn << 16) | (rt << 12) | ((imm8 & 0xf0) << 4) | (imm8 & 0xf));
784 static void tcg_out_memop_12(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
785 TCGReg rn, int imm12, bool p, bool w)
787 bool u = 1;
788 if (imm12 < 0) {
789 imm12 = -imm12;
790 u = 0;
792 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
793 (rn << 16) | (rt << 12) | imm12);
796 static inline void tcg_out_ld32_12(TCGContext *s, int cond, TCGReg rt,
797 TCGReg rn, int imm12)
799 tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 0);
802 static inline void tcg_out_st32_12(TCGContext *s, int cond, TCGReg rt,
803 TCGReg rn, int imm12)
805 tcg_out_memop_12(s, cond, INSN_STR_IMM, rt, rn, imm12, 1, 0);
808 static inline void tcg_out_ld32_r(TCGContext *s, int cond, TCGReg rt,
809 TCGReg rn, TCGReg rm)
811 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 0);
814 static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt,
815 TCGReg rn, TCGReg rm)
817 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0);
820 /* Register pre-increment with base writeback. */
821 static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt,
822 TCGReg rn, TCGReg rm)
824 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 1);
827 static inline void tcg_out_st32_rwb(TCGContext *s, int cond, TCGReg rt,
828 TCGReg rn, TCGReg rm)
830 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 1);
833 static inline void tcg_out_ld16u_8(TCGContext *s, int cond, TCGReg rt,
834 TCGReg rn, int imm8)
836 tcg_out_memop_8(s, cond, INSN_LDRH_IMM, rt, rn, imm8, 1, 0);
839 static inline void tcg_out_st16_8(TCGContext *s, int cond, TCGReg rt,
840 TCGReg rn, int imm8)
842 tcg_out_memop_8(s, cond, INSN_STRH_IMM, rt, rn, imm8, 1, 0);
845 static inline void tcg_out_ld16u_r(TCGContext *s, int cond, TCGReg rt,
846 TCGReg rn, TCGReg rm)
848 tcg_out_memop_r(s, cond, INSN_LDRH_REG, rt, rn, rm, 1, 1, 0);
851 static inline void tcg_out_st16_r(TCGContext *s, int cond, TCGReg rt,
852 TCGReg rn, TCGReg rm)
854 tcg_out_memop_r(s, cond, INSN_STRH_REG, rt, rn, rm, 1, 1, 0);
857 static inline void tcg_out_ld16s_8(TCGContext *s, int cond, TCGReg rt,
858 TCGReg rn, int imm8)
860 tcg_out_memop_8(s, cond, INSN_LDRSH_IMM, rt, rn, imm8, 1, 0);
863 static inline void tcg_out_ld16s_r(TCGContext *s, int cond, TCGReg rt,
864 TCGReg rn, TCGReg rm)
866 tcg_out_memop_r(s, cond, INSN_LDRSH_REG, rt, rn, rm, 1, 1, 0);
869 static inline void tcg_out_ld8_12(TCGContext *s, int cond, TCGReg rt,
870 TCGReg rn, int imm12)
872 tcg_out_memop_12(s, cond, INSN_LDRB_IMM, rt, rn, imm12, 1, 0);
875 static inline void tcg_out_st8_12(TCGContext *s, int cond, TCGReg rt,
876 TCGReg rn, int imm12)
878 tcg_out_memop_12(s, cond, INSN_STRB_IMM, rt, rn, imm12, 1, 0);
881 static inline void tcg_out_ld8_r(TCGContext *s, int cond, TCGReg rt,
882 TCGReg rn, TCGReg rm)
884 tcg_out_memop_r(s, cond, INSN_LDRB_REG, rt, rn, rm, 1, 1, 0);
887 static inline void tcg_out_st8_r(TCGContext *s, int cond, TCGReg rt,
888 TCGReg rn, TCGReg rm)
890 tcg_out_memop_r(s, cond, INSN_STRB_REG, rt, rn, rm, 1, 1, 0);
893 static inline void tcg_out_ld8s_8(TCGContext *s, int cond, TCGReg rt,
894 TCGReg rn, int imm8)
896 tcg_out_memop_8(s, cond, INSN_LDRSB_IMM, rt, rn, imm8, 1, 0);
899 static inline void tcg_out_ld8s_r(TCGContext *s, int cond, TCGReg rt,
900 TCGReg rn, TCGReg rm)
902 tcg_out_memop_r(s, cond, INSN_LDRSB_REG, rt, rn, rm, 1, 1, 0);
905 static inline void tcg_out_ld32u(TCGContext *s, int cond,
906 int rd, int rn, int32_t offset)
908 if (offset > 0xfff || offset < -0xfff) {
909 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
910 tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_TMP);
911 } else
912 tcg_out_ld32_12(s, cond, rd, rn, offset);
915 static inline void tcg_out_st32(TCGContext *s, int cond,
916 int rd, int rn, int32_t offset)
918 if (offset > 0xfff || offset < -0xfff) {
919 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
920 tcg_out_st32_r(s, cond, rd, rn, TCG_REG_TMP);
921 } else
922 tcg_out_st32_12(s, cond, rd, rn, offset);
925 static inline void tcg_out_ld16u(TCGContext *s, int cond,
926 int rd, int rn, int32_t offset)
928 if (offset > 0xff || offset < -0xff) {
929 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
930 tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_TMP);
931 } else
932 tcg_out_ld16u_8(s, cond, rd, rn, offset);
935 static inline void tcg_out_ld16s(TCGContext *s, int cond,
936 int rd, int rn, int32_t offset)
938 if (offset > 0xff || offset < -0xff) {
939 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
940 tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_TMP);
941 } else
942 tcg_out_ld16s_8(s, cond, rd, rn, offset);
945 static inline void tcg_out_st16(TCGContext *s, int cond,
946 int rd, int rn, int32_t offset)
948 if (offset > 0xff || offset < -0xff) {
949 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
950 tcg_out_st16_r(s, cond, rd, rn, TCG_REG_TMP);
951 } else
952 tcg_out_st16_8(s, cond, rd, rn, offset);
955 static inline void tcg_out_ld8u(TCGContext *s, int cond,
956 int rd, int rn, int32_t offset)
958 if (offset > 0xfff || offset < -0xfff) {
959 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
960 tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_TMP);
961 } else
962 tcg_out_ld8_12(s, cond, rd, rn, offset);
965 static inline void tcg_out_ld8s(TCGContext *s, int cond,
966 int rd, int rn, int32_t offset)
968 if (offset > 0xff || offset < -0xff) {
969 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
970 tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_TMP);
971 } else
972 tcg_out_ld8s_8(s, cond, rd, rn, offset);
975 static inline void tcg_out_st8(TCGContext *s, int cond,
976 int rd, int rn, int32_t offset)
978 if (offset > 0xfff || offset < -0xfff) {
979 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
980 tcg_out_st8_r(s, cond, rd, rn, TCG_REG_TMP);
981 } else
982 tcg_out_st8_12(s, cond, rd, rn, offset);
985 /* The _goto case is normally between TBs within the same code buffer,
986 * and with the code buffer limited to 16MB we shouldn't need the long
987 * case.
989 * .... except to the prologue that is in its own buffer.
991 static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
993 int32_t val;
995 if (addr & 1) {
996 /* goto to a Thumb destination isn't supported */
997 tcg_abort();
1000 val = addr - (tcg_target_long) s->code_ptr;
1001 if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
1002 tcg_out_b(s, cond, val);
1003 else {
1004 if (cond == COND_AL) {
1005 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1006 tcg_out32(s, addr);
1007 } else {
1008 tcg_out_movi32(s, cond, TCG_REG_TMP, val - 8);
1009 tcg_out_dat_reg(s, cond, ARITH_ADD,
1010 TCG_REG_PC, TCG_REG_PC,
1011 TCG_REG_TMP, SHIFT_IMM_LSL(0));
1016 /* The call case is mostly used for helpers - so it's not unreasonable
1017 * for them to be beyond branch range */
1018 static inline void tcg_out_call(TCGContext *s, uint32_t addr)
1020 int32_t val;
1022 val = addr - (tcg_target_long) s->code_ptr;
1023 if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
1024 if (addr & 1) {
1025 /* Use BLX if the target is in Thumb mode */
1026 if (!use_armv5_instructions) {
1027 tcg_abort();
1029 tcg_out_blx_imm(s, val);
1030 } else {
1031 tcg_out_bl(s, COND_AL, val);
1033 } else if (use_armv7_instructions) {
1034 tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addr);
1035 tcg_out_blx(s, COND_AL, TCG_REG_TMP);
1036 } else {
1037 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
1038 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1039 tcg_out32(s, addr);
1043 static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
1045 if (use_armv5_instructions) {
1046 tcg_out_blx(s, cond, arg);
1047 } else {
1048 tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
1049 TCG_REG_PC, SHIFT_IMM_LSL(0));
1050 tcg_out_bx(s, cond, arg);
1054 static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
1056 TCGLabel *l = &s->labels[label_index];
1058 if (l->has_value) {
1059 tcg_out_goto(s, cond, l->u.value);
1060 } else {
1061 tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
1062 tcg_out_b_noaddr(s, cond);
1066 #ifdef CONFIG_SOFTMMU
1068 #include "exec/softmmu_defs.h"
1070 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
1071 int mmu_idx) */
1072 static const void * const qemu_ld_helpers[4] = {
1073 helper_ldb_mmu,
1074 helper_ldw_mmu,
1075 helper_ldl_mmu,
1076 helper_ldq_mmu,
1079 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
1080 uintxx_t val, int mmu_idx) */
1081 static const void * const qemu_st_helpers[4] = {
1082 helper_stb_mmu,
1083 helper_stw_mmu,
1084 helper_stl_mmu,
1085 helper_stq_mmu,
1088 /* Helper routines for marshalling helper function arguments into
1089 * the correct registers and stack.
1090 * argreg is where we want to put this argument, arg is the argument itself.
1091 * Return value is the updated argreg ready for the next call.
1092 * Note that argreg 0..3 is real registers, 4+ on stack.
1094 * We provide routines for arguments which are: immediate, 32 bit
1095 * value in register, 16 and 8 bit values in register (which must be zero
1096 * extended before use) and 64 bit value in a lo:hi register pair.
1098 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1099 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1101 if (argreg < 4) { \
1102 MOV_ARG(s, COND_AL, argreg, arg); \
1103 } else { \
1104 int ofs = (argreg - 4) * 4; \
1105 EXT_ARG; \
1106 assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1107 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1109 return argreg + 1; \
1112 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
1113 (tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1114 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
1115 (tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1116 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
1117 (tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1118 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
1120 static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
1121 TCGReg arglo, TCGReg arghi)
1123 /* 64 bit arguments must go in even/odd register pairs
1124 * and in 8-aligned stack slots.
1126 if (argreg & 1) {
1127 argreg++;
1129 argreg = tcg_out_arg_reg32(s, argreg, arglo);
1130 argreg = tcg_out_arg_reg32(s, argreg, arghi);
1131 return argreg;
1134 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1136 /* Load and compare a TLB entry, leaving the flags set. Leaves R2 pointing
1137 to the tlb entry. Clobbers R1 and TMP. */
1139 static void tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
1140 int s_bits, int tlb_offset)
1142 TCGReg base = TCG_AREG0;
1144 /* Should generate something like the following:
1145 * pre-v7:
1146 * shr tmp, addr_reg, #TARGET_PAGE_BITS (1)
1147 * add r2, env, #off & 0xff00
1148 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1149 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1150 * ldr r0, [r2, #off & 0xff]! (4)
1151 * tst addr_reg, #s_mask
1152 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS (5)
1154 * v7 (not implemented yet):
1155 * ubfx r2, addr_reg, #TARGET_PAGE_BITS, #CPU_TLB_BITS (1)
1156 * movw tmp, #~TARGET_PAGE_MASK & ~s_mask
1157 * movw r0, #off
1158 * add r2, env, r2, lsl #CPU_TLB_ENTRY_BITS (2)
1159 * bic tmp, addr_reg, tmp
1160 * ldr r0, [r2, r0]! (3)
1161 * cmp r0, tmp (4)
1163 # if CPU_TLB_BITS > 8
1164 # error
1165 # endif
1166 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
1167 0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1169 /* We assume that the offset is contained within 16 bits. */
1170 assert((tlb_offset & ~0xffff) == 0);
1171 if (tlb_offset > 0xff) {
1172 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1173 (24 << 7) | (tlb_offset >> 8));
1174 tlb_offset &= 0xff;
1175 base = TCG_REG_R2;
1178 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1179 TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
1180 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1181 TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1183 /* Load the tlb comparator. Use ldrd if needed and available,
1184 but due to how the pointer needs setting up, ldm isn't useful.
1185 Base arm5 doesn't have ldrd, but armv5te does. */
1186 if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
1187 tcg_out_memop_8(s, COND_AL, INSN_LDRD_IMM, TCG_REG_R0,
1188 TCG_REG_R2, tlb_offset, 1, 1);
1189 } else {
1190 tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R0,
1191 TCG_REG_R2, tlb_offset, 1, 1);
1192 if (TARGET_LONG_BITS == 64) {
1193 tcg_out_memop_12(s, COND_AL, INSN_LDR_IMM, TCG_REG_R1,
1194 TCG_REG_R2, 4, 1, 0);
1198 /* Check alignment. */
1199 if (s_bits) {
1200 tcg_out_dat_imm(s, COND_AL, ARITH_TST,
1201 0, addrlo, (1 << s_bits) - 1);
1204 tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
1205 TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1207 if (TARGET_LONG_BITS == 64) {
1208 tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1209 TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
1213 /* Record the context of a call to the out of line helper code for the slow
1214 path for a load or store, so that we can later generate the correct
1215 helper code. */
1216 static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
1217 int data_reg, int data_reg2, int addrlo_reg,
1218 int addrhi_reg, int mem_index,
1219 uint8_t *raddr, uint8_t *label_ptr)
1221 int idx;
1222 TCGLabelQemuLdst *label;
1224 if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
1225 tcg_abort();
1228 idx = s->nb_qemu_ldst_labels++;
1229 label = (TCGLabelQemuLdst *)&s->qemu_ldst_labels[idx];
1230 label->is_ld = is_ld;
1231 label->opc = opc;
1232 label->datalo_reg = data_reg;
1233 label->datahi_reg = data_reg2;
1234 label->addrlo_reg = addrlo_reg;
1235 label->addrhi_reg = addrhi_reg;
1236 label->mem_index = mem_index;
1237 label->raddr = raddr;
1238 label->label_ptr[0] = label_ptr;
1241 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1243 TCGReg argreg, data_reg, data_reg2;
1244 uint8_t *start;
1246 reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
1248 argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
1249 if (TARGET_LONG_BITS == 64) {
1250 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1251 } else {
1252 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1254 argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
1255 tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[lb->opc & 3]);
1257 data_reg = lb->datalo_reg;
1258 data_reg2 = lb->datahi_reg;
1260 start = s->code_ptr;
1261 switch (lb->opc) {
1262 case 0 | 4:
1263 tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
1264 break;
1265 case 1 | 4:
1266 tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
1267 break;
1268 case 0:
1269 case 1:
1270 case 2:
1271 default:
1272 tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
1273 break;
1274 case 3:
1275 tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
1276 tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
1277 break;
1280 /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
1281 the call and the branch back to straight-line code. Note that the
1282 moves above could be elided by register allocation, nor do we know
1283 which code alternative we chose for extension. */
1284 switch (s->code_ptr - start) {
1285 case 0:
1286 tcg_out_nop(s);
1287 /* FALLTHRU */
1288 case 4:
1289 tcg_out_nop(s);
1290 /* FALLTHRU */
1291 case 8:
1292 break;
1293 default:
1294 abort();
1297 tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
1300 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1302 TCGReg argreg, data_reg, data_reg2;
1304 reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
1306 argreg = TCG_REG_R0;
1307 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
1308 if (TARGET_LONG_BITS == 64) {
1309 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1310 } else {
1311 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1314 data_reg = lb->datalo_reg;
1315 data_reg2 = lb->datahi_reg;
1316 switch (lb->opc) {
1317 case 0:
1318 argreg = tcg_out_arg_reg8(s, argreg, data_reg);
1319 break;
1320 case 1:
1321 argreg = tcg_out_arg_reg16(s, argreg, data_reg);
1322 break;
1323 case 2:
1324 argreg = tcg_out_arg_reg32(s, argreg, data_reg);
1325 break;
1326 case 3:
1327 argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2);
1328 break;
1331 argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
1332 tcg_out_call(s, (tcg_target_long) qemu_st_helpers[lb->opc & 3]);
1334 /* For GETPC_LDST in exec-all.h, we architect exactly 2 insns between
1335 the call and the branch back to straight-line code. */
1336 tcg_out_nop(s);
1337 tcg_out_nop(s);
1338 tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
1340 #endif /* SOFTMMU */
1342 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
1344 TCGReg addr_reg, data_reg, data_reg2;
1345 bool bswap;
1346 #ifdef CONFIG_SOFTMMU
1347 int mem_index, s_bits;
1348 TCGReg addr_reg2;
1349 uint8_t *label_ptr;
1350 #endif
1351 #ifdef TARGET_WORDS_BIGENDIAN
1352 bswap = 1;
1353 #else
1354 bswap = 0;
1355 #endif
1357 data_reg = *args++;
1358 data_reg2 = (opc == 3 ? *args++ : 0);
1359 addr_reg = *args++;
1360 #ifdef CONFIG_SOFTMMU
1361 addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1362 mem_index = *args;
1363 s_bits = opc & 3;
1365 tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
1366 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read));
1368 label_ptr = s->code_ptr;
1369 tcg_out_b_noaddr(s, COND_NE);
1371 tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
1372 offsetof(CPUTLBEntry, addend)
1373 - offsetof(CPUTLBEntry, addr_read));
1375 switch (opc) {
1376 case 0:
1377 tcg_out_ld8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1378 break;
1379 case 0 | 4:
1380 tcg_out_ld8s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1381 break;
1382 case 1:
1383 tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1384 if (bswap) {
1385 tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
1387 break;
1388 case 1 | 4:
1389 if (bswap) {
1390 tcg_out_ld16u_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1391 tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
1392 } else {
1393 tcg_out_ld16s_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1395 break;
1396 case 2:
1397 default:
1398 tcg_out_ld32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1399 if (bswap) {
1400 tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1402 break;
1403 case 3:
1404 if (bswap) {
1405 tcg_out_ld32_rwb(s, COND_AL, data_reg2, TCG_REG_R1, addr_reg);
1406 tcg_out_ld32_12(s, COND_AL, data_reg, TCG_REG_R1, 4);
1407 tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
1408 tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1409 } else {
1410 tcg_out_ld32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
1411 tcg_out_ld32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
1413 break;
1416 add_qemu_ldst_label(s, 1, opc, data_reg, data_reg2, addr_reg, addr_reg2,
1417 mem_index, s->code_ptr, label_ptr);
1418 #else /* !CONFIG_SOFTMMU */
1419 if (GUEST_BASE) {
1420 uint32_t offset = GUEST_BASE;
1421 int i, rot;
1423 while (offset) {
1424 i = ctz32(offset) & ~1;
1425 rot = ((32 - i) << 7) & 0xf00;
1427 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_TMP, addr_reg,
1428 ((offset >> i) & 0xff) | rot);
1429 addr_reg = TCG_REG_TMP;
1430 offset &= ~(0xff << i);
1433 switch (opc) {
1434 case 0:
1435 tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
1436 break;
1437 case 0 | 4:
1438 tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
1439 break;
1440 case 1:
1441 tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1442 if (bswap) {
1443 tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
1445 break;
1446 case 1 | 4:
1447 if (bswap) {
1448 tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1449 tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
1450 } else {
1451 tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
1453 break;
1454 case 2:
1455 default:
1456 tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1457 if (bswap) {
1458 tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1460 break;
1461 case 3:
1462 /* TODO: use block load -
1463 * check that data_reg2 > data_reg or the other way */
1464 if (data_reg == addr_reg) {
1465 tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1466 tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1467 } else {
1468 tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1469 tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1471 if (bswap) {
1472 tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1473 tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
1475 break;
1477 #endif
1480 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
1482 TCGReg addr_reg, data_reg, data_reg2;
1483 bool bswap;
1484 #ifdef CONFIG_SOFTMMU
1485 int mem_index, s_bits;
1486 TCGReg addr_reg2;
1487 uint8_t *label_ptr;
1488 #endif
1489 #ifdef TARGET_WORDS_BIGENDIAN
1490 bswap = 1;
1491 #else
1492 bswap = 0;
1493 #endif
1495 data_reg = *args++;
1496 data_reg2 = (opc == 3 ? *args++ : 0);
1497 addr_reg = *args++;
1498 #ifdef CONFIG_SOFTMMU
1499 addr_reg2 = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1500 mem_index = *args;
1501 s_bits = opc & 3;
1503 tcg_out_tlb_read(s, addr_reg, addr_reg2, s_bits,
1504 offsetof(CPUArchState,
1505 tlb_table[mem_index][0].addr_write));
1507 label_ptr = s->code_ptr;
1508 tcg_out_b_noaddr(s, COND_NE);
1510 tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2,
1511 offsetof(CPUTLBEntry, addend)
1512 - offsetof(CPUTLBEntry, addr_write));
1514 switch (opc) {
1515 case 0:
1516 tcg_out_st8_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1517 break;
1518 case 1:
1519 if (bswap) {
1520 tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
1521 tcg_out_st16_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1);
1522 } else {
1523 tcg_out_st16_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1525 break;
1526 case 2:
1527 default:
1528 if (bswap) {
1529 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1530 tcg_out_st32_r(s, COND_AL, TCG_REG_R0, addr_reg, TCG_REG_R1);
1531 } else {
1532 tcg_out_st32_r(s, COND_AL, data_reg, addr_reg, TCG_REG_R1);
1534 break;
1535 case 3:
1536 if (bswap) {
1537 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
1538 tcg_out_st32_rwb(s, COND_AL, TCG_REG_R0, TCG_REG_R1, addr_reg);
1539 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1540 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R1, 4);
1541 } else {
1542 tcg_out_st32_rwb(s, COND_AL, data_reg, TCG_REG_R1, addr_reg);
1543 tcg_out_st32_12(s, COND_AL, data_reg2, TCG_REG_R1, 4);
1545 break;
1548 add_qemu_ldst_label(s, 0, opc, data_reg, data_reg2, addr_reg, addr_reg2,
1549 mem_index, s->code_ptr, label_ptr);
1550 #else /* !CONFIG_SOFTMMU */
1551 if (GUEST_BASE) {
1552 uint32_t offset = GUEST_BASE;
1553 int i;
1554 int rot;
1556 while (offset) {
1557 i = ctz32(offset) & ~1;
1558 rot = ((32 - i) << 7) & 0xf00;
1560 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
1561 ((offset >> i) & 0xff) | rot);
1562 addr_reg = TCG_REG_R1;
1563 offset &= ~(0xff << i);
1566 switch (opc) {
1567 case 0:
1568 tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
1569 break;
1570 case 1:
1571 if (bswap) {
1572 tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
1573 tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1574 } else {
1575 tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
1577 break;
1578 case 2:
1579 default:
1580 if (bswap) {
1581 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1582 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1583 } else {
1584 tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1586 break;
1587 case 3:
1588 /* TODO: use block store -
1589 * check that data_reg2 > data_reg or the other way */
1590 if (bswap) {
1591 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
1592 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1593 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1594 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
1595 } else {
1596 tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1597 tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
1599 break;
1601 #endif
1604 static uint8_t *tb_ret_addr;
1606 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1607 const TCGArg *args, const int *const_args)
1609 TCGArg a0, a1, a2, a3, a4, a5;
1610 int c;
1612 switch (opc) {
1613 case INDEX_op_exit_tb:
1615 uint8_t *ld_ptr = s->code_ptr;
1616 if (args[0] >> 8)
1617 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1618 else
1619 tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1620 tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1621 if (args[0] >> 8) {
1622 *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
1623 tcg_out32(s, args[0]);
1626 break;
1627 case INDEX_op_goto_tb:
1628 if (s->tb_jmp_offset) {
1629 /* Direct jump method */
1630 #if defined(USE_DIRECT_JUMP)
1631 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1632 tcg_out_b_noaddr(s, COND_AL);
1633 #else
1634 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1635 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1636 tcg_out32(s, 0);
1637 #endif
1638 } else {
1639 /* Indirect jump method */
1640 #if 1
1641 c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
1642 if (c > 0xfff || c < -0xfff) {
1643 tcg_out_movi32(s, COND_AL, TCG_REG_R0,
1644 (tcg_target_long) (s->tb_next + args[0]));
1645 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1646 } else
1647 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
1648 #else
1649 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1650 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1651 tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
1652 #endif
1654 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1655 break;
1656 case INDEX_op_call:
1657 if (const_args[0])
1658 tcg_out_call(s, args[0]);
1659 else
1660 tcg_out_callr(s, COND_AL, args[0]);
1661 break;
1662 case INDEX_op_br:
1663 tcg_out_goto_label(s, COND_AL, args[0]);
1664 break;
1666 case INDEX_op_ld8u_i32:
1667 tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1668 break;
1669 case INDEX_op_ld8s_i32:
1670 tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1671 break;
1672 case INDEX_op_ld16u_i32:
1673 tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1674 break;
1675 case INDEX_op_ld16s_i32:
1676 tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1677 break;
1678 case INDEX_op_ld_i32:
1679 tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1680 break;
1681 case INDEX_op_st8_i32:
1682 tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1683 break;
1684 case INDEX_op_st16_i32:
1685 tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1686 break;
1687 case INDEX_op_st_i32:
1688 tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1689 break;
1691 case INDEX_op_mov_i32:
1692 tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1693 args[0], 0, args[1], SHIFT_IMM_LSL(0));
1694 break;
1695 case INDEX_op_movi_i32:
1696 tcg_out_movi32(s, COND_AL, args[0], args[1]);
1697 break;
1698 case INDEX_op_movcond_i32:
1699 /* Constraints mean that v2 is always in the same register as dest,
1700 * so we only need to do "if condition passed, move v1 to dest".
1702 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1703 args[1], args[2], const_args[2]);
1704 tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
1705 ARITH_MVN, args[0], 0, args[3], const_args[3]);
1706 break;
1707 case INDEX_op_add_i32:
1708 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
1709 args[0], args[1], args[2], const_args[2]);
1710 break;
1711 case INDEX_op_sub_i32:
1712 if (const_args[1]) {
1713 if (const_args[2]) {
1714 tcg_out_movi32(s, COND_AL, args[0], args[1] - args[2]);
1715 } else {
1716 tcg_out_dat_rI(s, COND_AL, ARITH_RSB,
1717 args[0], args[2], args[1], 1);
1719 } else {
1720 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
1721 args[0], args[1], args[2], const_args[2]);
1723 break;
1724 case INDEX_op_and_i32:
1725 tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
1726 args[0], args[1], args[2], const_args[2]);
1727 break;
1728 case INDEX_op_andc_i32:
1729 tcg_out_dat_rIK(s, COND_AL, ARITH_BIC, ARITH_AND,
1730 args[0], args[1], args[2], const_args[2]);
1731 break;
1732 case INDEX_op_or_i32:
1733 c = ARITH_ORR;
1734 goto gen_arith;
1735 case INDEX_op_xor_i32:
1736 c = ARITH_EOR;
1737 /* Fall through. */
1738 gen_arith:
1739 tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]);
1740 break;
1741 case INDEX_op_add2_i32:
1742 a0 = args[0], a1 = args[1], a2 = args[2];
1743 a3 = args[3], a4 = args[4], a5 = args[5];
1744 if (a0 == a3 || (a0 == a5 && !const_args[5])) {
1745 a0 = TCG_REG_TMP;
1747 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
1748 a0, a2, a4, const_args[4]);
1749 tcg_out_dat_rIK(s, COND_AL, ARITH_ADC, ARITH_SBC,
1750 a1, a3, a5, const_args[5]);
1751 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1752 break;
1753 case INDEX_op_sub2_i32:
1754 a0 = args[0], a1 = args[1], a2 = args[2];
1755 a3 = args[3], a4 = args[4], a5 = args[5];
1756 if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
1757 a0 = TCG_REG_TMP;
1759 if (const_args[2]) {
1760 if (const_args[4]) {
1761 tcg_out_movi32(s, COND_AL, a0, a4);
1762 a4 = a0;
1764 tcg_out_dat_rI(s, COND_AL, ARITH_RSB | TO_CPSR, a0, a4, a2, 1);
1765 } else {
1766 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB | TO_CPSR,
1767 ARITH_ADD | TO_CPSR, a0, a2, a4, const_args[4]);
1769 if (const_args[3]) {
1770 if (const_args[5]) {
1771 tcg_out_movi32(s, COND_AL, a1, a5);
1772 a5 = a1;
1774 tcg_out_dat_rI(s, COND_AL, ARITH_RSC, a1, a5, a3, 1);
1775 } else {
1776 tcg_out_dat_rIK(s, COND_AL, ARITH_SBC, ARITH_ADC,
1777 a1, a3, a5, const_args[5]);
1779 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1780 break;
1781 case INDEX_op_neg_i32:
1782 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1783 break;
1784 case INDEX_op_not_i32:
1785 tcg_out_dat_reg(s, COND_AL,
1786 ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1787 break;
1788 case INDEX_op_mul_i32:
1789 tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1790 break;
1791 case INDEX_op_mulu2_i32:
1792 tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1793 break;
1794 case INDEX_op_muls2_i32:
1795 tcg_out_smull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1796 break;
1797 /* XXX: Perhaps args[2] & 0x1f is wrong */
1798 case INDEX_op_shl_i32:
1799 c = const_args[2] ?
1800 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1801 goto gen_shift32;
1802 case INDEX_op_shr_i32:
1803 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1804 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1805 goto gen_shift32;
1806 case INDEX_op_sar_i32:
1807 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1808 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1809 goto gen_shift32;
1810 case INDEX_op_rotr_i32:
1811 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1812 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1813 /* Fall through. */
1814 gen_shift32:
1815 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1816 break;
1818 case INDEX_op_rotl_i32:
1819 if (const_args[2]) {
1820 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1821 ((0x20 - args[2]) & 0x1f) ?
1822 SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1823 SHIFT_IMM_LSL(0));
1824 } else {
1825 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[1], 0x20);
1826 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1827 SHIFT_REG_ROR(TCG_REG_TMP));
1829 break;
1831 case INDEX_op_brcond_i32:
1832 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1833 args[0], args[1], const_args[1]);
1834 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
1835 break;
1836 case INDEX_op_brcond2_i32:
1837 /* The resulting conditions are:
1838 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1839 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1840 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1841 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1842 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1843 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1845 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1846 args[1], args[3], const_args[3]);
1847 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1848 args[0], args[2], const_args[2]);
1849 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
1850 break;
1851 case INDEX_op_setcond_i32:
1852 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1853 args[1], args[2], const_args[2]);
1854 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1855 ARITH_MOV, args[0], 0, 1);
1856 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1857 ARITH_MOV, args[0], 0, 0);
1858 break;
1859 case INDEX_op_setcond2_i32:
1860 /* See brcond2_i32 comment */
1861 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1862 args[2], args[4], const_args[4]);
1863 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1864 args[1], args[3], const_args[3]);
1865 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1866 ARITH_MOV, args[0], 0, 1);
1867 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1868 ARITH_MOV, args[0], 0, 0);
1869 break;
1871 case INDEX_op_qemu_ld8u:
1872 tcg_out_qemu_ld(s, args, 0);
1873 break;
1874 case INDEX_op_qemu_ld8s:
1875 tcg_out_qemu_ld(s, args, 0 | 4);
1876 break;
1877 case INDEX_op_qemu_ld16u:
1878 tcg_out_qemu_ld(s, args, 1);
1879 break;
1880 case INDEX_op_qemu_ld16s:
1881 tcg_out_qemu_ld(s, args, 1 | 4);
1882 break;
1883 case INDEX_op_qemu_ld32:
1884 tcg_out_qemu_ld(s, args, 2);
1885 break;
1886 case INDEX_op_qemu_ld64:
1887 tcg_out_qemu_ld(s, args, 3);
1888 break;
1890 case INDEX_op_qemu_st8:
1891 tcg_out_qemu_st(s, args, 0);
1892 break;
1893 case INDEX_op_qemu_st16:
1894 tcg_out_qemu_st(s, args, 1);
1895 break;
1896 case INDEX_op_qemu_st32:
1897 tcg_out_qemu_st(s, args, 2);
1898 break;
1899 case INDEX_op_qemu_st64:
1900 tcg_out_qemu_st(s, args, 3);
1901 break;
1903 case INDEX_op_bswap16_i32:
1904 tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1905 break;
1906 case INDEX_op_bswap32_i32:
1907 tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1908 break;
1910 case INDEX_op_ext8s_i32:
1911 tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1912 break;
1913 case INDEX_op_ext16s_i32:
1914 tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1915 break;
1916 case INDEX_op_ext16u_i32:
1917 tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1918 break;
1920 case INDEX_op_deposit_i32:
1921 tcg_out_deposit(s, COND_AL, args[0], args[2],
1922 args[3], args[4], const_args[2]);
1923 break;
1925 case INDEX_op_div_i32:
1926 tcg_out_sdiv(s, COND_AL, args[0], args[1], args[2]);
1927 break;
1928 case INDEX_op_divu_i32:
1929 tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
1930 break;
1931 case INDEX_op_rem_i32:
1932 tcg_out_sdiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
1933 tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
1934 tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
1935 SHIFT_IMM_LSL(0));
1936 break;
1937 case INDEX_op_remu_i32:
1938 tcg_out_udiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]);
1939 tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]);
1940 tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP,
1941 SHIFT_IMM_LSL(0));
1942 break;
1944 default:
1945 tcg_abort();
1949 #ifdef CONFIG_SOFTMMU
1950 /* Generate TB finalization at the end of block. */
1951 void tcg_out_tb_finalize(TCGContext *s)
1953 int i;
1954 for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
1955 TCGLabelQemuLdst *label = &s->qemu_ldst_labels[i];
1956 if (label->is_ld) {
1957 tcg_out_qemu_ld_slow_path(s, label);
1958 } else {
1959 tcg_out_qemu_st_slow_path(s, label);
1963 #endif /* SOFTMMU */
1965 static const TCGTargetOpDef arm_op_defs[] = {
1966 { INDEX_op_exit_tb, { } },
1967 { INDEX_op_goto_tb, { } },
1968 { INDEX_op_call, { "ri" } },
1969 { INDEX_op_br, { } },
1971 { INDEX_op_mov_i32, { "r", "r" } },
1972 { INDEX_op_movi_i32, { "r" } },
1974 { INDEX_op_ld8u_i32, { "r", "r" } },
1975 { INDEX_op_ld8s_i32, { "r", "r" } },
1976 { INDEX_op_ld16u_i32, { "r", "r" } },
1977 { INDEX_op_ld16s_i32, { "r", "r" } },
1978 { INDEX_op_ld_i32, { "r", "r" } },
1979 { INDEX_op_st8_i32, { "r", "r" } },
1980 { INDEX_op_st16_i32, { "r", "r" } },
1981 { INDEX_op_st_i32, { "r", "r" } },
1983 /* TODO: "r", "r", "ri" */
1984 { INDEX_op_add_i32, { "r", "r", "rIN" } },
1985 { INDEX_op_sub_i32, { "r", "rI", "rIN" } },
1986 { INDEX_op_mul_i32, { "r", "r", "r" } },
1987 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1988 { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
1989 { INDEX_op_and_i32, { "r", "r", "rIK" } },
1990 { INDEX_op_andc_i32, { "r", "r", "rIK" } },
1991 { INDEX_op_or_i32, { "r", "r", "rI" } },
1992 { INDEX_op_xor_i32, { "r", "r", "rI" } },
1993 { INDEX_op_neg_i32, { "r", "r" } },
1994 { INDEX_op_not_i32, { "r", "r" } },
1996 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1997 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1998 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1999 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
2000 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
2002 { INDEX_op_brcond_i32, { "r", "rIN" } },
2003 { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
2004 { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
2006 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
2007 { INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
2008 { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
2009 { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
2011 #if TARGET_LONG_BITS == 32
2012 { INDEX_op_qemu_ld8u, { "r", "l" } },
2013 { INDEX_op_qemu_ld8s, { "r", "l" } },
2014 { INDEX_op_qemu_ld16u, { "r", "l" } },
2015 { INDEX_op_qemu_ld16s, { "r", "l" } },
2016 { INDEX_op_qemu_ld32, { "r", "l" } },
2017 { INDEX_op_qemu_ld64, { "L", "L", "l" } },
2019 { INDEX_op_qemu_st8, { "s", "s" } },
2020 { INDEX_op_qemu_st16, { "s", "s" } },
2021 { INDEX_op_qemu_st32, { "s", "s" } },
2022 { INDEX_op_qemu_st64, { "s", "s", "s" } },
2023 #else
2024 { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
2025 { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
2026 { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
2027 { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
2028 { INDEX_op_qemu_ld32, { "r", "l", "l" } },
2029 { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
2031 { INDEX_op_qemu_st8, { "s", "s", "s" } },
2032 { INDEX_op_qemu_st16, { "s", "s", "s" } },
2033 { INDEX_op_qemu_st32, { "s", "s", "s" } },
2034 { INDEX_op_qemu_st64, { "s", "s", "s", "s" } },
2035 #endif
2037 { INDEX_op_bswap16_i32, { "r", "r" } },
2038 { INDEX_op_bswap32_i32, { "r", "r" } },
2040 { INDEX_op_ext8s_i32, { "r", "r" } },
2041 { INDEX_op_ext16s_i32, { "r", "r" } },
2042 { INDEX_op_ext16u_i32, { "r", "r" } },
2044 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
2046 #if TCG_TARGET_HAS_div_i32
2047 { INDEX_op_div_i32, { "r", "r", "r" } },
2048 { INDEX_op_rem_i32, { "r", "r", "r" } },
2049 { INDEX_op_divu_i32, { "r", "r", "r" } },
2050 { INDEX_op_remu_i32, { "r", "r", "r" } },
2051 #endif
2053 { -1 },
2056 static void tcg_target_init(TCGContext *s)
2058 #if !defined(CONFIG_USER_ONLY)
2059 /* fail safe */
2060 if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
2061 tcg_abort();
2062 #endif
2064 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
2065 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
2066 (1 << TCG_REG_R0) |
2067 (1 << TCG_REG_R1) |
2068 (1 << TCG_REG_R2) |
2069 (1 << TCG_REG_R3) |
2070 (1 << TCG_REG_R12) |
2071 (1 << TCG_REG_R14));
2073 tcg_regset_clear(s->reserved_regs);
2074 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
2075 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
2076 tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
2078 tcg_add_target_add_op_defs(arm_op_defs);
2081 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
2082 TCGReg arg1, tcg_target_long arg2)
2084 tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
2087 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
2088 TCGReg arg1, tcg_target_long arg2)
2090 tcg_out_st32(s, COND_AL, arg, arg1, arg2);
2093 static inline void tcg_out_mov(TCGContext *s, TCGType type,
2094 TCGReg ret, TCGReg arg)
2096 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
2099 static inline void tcg_out_movi(TCGContext *s, TCGType type,
2100 TCGReg ret, tcg_target_long arg)
2102 tcg_out_movi32(s, COND_AL, ret, arg);
2105 static void tcg_target_qemu_prologue(TCGContext *s)
2107 int frame_size;
2109 /* Calling convention requires us to save r4-r11 and lr. */
2110 /* stmdb sp!, { r4 - r11, lr } */
2111 tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
2113 /* Allocate the local stack frame. */
2114 frame_size = TCG_STATIC_CALL_ARGS_SIZE;
2115 frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
2116 /* We saved an odd number of registers above; keep an 8 aligned stack. */
2117 frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
2118 & -TCG_TARGET_STACK_ALIGN) + 4;
2120 tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
2121 TCG_REG_CALL_STACK, frame_size, 1);
2122 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
2123 CPU_TEMP_BUF_NLONGS * sizeof(long));
2125 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2127 tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
2128 tb_ret_addr = s->code_ptr;
2130 /* Epilogue. We branch here via tb_ret_addr. */
2131 tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
2132 TCG_REG_CALL_STACK, frame_size, 1);
2134 /* ldmia sp!, { r4 - r11, pc } */
2135 tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);