s390x/cpu: Use ioctl to reset state in the kernel
[qemu/kevin.git] / tcg / arm / tcg-target.c
blobc8884b31f4fb9cded96095ff41970eeb78f0512b
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 #include "elf.h"
26 #include "tcg-be-ldst.h"
28 /* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
29 #ifndef __ARM_ARCH
30 # if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
31 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
32 || defined(__ARM_ARCH_7EM__)
33 # define __ARM_ARCH 7
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__)
37 # define __ARM_ARCH 6
38 # elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
39 || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
40 || defined(__ARM_ARCH_5TEJ__)
41 # define __ARM_ARCH 5
42 # else
43 # define __ARM_ARCH 4
44 # endif
45 #endif
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
52 #else
53 # define use_armv5t_instructions use_armv6_instructions
54 #endif
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;
61 #endif
63 #ifndef NDEBUG
64 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
65 "%r0",
66 "%r1",
67 "%r2",
68 "%r3",
69 "%r4",
70 "%r5",
71 "%r6",
72 "%r7",
73 "%r8",
74 "%r9",
75 "%r10",
76 "%r11",
77 "%r12",
78 "%r13",
79 "%r14",
80 "%pc",
82 #endif
84 static const int tcg_target_reg_alloc_order[] = {
85 TCG_REG_R4,
86 TCG_REG_R5,
87 TCG_REG_R6,
88 TCG_REG_R7,
89 TCG_REG_R8,
90 TCG_REG_R9,
91 TCG_REG_R10,
92 TCG_REG_R11,
93 TCG_REG_R13,
94 TCG_REG_R0,
95 TCG_REG_R1,
96 TCG_REG_R2,
97 TCG_REG_R3,
98 TCG_REG_R12,
99 TCG_REG_R14,
102 static const int tcg_target_call_iarg_regs[4] = {
103 TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
105 static const int tcg_target_call_oarg_regs[2] = {
106 TCG_REG_R0, TCG_REG_R1
109 #define TCG_REG_TMP TCG_REG_R12
111 static inline void reloc_abs32(void *code_ptr, intptr_t target)
113 *(uint32_t *) code_ptr = target;
116 static inline void reloc_pc24(void *code_ptr, intptr_t target)
118 uint32_t offset = ((target - ((intptr_t)code_ptr + 8)) >> 2);
120 *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
121 | (offset & 0xffffff);
124 static void patch_reloc(uint8_t *code_ptr, int type,
125 intptr_t value, intptr_t addend)
127 switch (type) {
128 case R_ARM_ABS32:
129 reloc_abs32(code_ptr, value);
130 break;
132 case R_ARM_CALL:
133 case R_ARM_JUMP24:
134 default:
135 tcg_abort();
137 case R_ARM_PC24:
138 reloc_pc24(code_ptr, value);
139 break;
143 #define TCG_CT_CONST_ARM 0x100
144 #define TCG_CT_CONST_INV 0x200
145 #define TCG_CT_CONST_NEG 0x400
146 #define TCG_CT_CONST_ZERO 0x800
148 /* parse target specific constraints */
149 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
151 const char *ct_str;
153 ct_str = *pct_str;
154 switch (ct_str[0]) {
155 case 'I':
156 ct->ct |= TCG_CT_CONST_ARM;
157 break;
158 case 'K':
159 ct->ct |= TCG_CT_CONST_INV;
160 break;
161 case 'N': /* The gcc constraint letter is L, already used here. */
162 ct->ct |= TCG_CT_CONST_NEG;
163 break;
164 case 'Z':
165 ct->ct |= TCG_CT_CONST_ZERO;
166 break;
168 case 'r':
169 ct->ct |= TCG_CT_REG;
170 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
171 break;
173 /* qemu_ld address */
174 case 'l':
175 ct->ct |= TCG_CT_REG;
176 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
177 #ifdef CONFIG_SOFTMMU
178 /* r0-r2,lr will be overwritten when reading the tlb entry,
179 so don't use these. */
180 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
181 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
182 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
183 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
184 #endif
185 break;
187 /* qemu_st address & data */
188 case 's':
189 ct->ct |= TCG_CT_REG;
190 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
191 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
192 and r0-r1 doing the byte swapping, so don't use these. */
193 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
194 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
195 #if defined(CONFIG_SOFTMMU)
196 /* Avoid clashes with registers being used for helper args */
197 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
198 #if TARGET_LONG_BITS == 64
199 /* Avoid clashes with registers being used for helper args */
200 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
201 #endif
202 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
203 #endif
204 break;
206 default:
207 return -1;
209 ct_str++;
210 *pct_str = ct_str;
212 return 0;
215 static inline uint32_t rotl(uint32_t val, int n)
217 return (val << n) | (val >> (32 - n));
220 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
221 right-rotated by an even amount between 0 and 30. */
222 static inline int encode_imm(uint32_t imm)
224 int shift;
226 /* simple case, only lower bits */
227 if ((imm & ~0xff) == 0)
228 return 0;
229 /* then try a simple even shift */
230 shift = ctz32(imm) & ~1;
231 if (((imm >> shift) & ~0xff) == 0)
232 return 32 - shift;
233 /* now try harder with rotations */
234 if ((rotl(imm, 2) & ~0xff) == 0)
235 return 2;
236 if ((rotl(imm, 4) & ~0xff) == 0)
237 return 4;
238 if ((rotl(imm, 6) & ~0xff) == 0)
239 return 6;
240 /* imm can't be encoded */
241 return -1;
244 static inline int check_fit_imm(uint32_t imm)
246 return encode_imm(imm) >= 0;
249 /* Test if a constant matches the constraint.
250 * TODO: define constraints for:
252 * ldr/str offset: between -0xfff and 0xfff
253 * ldrh/strh offset: between -0xff and 0xff
254 * mov operand2: values represented with x << (2 * y), x < 0x100
255 * add, sub, eor...: ditto
257 static inline int tcg_target_const_match(tcg_target_long val,
258 const TCGArgConstraint *arg_ct)
260 int ct;
261 ct = arg_ct->ct;
262 if (ct & TCG_CT_CONST) {
263 return 1;
264 } else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
265 return 1;
266 } else if ((ct & TCG_CT_CONST_INV) && check_fit_imm(~val)) {
267 return 1;
268 } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
269 return 1;
270 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
271 return 1;
272 } else {
273 return 0;
277 #define TO_CPSR (1 << 20)
279 typedef enum {
280 ARITH_AND = 0x0 << 21,
281 ARITH_EOR = 0x1 << 21,
282 ARITH_SUB = 0x2 << 21,
283 ARITH_RSB = 0x3 << 21,
284 ARITH_ADD = 0x4 << 21,
285 ARITH_ADC = 0x5 << 21,
286 ARITH_SBC = 0x6 << 21,
287 ARITH_RSC = 0x7 << 21,
288 ARITH_TST = 0x8 << 21 | TO_CPSR,
289 ARITH_CMP = 0xa << 21 | TO_CPSR,
290 ARITH_CMN = 0xb << 21 | TO_CPSR,
291 ARITH_ORR = 0xc << 21,
292 ARITH_MOV = 0xd << 21,
293 ARITH_BIC = 0xe << 21,
294 ARITH_MVN = 0xf << 21,
296 INSN_LDR_IMM = 0x04100000,
297 INSN_LDR_REG = 0x06100000,
298 INSN_STR_IMM = 0x04000000,
299 INSN_STR_REG = 0x06000000,
301 INSN_LDRH_IMM = 0x005000b0,
302 INSN_LDRH_REG = 0x001000b0,
303 INSN_LDRSH_IMM = 0x005000f0,
304 INSN_LDRSH_REG = 0x001000f0,
305 INSN_STRH_IMM = 0x004000b0,
306 INSN_STRH_REG = 0x000000b0,
308 INSN_LDRB_IMM = 0x04500000,
309 INSN_LDRB_REG = 0x06500000,
310 INSN_LDRSB_IMM = 0x005000d0,
311 INSN_LDRSB_REG = 0x001000d0,
312 INSN_STRB_IMM = 0x04400000,
313 INSN_STRB_REG = 0x06400000,
315 INSN_LDRD_IMM = 0x004000d0,
316 INSN_LDRD_REG = 0x000000d0,
317 INSN_STRD_IMM = 0x004000f0,
318 INSN_STRD_REG = 0x000000f0,
319 } ARMInsn;
321 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
322 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
323 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
324 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
325 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
326 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
327 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
328 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
330 enum arm_cond_code_e {
331 COND_EQ = 0x0,
332 COND_NE = 0x1,
333 COND_CS = 0x2, /* Unsigned greater or equal */
334 COND_CC = 0x3, /* Unsigned less than */
335 COND_MI = 0x4, /* Negative */
336 COND_PL = 0x5, /* Zero or greater */
337 COND_VS = 0x6, /* Overflow */
338 COND_VC = 0x7, /* No overflow */
339 COND_HI = 0x8, /* Unsigned greater than */
340 COND_LS = 0x9, /* Unsigned less or equal */
341 COND_GE = 0xa,
342 COND_LT = 0xb,
343 COND_GT = 0xc,
344 COND_LE = 0xd,
345 COND_AL = 0xe,
348 static const uint8_t tcg_cond_to_arm_cond[] = {
349 [TCG_COND_EQ] = COND_EQ,
350 [TCG_COND_NE] = COND_NE,
351 [TCG_COND_LT] = COND_LT,
352 [TCG_COND_GE] = COND_GE,
353 [TCG_COND_LE] = COND_LE,
354 [TCG_COND_GT] = COND_GT,
355 /* unsigned */
356 [TCG_COND_LTU] = COND_CC,
357 [TCG_COND_GEU] = COND_CS,
358 [TCG_COND_LEU] = COND_LS,
359 [TCG_COND_GTU] = COND_HI,
362 static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
364 tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
367 static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
369 tcg_out32(s, (cond << 28) | 0x0a000000 |
370 (((offset - 8) >> 2) & 0x00ffffff));
373 static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
375 /* We pay attention here to not modify the branch target by skipping
376 the corresponding bytes. This ensure that caches and memory are
377 kept coherent during retranslation. */
378 s->code_ptr += 3;
379 tcg_out8(s, (cond << 4) | 0x0a);
382 static inline void tcg_out_bl_noaddr(TCGContext *s, int cond)
384 /* We pay attention here to not modify the branch target by skipping
385 the corresponding bytes. This ensure that caches and memory are
386 kept coherent during retranslation. */
387 s->code_ptr += 3;
388 tcg_out8(s, (cond << 4) | 0x0b);
391 static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
393 tcg_out32(s, (cond << 28) | 0x0b000000 |
394 (((offset - 8) >> 2) & 0x00ffffff));
397 static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
399 tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
402 static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
404 tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
405 (((offset - 8) >> 2) & 0x00ffffff));
408 static inline void tcg_out_dat_reg(TCGContext *s,
409 int cond, int opc, int rd, int rn, int rm, int shift)
411 tcg_out32(s, (cond << 28) | (0 << 25) | opc |
412 (rn << 16) | (rd << 12) | shift | rm);
415 static inline void tcg_out_nop(TCGContext *s)
417 if (use_armv7_instructions) {
418 /* Architected nop introduced in v6k. */
419 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
420 also Just So Happened to do nothing on pre-v6k so that we
421 don't need to conditionalize it? */
422 tcg_out32(s, 0xe320f000);
423 } else {
424 /* Prior to that the assembler uses mov r0, r0. */
425 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 0, 0, 0, SHIFT_IMM_LSL(0));
429 static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
431 /* Simple reg-reg move, optimising out the 'do nothing' case */
432 if (rd != rm) {
433 tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, rm, SHIFT_IMM_LSL(0));
437 static inline void tcg_out_dat_imm(TCGContext *s,
438 int cond, int opc, int rd, int rn, int im)
440 tcg_out32(s, (cond << 28) | (1 << 25) | opc |
441 (rn << 16) | (rd << 12) | im);
444 static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
446 int rot, opc, rn;
448 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
449 Speed things up by only checking when movt would be required.
450 Prior to armv7, have one go at fully rotated immediates before
451 doing the decomposition thing below. */
452 if (!use_armv7_instructions || (arg & 0xffff0000)) {
453 rot = encode_imm(arg);
454 if (rot >= 0) {
455 tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
456 rotl(arg, rot) | (rot << 7));
457 return;
459 rot = encode_imm(~arg);
460 if (rot >= 0) {
461 tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
462 rotl(~arg, rot) | (rot << 7));
463 return;
467 /* Use movw + movt. */
468 if (use_armv7_instructions) {
469 /* movw */
470 tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
471 | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
472 if (arg & 0xffff0000) {
473 /* movt */
474 tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
475 | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
477 return;
480 /* TODO: This is very suboptimal, we can easily have a constant
481 pool somewhere after all the instructions. */
482 opc = ARITH_MOV;
483 rn = 0;
484 /* If we have lots of leading 1's, we can shorten the sequence by
485 beginning with mvn and then clearing higher bits with eor. */
486 if (clz32(~arg) > clz32(arg)) {
487 opc = ARITH_MVN, arg = ~arg;
489 do {
490 int i = ctz32(arg) & ~1;
491 rot = ((32 - i) << 7) & 0xf00;
492 tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
493 arg &= ~(0xff << i);
495 opc = ARITH_EOR;
496 rn = rd;
497 } while (arg);
500 static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
501 TCGArg lhs, TCGArg rhs, int rhs_is_const)
503 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
504 * rhs must satisfy the "rI" constraint.
506 if (rhs_is_const) {
507 int rot = encode_imm(rhs);
508 assert(rot >= 0);
509 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
510 } else {
511 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
515 static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
516 TCGReg dst, TCGReg lhs, TCGArg rhs,
517 bool rhs_is_const)
519 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
520 * rhs must satisfy the "rIK" constraint.
522 if (rhs_is_const) {
523 int rot = encode_imm(rhs);
524 if (rot < 0) {
525 rhs = ~rhs;
526 rot = encode_imm(rhs);
527 assert(rot >= 0);
528 opc = opinv;
530 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
531 } else {
532 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
536 static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
537 TCGArg dst, TCGArg lhs, TCGArg rhs,
538 bool rhs_is_const)
540 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
541 * rhs must satisfy the "rIN" constraint.
543 if (rhs_is_const) {
544 int rot = encode_imm(rhs);
545 if (rot < 0) {
546 rhs = -rhs;
547 rot = encode_imm(rhs);
548 assert(rot >= 0);
549 opc = opneg;
551 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
552 } else {
553 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
557 static inline void tcg_out_mul32(TCGContext *s, int cond, TCGReg rd,
558 TCGReg rn, TCGReg rm)
560 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
561 if (!use_armv6_instructions && rd == rn) {
562 if (rd == rm) {
563 /* rd == rn == rm; copy an input to tmp first. */
564 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
565 rm = rn = TCG_REG_TMP;
566 } else {
567 rn = rm;
568 rm = rd;
571 /* mul */
572 tcg_out32(s, (cond << 28) | 0x90 | (rd << 16) | (rm << 8) | rn);
575 static inline void tcg_out_umull32(TCGContext *s, int cond, TCGReg rd0,
576 TCGReg rd1, TCGReg rn, TCGReg rm)
578 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
579 if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
580 if (rd0 == rm || rd1 == rm) {
581 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
582 rn = TCG_REG_TMP;
583 } else {
584 TCGReg t = rn;
585 rn = rm;
586 rm = t;
589 /* umull */
590 tcg_out32(s, (cond << 28) | 0x00800090 |
591 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
594 static inline void tcg_out_smull32(TCGContext *s, int cond, TCGReg rd0,
595 TCGReg rd1, TCGReg rn, TCGReg rm)
597 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
598 if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
599 if (rd0 == rm || rd1 == rm) {
600 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
601 rn = TCG_REG_TMP;
602 } else {
603 TCGReg t = rn;
604 rn = rm;
605 rm = t;
608 /* smull */
609 tcg_out32(s, (cond << 28) | 0x00c00090 |
610 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
613 static inline void tcg_out_sdiv(TCGContext *s, int cond, int rd, int rn, int rm)
615 tcg_out32(s, 0x0710f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
618 static inline void tcg_out_udiv(TCGContext *s, int cond, int rd, int rn, int rm)
620 tcg_out32(s, 0x0730f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
623 static inline void tcg_out_ext8s(TCGContext *s, int cond,
624 int rd, int rn)
626 if (use_armv6_instructions) {
627 /* sxtb */
628 tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
629 } else {
630 tcg_out_dat_reg(s, cond, ARITH_MOV,
631 rd, 0, rn, SHIFT_IMM_LSL(24));
632 tcg_out_dat_reg(s, cond, ARITH_MOV,
633 rd, 0, rd, SHIFT_IMM_ASR(24));
637 static inline void tcg_out_ext8u(TCGContext *s, int cond,
638 int rd, int rn)
640 tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
643 static inline void tcg_out_ext16s(TCGContext *s, int cond,
644 int rd, int rn)
646 if (use_armv6_instructions) {
647 /* sxth */
648 tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
649 } else {
650 tcg_out_dat_reg(s, cond, ARITH_MOV,
651 rd, 0, rn, SHIFT_IMM_LSL(16));
652 tcg_out_dat_reg(s, cond, ARITH_MOV,
653 rd, 0, rd, SHIFT_IMM_ASR(16));
657 static inline void tcg_out_ext16u(TCGContext *s, int cond,
658 int rd, int rn)
660 if (use_armv6_instructions) {
661 /* uxth */
662 tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
663 } else {
664 tcg_out_dat_reg(s, cond, ARITH_MOV,
665 rd, 0, rn, SHIFT_IMM_LSL(16));
666 tcg_out_dat_reg(s, cond, ARITH_MOV,
667 rd, 0, rd, SHIFT_IMM_LSR(16));
671 static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
673 if (use_armv6_instructions) {
674 /* revsh */
675 tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
676 } else {
677 tcg_out_dat_reg(s, cond, ARITH_MOV,
678 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
679 tcg_out_dat_reg(s, cond, ARITH_MOV,
680 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_ASR(16));
681 tcg_out_dat_reg(s, cond, ARITH_ORR,
682 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
686 static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
688 if (use_armv6_instructions) {
689 /* rev16 */
690 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
691 } else {
692 tcg_out_dat_reg(s, cond, ARITH_MOV,
693 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
694 tcg_out_dat_reg(s, cond, ARITH_MOV,
695 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_LSR(16));
696 tcg_out_dat_reg(s, cond, ARITH_ORR,
697 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
701 /* swap the two low bytes assuming that the two high input bytes and the
702 two high output bit can hold any value. */
703 static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
705 if (use_armv6_instructions) {
706 /* rev16 */
707 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
708 } else {
709 tcg_out_dat_reg(s, cond, ARITH_MOV,
710 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSR(8));
711 tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, 0xff);
712 tcg_out_dat_reg(s, cond, ARITH_ORR,
713 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSL(8));
717 static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
719 if (use_armv6_instructions) {
720 /* rev */
721 tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
722 } else {
723 tcg_out_dat_reg(s, cond, ARITH_EOR,
724 TCG_REG_TMP, rn, rn, SHIFT_IMM_ROR(16));
725 tcg_out_dat_imm(s, cond, ARITH_BIC,
726 TCG_REG_TMP, TCG_REG_TMP, 0xff | 0x800);
727 tcg_out_dat_reg(s, cond, ARITH_MOV,
728 rd, 0, rn, SHIFT_IMM_ROR(8));
729 tcg_out_dat_reg(s, cond, ARITH_EOR,
730 rd, rd, TCG_REG_TMP, SHIFT_IMM_LSR(8));
734 bool tcg_target_deposit_valid(int ofs, int len)
736 /* ??? Without bfi, we could improve over generic code by combining
737 the right-shift from a non-zero ofs with the orr. We do run into
738 problems when rd == rs, and the mask generated from ofs+len doesn't
739 fit into an immediate. We would have to be careful not to pessimize
740 wrt the optimizations performed on the expanded code. */
741 return use_armv7_instructions;
744 static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd,
745 TCGArg a1, int ofs, int len, bool const_a1)
747 if (const_a1) {
748 /* bfi becomes bfc with rn == 15. */
749 a1 = 15;
751 /* bfi/bfc */
752 tcg_out32(s, 0x07c00010 | (cond << 28) | (rd << 12) | a1
753 | (ofs << 7) | ((ofs + len - 1) << 16));
756 /* Note that this routine is used for both LDR and LDRH formats, so we do
757 not wish to include an immediate shift at this point. */
758 static void tcg_out_memop_r(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
759 TCGReg rn, TCGReg rm, bool u, bool p, bool w)
761 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24)
762 | (w << 21) | (rn << 16) | (rt << 12) | rm);
765 static void tcg_out_memop_8(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
766 TCGReg rn, int imm8, bool p, bool w)
768 bool u = 1;
769 if (imm8 < 0) {
770 imm8 = -imm8;
771 u = 0;
773 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
774 (rn << 16) | (rt << 12) | ((imm8 & 0xf0) << 4) | (imm8 & 0xf));
777 static void tcg_out_memop_12(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
778 TCGReg rn, int imm12, bool p, bool w)
780 bool u = 1;
781 if (imm12 < 0) {
782 imm12 = -imm12;
783 u = 0;
785 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
786 (rn << 16) | (rt << 12) | imm12);
789 static inline void tcg_out_ld32_12(TCGContext *s, int cond, TCGReg rt,
790 TCGReg rn, int imm12)
792 tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 0);
795 static inline void tcg_out_st32_12(TCGContext *s, int cond, TCGReg rt,
796 TCGReg rn, int imm12)
798 tcg_out_memop_12(s, cond, INSN_STR_IMM, rt, rn, imm12, 1, 0);
801 static inline void tcg_out_ld32_r(TCGContext *s, int cond, TCGReg rt,
802 TCGReg rn, TCGReg rm)
804 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 0);
807 static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt,
808 TCGReg rn, TCGReg rm)
810 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0);
813 static inline void tcg_out_ldrd_8(TCGContext *s, int cond, TCGReg rt,
814 TCGReg rn, int imm8)
816 tcg_out_memop_8(s, cond, INSN_LDRD_IMM, rt, rn, imm8, 1, 0);
819 static inline void tcg_out_ldrd_r(TCGContext *s, int cond, TCGReg rt,
820 TCGReg rn, TCGReg rm)
822 tcg_out_memop_r(s, cond, INSN_LDRD_REG, rt, rn, rm, 1, 1, 0);
825 static inline void tcg_out_strd_8(TCGContext *s, int cond, TCGReg rt,
826 TCGReg rn, int imm8)
828 tcg_out_memop_8(s, cond, INSN_STRD_IMM, rt, rn, imm8, 1, 0);
831 static inline void tcg_out_strd_r(TCGContext *s, int cond, TCGReg rt,
832 TCGReg rn, TCGReg rm)
834 tcg_out_memop_r(s, cond, INSN_STRD_REG, rt, rn, rm, 1, 1, 0);
837 /* Register pre-increment with base writeback. */
838 static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt,
839 TCGReg rn, TCGReg rm)
841 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 1);
844 static inline void tcg_out_st32_rwb(TCGContext *s, int cond, TCGReg rt,
845 TCGReg rn, TCGReg rm)
847 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 1);
850 static inline void tcg_out_ld16u_8(TCGContext *s, int cond, TCGReg rt,
851 TCGReg rn, int imm8)
853 tcg_out_memop_8(s, cond, INSN_LDRH_IMM, rt, rn, imm8, 1, 0);
856 static inline void tcg_out_st16_8(TCGContext *s, int cond, TCGReg rt,
857 TCGReg rn, int imm8)
859 tcg_out_memop_8(s, cond, INSN_STRH_IMM, rt, rn, imm8, 1, 0);
862 static inline void tcg_out_ld16u_r(TCGContext *s, int cond, TCGReg rt,
863 TCGReg rn, TCGReg rm)
865 tcg_out_memop_r(s, cond, INSN_LDRH_REG, rt, rn, rm, 1, 1, 0);
868 static inline void tcg_out_st16_r(TCGContext *s, int cond, TCGReg rt,
869 TCGReg rn, TCGReg rm)
871 tcg_out_memop_r(s, cond, INSN_STRH_REG, rt, rn, rm, 1, 1, 0);
874 static inline void tcg_out_ld16s_8(TCGContext *s, int cond, TCGReg rt,
875 TCGReg rn, int imm8)
877 tcg_out_memop_8(s, cond, INSN_LDRSH_IMM, rt, rn, imm8, 1, 0);
880 static inline void tcg_out_ld16s_r(TCGContext *s, int cond, TCGReg rt,
881 TCGReg rn, TCGReg rm)
883 tcg_out_memop_r(s, cond, INSN_LDRSH_REG, rt, rn, rm, 1, 1, 0);
886 static inline void tcg_out_ld8_12(TCGContext *s, int cond, TCGReg rt,
887 TCGReg rn, int imm12)
889 tcg_out_memop_12(s, cond, INSN_LDRB_IMM, rt, rn, imm12, 1, 0);
892 static inline void tcg_out_st8_12(TCGContext *s, int cond, TCGReg rt,
893 TCGReg rn, int imm12)
895 tcg_out_memop_12(s, cond, INSN_STRB_IMM, rt, rn, imm12, 1, 0);
898 static inline void tcg_out_ld8_r(TCGContext *s, int cond, TCGReg rt,
899 TCGReg rn, TCGReg rm)
901 tcg_out_memop_r(s, cond, INSN_LDRB_REG, rt, rn, rm, 1, 1, 0);
904 static inline void tcg_out_st8_r(TCGContext *s, int cond, TCGReg rt,
905 TCGReg rn, TCGReg rm)
907 tcg_out_memop_r(s, cond, INSN_STRB_REG, rt, rn, rm, 1, 1, 0);
910 static inline void tcg_out_ld8s_8(TCGContext *s, int cond, TCGReg rt,
911 TCGReg rn, int imm8)
913 tcg_out_memop_8(s, cond, INSN_LDRSB_IMM, rt, rn, imm8, 1, 0);
916 static inline void tcg_out_ld8s_r(TCGContext *s, int cond, TCGReg rt,
917 TCGReg rn, TCGReg rm)
919 tcg_out_memop_r(s, cond, INSN_LDRSB_REG, rt, rn, rm, 1, 1, 0);
922 static inline void tcg_out_ld32u(TCGContext *s, int cond,
923 int rd, int rn, int32_t offset)
925 if (offset > 0xfff || offset < -0xfff) {
926 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
927 tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_TMP);
928 } else
929 tcg_out_ld32_12(s, cond, rd, rn, offset);
932 static inline void tcg_out_st32(TCGContext *s, int cond,
933 int rd, int rn, int32_t offset)
935 if (offset > 0xfff || offset < -0xfff) {
936 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
937 tcg_out_st32_r(s, cond, rd, rn, TCG_REG_TMP);
938 } else
939 tcg_out_st32_12(s, cond, rd, rn, offset);
942 static inline void tcg_out_ld16u(TCGContext *s, int cond,
943 int rd, int rn, int32_t offset)
945 if (offset > 0xff || offset < -0xff) {
946 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
947 tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_TMP);
948 } else
949 tcg_out_ld16u_8(s, cond, rd, rn, offset);
952 static inline void tcg_out_ld16s(TCGContext *s, int cond,
953 int rd, int rn, int32_t offset)
955 if (offset > 0xff || offset < -0xff) {
956 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
957 tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_TMP);
958 } else
959 tcg_out_ld16s_8(s, cond, rd, rn, offset);
962 static inline void tcg_out_st16(TCGContext *s, int cond,
963 int rd, int rn, int32_t offset)
965 if (offset > 0xff || offset < -0xff) {
966 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
967 tcg_out_st16_r(s, cond, rd, rn, TCG_REG_TMP);
968 } else
969 tcg_out_st16_8(s, cond, rd, rn, offset);
972 static inline void tcg_out_ld8u(TCGContext *s, int cond,
973 int rd, int rn, int32_t offset)
975 if (offset > 0xfff || offset < -0xfff) {
976 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
977 tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_TMP);
978 } else
979 tcg_out_ld8_12(s, cond, rd, rn, offset);
982 static inline void tcg_out_ld8s(TCGContext *s, int cond,
983 int rd, int rn, int32_t offset)
985 if (offset > 0xff || offset < -0xff) {
986 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
987 tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_TMP);
988 } else
989 tcg_out_ld8s_8(s, cond, rd, rn, offset);
992 static inline void tcg_out_st8(TCGContext *s, int cond,
993 int rd, int rn, int32_t offset)
995 if (offset > 0xfff || offset < -0xfff) {
996 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
997 tcg_out_st8_r(s, cond, rd, rn, TCG_REG_TMP);
998 } else
999 tcg_out_st8_12(s, cond, rd, rn, offset);
1002 /* The _goto case is normally between TBs within the same code buffer, and
1003 * with the code buffer limited to 16MB we wouldn't need the long case.
1004 * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
1006 static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
1008 int32_t disp = addr - (tcg_target_long) s->code_ptr;
1010 if ((addr & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) {
1011 tcg_out_b(s, cond, disp);
1012 return;
1015 tcg_out_movi32(s, cond, TCG_REG_TMP, addr);
1016 if (use_armv5t_instructions) {
1017 tcg_out_bx(s, cond, TCG_REG_TMP);
1018 } else {
1019 if (addr & 1) {
1020 tcg_abort();
1022 tcg_out_mov_reg(s, cond, TCG_REG_PC, TCG_REG_TMP);
1026 /* The call case is mostly used for helpers - so it's not unreasonable
1027 * for them to be beyond branch range */
1028 static inline void tcg_out_call(TCGContext *s, uint32_t addr)
1030 int32_t val;
1032 val = addr - (tcg_target_long) s->code_ptr;
1033 if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
1034 if (addr & 1) {
1035 /* Use BLX if the target is in Thumb mode */
1036 if (!use_armv5t_instructions) {
1037 tcg_abort();
1039 tcg_out_blx_imm(s, val);
1040 } else {
1041 tcg_out_bl(s, COND_AL, val);
1043 } else if (use_armv7_instructions) {
1044 tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addr);
1045 tcg_out_blx(s, COND_AL, TCG_REG_TMP);
1046 } else {
1047 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
1048 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1049 tcg_out32(s, addr);
1053 static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
1055 if (use_armv5t_instructions) {
1056 tcg_out_blx(s, cond, arg);
1057 } else {
1058 tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
1059 TCG_REG_PC, SHIFT_IMM_LSL(0));
1060 tcg_out_bx(s, cond, arg);
1064 static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
1066 TCGLabel *l = &s->labels[label_index];
1068 if (l->has_value) {
1069 tcg_out_goto(s, cond, l->u.value);
1070 } else {
1071 tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
1072 tcg_out_b_noaddr(s, cond);
1076 #ifdef CONFIG_SOFTMMU
1077 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1078 * int mmu_idx, uintptr_t ra)
1080 static const void * const qemu_ld_helpers[16] = {
1081 [MO_UB] = helper_ret_ldub_mmu,
1082 [MO_SB] = helper_ret_ldsb_mmu,
1084 [MO_LEUW] = helper_le_lduw_mmu,
1085 [MO_LEUL] = helper_le_ldul_mmu,
1086 [MO_LEQ] = helper_le_ldq_mmu,
1087 [MO_LESW] = helper_le_ldsw_mmu,
1088 [MO_LESL] = helper_le_ldul_mmu,
1090 [MO_BEUW] = helper_be_lduw_mmu,
1091 [MO_BEUL] = helper_be_ldul_mmu,
1092 [MO_BEQ] = helper_be_ldq_mmu,
1093 [MO_BESW] = helper_be_ldsw_mmu,
1094 [MO_BESL] = helper_be_ldul_mmu,
1097 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1098 * uintxx_t val, int mmu_idx, uintptr_t ra)
1100 static const void * const qemu_st_helpers[16] = {
1101 [MO_UB] = helper_ret_stb_mmu,
1102 [MO_LEUW] = helper_le_stw_mmu,
1103 [MO_LEUL] = helper_le_stl_mmu,
1104 [MO_LEQ] = helper_le_stq_mmu,
1105 [MO_BEUW] = helper_be_stw_mmu,
1106 [MO_BEUL] = helper_be_stl_mmu,
1107 [MO_BEQ] = helper_be_stq_mmu,
1110 /* Helper routines for marshalling helper function arguments into
1111 * the correct registers and stack.
1112 * argreg is where we want to put this argument, arg is the argument itself.
1113 * Return value is the updated argreg ready for the next call.
1114 * Note that argreg 0..3 is real registers, 4+ on stack.
1116 * We provide routines for arguments which are: immediate, 32 bit
1117 * value in register, 16 and 8 bit values in register (which must be zero
1118 * extended before use) and 64 bit value in a lo:hi register pair.
1120 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1121 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1123 if (argreg < 4) { \
1124 MOV_ARG(s, COND_AL, argreg, arg); \
1125 } else { \
1126 int ofs = (argreg - 4) * 4; \
1127 EXT_ARG; \
1128 assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1129 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1131 return argreg + 1; \
1134 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
1135 (tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1136 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
1137 (tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1138 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
1139 (tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1140 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
1142 static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
1143 TCGReg arglo, TCGReg arghi)
1145 /* 64 bit arguments must go in even/odd register pairs
1146 * and in 8-aligned stack slots.
1148 if (argreg & 1) {
1149 argreg++;
1151 if (use_armv6_instructions && argreg >= 4
1152 && (arglo & 1) == 0 && arghi == arglo + 1) {
1153 tcg_out_strd_8(s, COND_AL, arglo,
1154 TCG_REG_CALL_STACK, (argreg - 4) * 4);
1155 return argreg + 2;
1156 } else {
1157 argreg = tcg_out_arg_reg32(s, argreg, arglo);
1158 argreg = tcg_out_arg_reg32(s, argreg, arghi);
1159 return argreg;
1163 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1165 /* We're expecting to use an 8-bit immediate and to mask. */
1166 QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
1168 /* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset.
1169 Using the offset of the second entry in the last tlb table ensures
1170 that we can index all of the elements of the first entry. */
1171 QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
1172 > 0xffff);
1174 /* Load and compare a TLB entry, leaving the flags set. Returns the register
1175 containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
1177 static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
1178 TCGMemOp s_bits, int mem_index, bool is_load)
1180 TCGReg base = TCG_AREG0;
1181 int cmp_off =
1182 (is_load
1183 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1184 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1185 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1187 /* Should generate something like the following:
1188 * shr tmp, addrlo, #TARGET_PAGE_BITS (1)
1189 * add r2, env, #high
1190 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1191 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1192 * ldr r0, [r2, #cmp] (4)
1193 * tst addrlo, #s_mask
1194 * ldr r2, [r2, #add] (5)
1195 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS
1197 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
1198 0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1200 /* We checked that the offset is contained within 16 bits above. */
1201 if (add_off > 0xfff || (use_armv6_instructions && cmp_off > 0xff)) {
1202 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1203 (24 << 7) | (cmp_off >> 8));
1204 base = TCG_REG_R2;
1205 add_off -= cmp_off & 0xff00;
1206 cmp_off &= 0xff;
1209 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1210 TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
1211 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1212 TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1214 /* Load the tlb comparator. Use ldrd if needed and available,
1215 but due to how the pointer needs setting up, ldm isn't useful.
1216 Base arm5 doesn't have ldrd, but armv5te does. */
1217 if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
1218 tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1219 } else {
1220 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1221 if (TARGET_LONG_BITS == 64) {
1222 tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, cmp_off + 4);
1226 /* Check alignment. */
1227 if (s_bits) {
1228 tcg_out_dat_imm(s, COND_AL, ARITH_TST,
1229 0, addrlo, (1 << s_bits) - 1);
1232 /* Load the tlb addend. */
1233 tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R2, add_off);
1235 tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
1236 TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1238 if (TARGET_LONG_BITS == 64) {
1239 tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1240 TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
1243 return TCG_REG_R2;
1246 /* Record the context of a call to the out of line helper code for the slow
1247 path for a load or store, so that we can later generate the correct
1248 helper code. */
1249 static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOp opc,
1250 TCGReg datalo, TCGReg datahi, TCGReg addrlo,
1251 TCGReg addrhi, int mem_index,
1252 uint8_t *raddr, uint8_t *label_ptr)
1254 TCGLabelQemuLdst *label = new_ldst_label(s);
1256 label->is_ld = is_ld;
1257 label->opc = opc;
1258 label->datalo_reg = datalo;
1259 label->datahi_reg = datahi;
1260 label->addrlo_reg = addrlo;
1261 label->addrhi_reg = addrhi;
1262 label->mem_index = mem_index;
1263 label->raddr = raddr;
1264 label->label_ptr[0] = label_ptr;
1267 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1269 TCGReg argreg, datalo, datahi;
1270 TCGMemOp opc = lb->opc;
1271 uintptr_t func;
1273 reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
1275 argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
1276 if (TARGET_LONG_BITS == 64) {
1277 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1278 } else {
1279 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1281 argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
1282 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1284 /* For armv6 we can use the canonical unsigned helpers and minimize
1285 icache usage. For pre-armv6, use the signed helpers since we do
1286 not have a single insn sign-extend. */
1287 if (use_armv6_instructions) {
1288 func = (uintptr_t)qemu_ld_helpers[opc & ~MO_SIGN];
1289 } else {
1290 func = (uintptr_t)qemu_ld_helpers[opc];
1291 if (opc & MO_SIGN) {
1292 opc = MO_UL;
1295 tcg_out_call(s, func);
1297 datalo = lb->datalo_reg;
1298 datahi = lb->datahi_reg;
1299 switch (opc & MO_SSIZE) {
1300 case MO_SB:
1301 tcg_out_ext8s(s, COND_AL, datalo, TCG_REG_R0);
1302 break;
1303 case MO_SW:
1304 tcg_out_ext16s(s, COND_AL, datalo, TCG_REG_R0);
1305 break;
1306 default:
1307 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1308 break;
1309 case MO_Q:
1310 if (datalo != TCG_REG_R1) {
1311 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1312 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1313 } else if (datahi != TCG_REG_R0) {
1314 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1315 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1316 } else {
1317 tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0);
1318 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1319 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_TMP);
1321 break;
1324 tcg_out_goto(s, COND_AL, (tcg_target_long)lb->raddr);
1327 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1329 TCGReg argreg, datalo, datahi;
1330 TCGMemOp opc = lb->opc;
1332 reloc_pc24(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
1334 argreg = TCG_REG_R0;
1335 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
1336 if (TARGET_LONG_BITS == 64) {
1337 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1338 } else {
1339 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1342 datalo = lb->datalo_reg;
1343 datahi = lb->datahi_reg;
1344 switch (opc & MO_SIZE) {
1345 case MO_8:
1346 argreg = tcg_out_arg_reg8(s, argreg, datalo);
1347 break;
1348 case MO_16:
1349 argreg = tcg_out_arg_reg16(s, argreg, datalo);
1350 break;
1351 case MO_32:
1352 default:
1353 argreg = tcg_out_arg_reg32(s, argreg, datalo);
1354 break;
1355 case MO_64:
1356 argreg = tcg_out_arg_reg64(s, argreg, datalo, datahi);
1357 break;
1360 argreg = tcg_out_arg_imm32(s, argreg, lb->mem_index);
1361 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1363 /* Tail-call to the helper, which will return to the fast path. */
1364 tcg_out_goto(s, COND_AL, (uintptr_t)qemu_st_helpers[opc]);
1366 #endif /* SOFTMMU */
1368 static inline void tcg_out_qemu_ld_index(TCGContext *s, TCGMemOp opc,
1369 TCGReg datalo, TCGReg datahi,
1370 TCGReg addrlo, TCGReg addend)
1372 TCGMemOp bswap = opc & MO_BSWAP;
1374 switch (opc & MO_SSIZE) {
1375 case MO_UB:
1376 tcg_out_ld8_r(s, COND_AL, datalo, addrlo, addend);
1377 break;
1378 case MO_SB:
1379 tcg_out_ld8s_r(s, COND_AL, datalo, addrlo, addend);
1380 break;
1381 case MO_UW:
1382 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1383 if (bswap) {
1384 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1386 break;
1387 case MO_SW:
1388 if (bswap) {
1389 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1390 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1391 } else {
1392 tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
1394 break;
1395 case MO_UL:
1396 default:
1397 tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
1398 if (bswap) {
1399 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1401 break;
1402 case MO_Q:
1404 TCGReg dl = (bswap ? datahi : datalo);
1405 TCGReg dh = (bswap ? datalo : datahi);
1407 if (use_armv6_instructions && (dl & 1) == 0 && dh == dl + 1) {
1408 tcg_out_ldrd_r(s, COND_AL, dl, addrlo, addend);
1409 } else if (dl != addend) {
1410 tcg_out_ld32_rwb(s, COND_AL, dl, addend, addrlo);
1411 tcg_out_ld32_12(s, COND_AL, dh, addend, 4);
1412 } else {
1413 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
1414 addend, addrlo, SHIFT_IMM_LSL(0));
1415 tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0);
1416 tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
1418 if (bswap) {
1419 tcg_out_bswap32(s, COND_AL, dl, dl);
1420 tcg_out_bswap32(s, COND_AL, dh, dh);
1423 break;
1427 static inline void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp opc,
1428 TCGReg datalo, TCGReg datahi,
1429 TCGReg addrlo)
1431 TCGMemOp bswap = opc & MO_BSWAP;
1433 switch (opc & MO_SSIZE) {
1434 case MO_UB:
1435 tcg_out_ld8_12(s, COND_AL, datalo, addrlo, 0);
1436 break;
1437 case MO_SB:
1438 tcg_out_ld8s_8(s, COND_AL, datalo, addrlo, 0);
1439 break;
1440 case MO_UW:
1441 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1442 if (bswap) {
1443 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1445 break;
1446 case MO_SW:
1447 if (bswap) {
1448 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1449 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1450 } else {
1451 tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
1453 break;
1454 case MO_UL:
1455 default:
1456 tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
1457 if (bswap) {
1458 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1460 break;
1461 case MO_Q:
1463 TCGReg dl = (bswap ? datahi : datalo);
1464 TCGReg dh = (bswap ? datalo : datahi);
1466 if (use_armv6_instructions && (dl & 1) == 0 && dh == dl + 1) {
1467 tcg_out_ldrd_8(s, COND_AL, dl, addrlo, 0);
1468 } else if (dl == addrlo) {
1469 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1470 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1471 } else {
1472 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1473 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1475 if (bswap) {
1476 tcg_out_bswap32(s, COND_AL, dl, dl);
1477 tcg_out_bswap32(s, COND_AL, dh, dh);
1480 break;
1484 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
1486 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1487 TCGMemOp opc;
1488 #ifdef CONFIG_SOFTMMU
1489 int mem_index;
1490 TCGReg addend;
1491 uint8_t *label_ptr;
1492 #endif
1494 datalo = *args++;
1495 datahi = (is64 ? *args++ : 0);
1496 addrlo = *args++;
1497 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1498 opc = *args++;
1500 #ifdef CONFIG_SOFTMMU
1501 mem_index = *args;
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, 1, opc, datalo, datahi, addrlo, addrhi,
1512 mem_index, s->code_ptr, label_ptr);
1513 #else /* !CONFIG_SOFTMMU */
1514 if (GUEST_BASE) {
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);
1517 } else {
1518 tcg_out_qemu_ld_direct(s, opc, datalo, datahi, addrlo);
1520 #endif
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) {
1530 case MO_8:
1531 tcg_out_st8_r(s, cond, datalo, addrlo, addend);
1532 break;
1533 case MO_16:
1534 if (bswap) {
1535 tcg_out_bswap16st(s, cond, TCG_REG_R0, datalo);
1536 tcg_out_st16_r(s, cond, TCG_REG_R0, addrlo, addend);
1537 } else {
1538 tcg_out_st16_r(s, cond, datalo, addrlo, addend);
1540 break;
1541 case MO_32:
1542 default:
1543 if (bswap) {
1544 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1545 tcg_out_st32_r(s, cond, TCG_REG_R0, addrlo, addend);
1546 } else {
1547 tcg_out_st32_r(s, cond, datalo, addrlo, addend);
1549 break;
1550 case MO_64:
1551 if (bswap) {
1552 tcg_out_bswap32(s, cond, TCG_REG_R0, datahi);
1553 tcg_out_st32_rwb(s, cond, TCG_REG_R0, addend, addrlo);
1554 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1555 tcg_out_st32_12(s, cond, TCG_REG_R0, addend, 4);
1556 } else if (use_armv6_instructions
1557 && (datalo & 1) == 0 && datahi == datalo + 1) {
1558 tcg_out_strd_r(s, cond, datalo, addrlo, addend);
1559 } else {
1560 tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
1561 tcg_out_st32_12(s, cond, datahi, addend, 4);
1563 break;
1567 static inline void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp opc,
1568 TCGReg datalo, TCGReg datahi,
1569 TCGReg addrlo)
1571 TCGMemOp bswap = opc & MO_BSWAP;
1573 switch (opc & MO_SIZE) {
1574 case MO_8:
1575 tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0);
1576 break;
1577 case MO_16:
1578 if (bswap) {
1579 tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, datalo);
1580 tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
1581 } else {
1582 tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
1584 break;
1585 case MO_32:
1586 default:
1587 if (bswap) {
1588 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1589 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1590 } else {
1591 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1593 break;
1594 case MO_64:
1595 if (bswap) {
1596 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datahi);
1597 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1598 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1599 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 4);
1600 } else if (use_armv6_instructions
1601 && (datalo & 1) == 0 && datahi == datalo + 1) {
1602 tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
1603 } else {
1604 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1605 tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4);
1607 break;
1611 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
1613 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1614 TCGMemOp opc;
1615 #ifdef CONFIG_SOFTMMU
1616 int mem_index;
1617 TCGReg addend;
1618 uint8_t *label_ptr;
1619 #endif
1621 datalo = *args++;
1622 datahi = (is64 ? *args++ : 0);
1623 addrlo = *args++;
1624 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1625 opc = *args++;
1627 #ifdef CONFIG_SOFTMMU
1628 mem_index = *args;
1629 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc & MO_SIZE, mem_index, 0);
1631 tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, addrlo, addend);
1633 /* The conditional call must come last, as we're going to return here. */
1634 label_ptr = s->code_ptr;
1635 tcg_out_bl_noaddr(s, COND_NE);
1637 add_qemu_ldst_label(s, 0, opc, datalo, datahi, addrlo, addrhi,
1638 mem_index, s->code_ptr, label_ptr);
1639 #else /* !CONFIG_SOFTMMU */
1640 if (GUEST_BASE) {
1641 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, GUEST_BASE);
1642 tcg_out_qemu_st_index(s, COND_AL, opc, datalo,
1643 datahi, addrlo, TCG_REG_TMP);
1644 } else {
1645 tcg_out_qemu_st_direct(s, opc, datalo, datahi, addrlo);
1647 #endif
1650 static uint8_t *tb_ret_addr;
1652 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1653 const TCGArg *args, const int *const_args)
1655 TCGArg a0, a1, a2, a3, a4, a5;
1656 int c;
1658 switch (opc) {
1659 case INDEX_op_exit_tb:
1660 if (use_armv7_instructions || check_fit_imm(args[0])) {
1661 tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]);
1662 tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1663 } else {
1664 uint8_t *ld_ptr = s->code_ptr;
1665 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1666 tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1667 *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
1668 tcg_out32(s, args[0]);
1670 break;
1671 case INDEX_op_goto_tb:
1672 if (s->tb_jmp_offset) {
1673 /* Direct jump method */
1674 #if defined(USE_DIRECT_JUMP)
1675 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1676 tcg_out_b_noaddr(s, COND_AL);
1677 #else
1678 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1679 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1680 tcg_out32(s, 0);
1681 #endif
1682 } else {
1683 /* Indirect jump method */
1684 #if 1
1685 c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
1686 if (c > 0xfff || c < -0xfff) {
1687 tcg_out_movi32(s, COND_AL, TCG_REG_R0,
1688 (tcg_target_long) (s->tb_next + args[0]));
1689 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1690 } else
1691 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
1692 #else
1693 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1694 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1695 tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
1696 #endif
1698 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1699 break;
1700 case INDEX_op_call:
1701 if (const_args[0])
1702 tcg_out_call(s, args[0]);
1703 else
1704 tcg_out_callr(s, COND_AL, args[0]);
1705 break;
1706 case INDEX_op_br:
1707 tcg_out_goto_label(s, COND_AL, args[0]);
1708 break;
1710 case INDEX_op_ld8u_i32:
1711 tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1712 break;
1713 case INDEX_op_ld8s_i32:
1714 tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1715 break;
1716 case INDEX_op_ld16u_i32:
1717 tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1718 break;
1719 case INDEX_op_ld16s_i32:
1720 tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1721 break;
1722 case INDEX_op_ld_i32:
1723 tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1724 break;
1725 case INDEX_op_st8_i32:
1726 tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1727 break;
1728 case INDEX_op_st16_i32:
1729 tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1730 break;
1731 case INDEX_op_st_i32:
1732 tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1733 break;
1735 case INDEX_op_mov_i32:
1736 tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1737 args[0], 0, args[1], SHIFT_IMM_LSL(0));
1738 break;
1739 case INDEX_op_movi_i32:
1740 tcg_out_movi32(s, COND_AL, args[0], args[1]);
1741 break;
1742 case INDEX_op_movcond_i32:
1743 /* Constraints mean that v2 is always in the same register as dest,
1744 * so we only need to do "if condition passed, move v1 to dest".
1746 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1747 args[1], args[2], const_args[2]);
1748 tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
1749 ARITH_MVN, args[0], 0, args[3], const_args[3]);
1750 break;
1751 case INDEX_op_add_i32:
1752 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
1753 args[0], args[1], args[2], const_args[2]);
1754 break;
1755 case INDEX_op_sub_i32:
1756 if (const_args[1]) {
1757 if (const_args[2]) {
1758 tcg_out_movi32(s, COND_AL, args[0], args[1] - args[2]);
1759 } else {
1760 tcg_out_dat_rI(s, COND_AL, ARITH_RSB,
1761 args[0], args[2], args[1], 1);
1763 } else {
1764 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
1765 args[0], args[1], args[2], const_args[2]);
1767 break;
1768 case INDEX_op_and_i32:
1769 tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
1770 args[0], args[1], args[2], const_args[2]);
1771 break;
1772 case INDEX_op_andc_i32:
1773 tcg_out_dat_rIK(s, COND_AL, ARITH_BIC, ARITH_AND,
1774 args[0], args[1], args[2], const_args[2]);
1775 break;
1776 case INDEX_op_or_i32:
1777 c = ARITH_ORR;
1778 goto gen_arith;
1779 case INDEX_op_xor_i32:
1780 c = ARITH_EOR;
1781 /* Fall through. */
1782 gen_arith:
1783 tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]);
1784 break;
1785 case INDEX_op_add2_i32:
1786 a0 = args[0], a1 = args[1], a2 = args[2];
1787 a3 = args[3], a4 = args[4], a5 = args[5];
1788 if (a0 == a3 || (a0 == a5 && !const_args[5])) {
1789 a0 = TCG_REG_TMP;
1791 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
1792 a0, a2, a4, const_args[4]);
1793 tcg_out_dat_rIK(s, COND_AL, ARITH_ADC, ARITH_SBC,
1794 a1, a3, a5, const_args[5]);
1795 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1796 break;
1797 case INDEX_op_sub2_i32:
1798 a0 = args[0], a1 = args[1], a2 = args[2];
1799 a3 = args[3], a4 = args[4], a5 = args[5];
1800 if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
1801 a0 = TCG_REG_TMP;
1803 if (const_args[2]) {
1804 if (const_args[4]) {
1805 tcg_out_movi32(s, COND_AL, a0, a4);
1806 a4 = a0;
1808 tcg_out_dat_rI(s, COND_AL, ARITH_RSB | TO_CPSR, a0, a4, a2, 1);
1809 } else {
1810 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB | TO_CPSR,
1811 ARITH_ADD | TO_CPSR, a0, a2, a4, const_args[4]);
1813 if (const_args[3]) {
1814 if (const_args[5]) {
1815 tcg_out_movi32(s, COND_AL, a1, a5);
1816 a5 = a1;
1818 tcg_out_dat_rI(s, COND_AL, ARITH_RSC, a1, a5, a3, 1);
1819 } else {
1820 tcg_out_dat_rIK(s, COND_AL, ARITH_SBC, ARITH_ADC,
1821 a1, a3, a5, const_args[5]);
1823 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1824 break;
1825 case INDEX_op_neg_i32:
1826 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1827 break;
1828 case INDEX_op_not_i32:
1829 tcg_out_dat_reg(s, COND_AL,
1830 ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1831 break;
1832 case INDEX_op_mul_i32:
1833 tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1834 break;
1835 case INDEX_op_mulu2_i32:
1836 tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1837 break;
1838 case INDEX_op_muls2_i32:
1839 tcg_out_smull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1840 break;
1841 /* XXX: Perhaps args[2] & 0x1f is wrong */
1842 case INDEX_op_shl_i32:
1843 c = const_args[2] ?
1844 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1845 goto gen_shift32;
1846 case INDEX_op_shr_i32:
1847 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1848 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1849 goto gen_shift32;
1850 case INDEX_op_sar_i32:
1851 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1852 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1853 goto gen_shift32;
1854 case INDEX_op_rotr_i32:
1855 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1856 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1857 /* Fall through. */
1858 gen_shift32:
1859 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1860 break;
1862 case INDEX_op_rotl_i32:
1863 if (const_args[2]) {
1864 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1865 ((0x20 - args[2]) & 0x1f) ?
1866 SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1867 SHIFT_IMM_LSL(0));
1868 } else {
1869 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[2], 0x20);
1870 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1871 SHIFT_REG_ROR(TCG_REG_TMP));
1873 break;
1875 case INDEX_op_brcond_i32:
1876 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1877 args[0], args[1], const_args[1]);
1878 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
1879 break;
1880 case INDEX_op_brcond2_i32:
1881 /* The resulting conditions are:
1882 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1883 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1884 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1885 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1886 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1887 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1889 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1890 args[1], args[3], const_args[3]);
1891 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1892 args[0], args[2], const_args[2]);
1893 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
1894 break;
1895 case INDEX_op_setcond_i32:
1896 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1897 args[1], args[2], const_args[2]);
1898 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1899 ARITH_MOV, args[0], 0, 1);
1900 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1901 ARITH_MOV, args[0], 0, 0);
1902 break;
1903 case INDEX_op_setcond2_i32:
1904 /* See brcond2_i32 comment */
1905 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1906 args[2], args[4], const_args[4]);
1907 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1908 args[1], args[3], const_args[3]);
1909 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1910 ARITH_MOV, args[0], 0, 1);
1911 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1912 ARITH_MOV, args[0], 0, 0);
1913 break;
1915 case INDEX_op_qemu_ld_i32:
1916 tcg_out_qemu_ld(s, args, 0);
1917 break;
1918 case INDEX_op_qemu_ld_i64:
1919 tcg_out_qemu_ld(s, args, 1);
1920 break;
1921 case INDEX_op_qemu_st_i32:
1922 tcg_out_qemu_st(s, args, 0);
1923 break;
1924 case INDEX_op_qemu_st_i64:
1925 tcg_out_qemu_st(s, args, 1);
1926 break;
1928 case INDEX_op_bswap16_i32:
1929 tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1930 break;
1931 case INDEX_op_bswap32_i32:
1932 tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1933 break;
1935 case INDEX_op_ext8s_i32:
1936 tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1937 break;
1938 case INDEX_op_ext16s_i32:
1939 tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1940 break;
1941 case INDEX_op_ext16u_i32:
1942 tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1943 break;
1945 case INDEX_op_deposit_i32:
1946 tcg_out_deposit(s, COND_AL, args[0], args[2],
1947 args[3], args[4], const_args[2]);
1948 break;
1950 case INDEX_op_div_i32:
1951 tcg_out_sdiv(s, COND_AL, args[0], args[1], args[2]);
1952 break;
1953 case INDEX_op_divu_i32:
1954 tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
1955 break;
1957 default:
1958 tcg_abort();
1962 static const TCGTargetOpDef arm_op_defs[] = {
1963 { INDEX_op_exit_tb, { } },
1964 { INDEX_op_goto_tb, { } },
1965 { INDEX_op_call, { "ri" } },
1966 { INDEX_op_br, { } },
1968 { INDEX_op_mov_i32, { "r", "r" } },
1969 { INDEX_op_movi_i32, { "r" } },
1971 { INDEX_op_ld8u_i32, { "r", "r" } },
1972 { INDEX_op_ld8s_i32, { "r", "r" } },
1973 { INDEX_op_ld16u_i32, { "r", "r" } },
1974 { INDEX_op_ld16s_i32, { "r", "r" } },
1975 { INDEX_op_ld_i32, { "r", "r" } },
1976 { INDEX_op_st8_i32, { "r", "r" } },
1977 { INDEX_op_st16_i32, { "r", "r" } },
1978 { INDEX_op_st_i32, { "r", "r" } },
1980 /* TODO: "r", "r", "ri" */
1981 { INDEX_op_add_i32, { "r", "r", "rIN" } },
1982 { INDEX_op_sub_i32, { "r", "rI", "rIN" } },
1983 { INDEX_op_mul_i32, { "r", "r", "r" } },
1984 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1985 { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
1986 { INDEX_op_and_i32, { "r", "r", "rIK" } },
1987 { INDEX_op_andc_i32, { "r", "r", "rIK" } },
1988 { INDEX_op_or_i32, { "r", "r", "rI" } },
1989 { INDEX_op_xor_i32, { "r", "r", "rI" } },
1990 { INDEX_op_neg_i32, { "r", "r" } },
1991 { INDEX_op_not_i32, { "r", "r" } },
1993 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1994 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1995 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1996 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1997 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1999 { INDEX_op_brcond_i32, { "r", "rIN" } },
2000 { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
2001 { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
2003 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
2004 { INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
2005 { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
2006 { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
2008 #if TARGET_LONG_BITS == 32
2009 { INDEX_op_qemu_ld_i32, { "r", "l" } },
2010 { INDEX_op_qemu_ld_i64, { "r", "r", "l" } },
2011 { INDEX_op_qemu_st_i32, { "s", "s" } },
2012 { INDEX_op_qemu_st_i64, { "s", "s", "s" } },
2013 #else
2014 { INDEX_op_qemu_ld_i32, { "r", "l", "l" } },
2015 { INDEX_op_qemu_ld_i64, { "r", "r", "l", "l" } },
2016 { INDEX_op_qemu_st_i32, { "s", "s", "s" } },
2017 { INDEX_op_qemu_st_i64, { "s", "s", "s", "s" } },
2018 #endif
2020 { INDEX_op_bswap16_i32, { "r", "r" } },
2021 { INDEX_op_bswap32_i32, { "r", "r" } },
2023 { INDEX_op_ext8s_i32, { "r", "r" } },
2024 { INDEX_op_ext16s_i32, { "r", "r" } },
2025 { INDEX_op_ext16u_i32, { "r", "r" } },
2027 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
2029 { INDEX_op_div_i32, { "r", "r", "r" } },
2030 { INDEX_op_divu_i32, { "r", "r", "r" } },
2032 { -1 },
2035 static void tcg_target_init(TCGContext *s)
2037 /* Only probe for the platform and capabilities if we havn't already
2038 determined maximum values at compile time. */
2039 #ifndef use_idiv_instructions
2041 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
2042 use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
2044 #endif
2045 if (__ARM_ARCH < 7) {
2046 const char *pl = (const char *)qemu_getauxval(AT_PLATFORM);
2047 if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
2048 arm_arch = pl[1] - '0';
2052 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
2053 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
2054 (1 << TCG_REG_R0) |
2055 (1 << TCG_REG_R1) |
2056 (1 << TCG_REG_R2) |
2057 (1 << TCG_REG_R3) |
2058 (1 << TCG_REG_R12) |
2059 (1 << TCG_REG_R14));
2061 tcg_regset_clear(s->reserved_regs);
2062 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
2063 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
2064 tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
2066 tcg_add_target_add_op_defs(arm_op_defs);
2069 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
2070 TCGReg arg1, intptr_t arg2)
2072 tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
2075 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
2076 TCGReg arg1, intptr_t arg2)
2078 tcg_out_st32(s, COND_AL, arg, arg1, arg2);
2081 static inline void tcg_out_mov(TCGContext *s, TCGType type,
2082 TCGReg ret, TCGReg arg)
2084 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
2087 static inline void tcg_out_movi(TCGContext *s, TCGType type,
2088 TCGReg ret, tcg_target_long arg)
2090 tcg_out_movi32(s, COND_AL, ret, arg);
2093 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2094 and tcg_register_jit. */
2096 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2098 #define FRAME_SIZE \
2099 ((PUSH_SIZE \
2100 + TCG_STATIC_CALL_ARGS_SIZE \
2101 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2102 + TCG_TARGET_STACK_ALIGN - 1) \
2103 & -TCG_TARGET_STACK_ALIGN)
2105 static void tcg_target_qemu_prologue(TCGContext *s)
2107 int stack_addend;
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 /* Reserve callee argument and tcg temp space. */
2114 stack_addend = FRAME_SIZE - PUSH_SIZE;
2116 tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
2117 TCG_REG_CALL_STACK, stack_addend, 1);
2118 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
2119 CPU_TEMP_BUF_NLONGS * sizeof(long));
2121 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2123 tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
2124 tb_ret_addr = s->code_ptr;
2126 /* Epilogue. We branch here via tb_ret_addr. */
2127 tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
2128 TCG_REG_CALL_STACK, stack_addend, 1);
2130 /* ldmia sp!, { r4 - r11, pc } */
2131 tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
2134 typedef struct {
2135 DebugFrameCIE cie;
2136 DebugFrameFDEHeader fde;
2137 uint8_t fde_def_cfa[4];
2138 uint8_t fde_reg_ofs[18];
2139 } DebugFrame;
2141 #define ELF_HOST_MACHINE EM_ARM
2143 /* We're expecting a 2 byte uleb128 encoded value. */
2144 QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
2146 static DebugFrame debug_frame = {
2147 .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
2148 .cie.id = -1,
2149 .cie.version = 1,
2150 .cie.code_align = 1,
2151 .cie.data_align = 0x7c, /* sleb128 -4 */
2152 .cie.return_column = 14,
2154 /* Total FDE size does not include the "len" member. */
2155 .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
2157 .fde_def_cfa = {
2158 12, 13, /* DW_CFA_def_cfa sp, ... */
2159 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2160 (FRAME_SIZE >> 7)
2162 .fde_reg_ofs = {
2163 /* The following must match the stmdb in the prologue. */
2164 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2165 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2166 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2167 0x89, 4, /* DW_CFA_offset, r9, -16 */
2168 0x88, 5, /* DW_CFA_offset, r8, -20 */
2169 0x87, 6, /* DW_CFA_offset, r7, -24 */
2170 0x86, 7, /* DW_CFA_offset, r6, -28 */
2171 0x85, 8, /* DW_CFA_offset, r5, -32 */
2172 0x84, 9, /* DW_CFA_offset, r4, -36 */
2176 void tcg_register_jit(void *buf, size_t buf_size)
2178 debug_frame.fde.func_start = (tcg_target_long) buf;
2179 debug_frame.fde.func_len = buf_size;
2181 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));