fix MSI injection on Xen
[qemu.git] / tcg / arm / tcg-target.c
blob146ac00f632977c3aace8bb7d01a9e0324046f2d
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 "qemu/osdep.h"
26 #include "elf.h"
27 #include "tcg-be-ldst.h"
29 /* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */
30 #ifndef __ARM_ARCH
31 # if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
32 || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
33 || defined(__ARM_ARCH_7EM__)
34 # define __ARM_ARCH 7
35 # elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
36 || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
37 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
38 # define __ARM_ARCH 6
39 # elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \
40 || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \
41 || defined(__ARM_ARCH_5TEJ__)
42 # define __ARM_ARCH 5
43 # else
44 # define __ARM_ARCH 4
45 # endif
46 #endif
48 static int arm_arch = __ARM_ARCH;
50 #if defined(__ARM_ARCH_5T__) \
51 || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
52 # define use_armv5t_instructions 1
53 #else
54 # define use_armv5t_instructions use_armv6_instructions
55 #endif
57 #define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6)
58 #define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7)
60 #ifndef use_idiv_instructions
61 bool use_idiv_instructions;
62 #endif
64 /* ??? Ought to think about changing CONFIG_SOFTMMU to always defined. */
65 #ifdef CONFIG_SOFTMMU
66 # define USING_SOFTMMU 1
67 #else
68 # define USING_SOFTMMU 0
69 #endif
71 #ifndef NDEBUG
72 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
73 "%r0",
74 "%r1",
75 "%r2",
76 "%r3",
77 "%r4",
78 "%r5",
79 "%r6",
80 "%r7",
81 "%r8",
82 "%r9",
83 "%r10",
84 "%r11",
85 "%r12",
86 "%r13",
87 "%r14",
88 "%pc",
90 #endif
92 static const int tcg_target_reg_alloc_order[] = {
93 TCG_REG_R4,
94 TCG_REG_R5,
95 TCG_REG_R6,
96 TCG_REG_R7,
97 TCG_REG_R8,
98 TCG_REG_R9,
99 TCG_REG_R10,
100 TCG_REG_R11,
101 TCG_REG_R13,
102 TCG_REG_R0,
103 TCG_REG_R1,
104 TCG_REG_R2,
105 TCG_REG_R3,
106 TCG_REG_R12,
107 TCG_REG_R14,
110 static const int tcg_target_call_iarg_regs[4] = {
111 TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
113 static const int tcg_target_call_oarg_regs[2] = {
114 TCG_REG_R0, TCG_REG_R1
117 #define TCG_REG_TMP TCG_REG_R12
119 static inline void reloc_pc24(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
121 ptrdiff_t offset = (tcg_ptr_byte_diff(target, code_ptr) - 8) >> 2;
122 *code_ptr = (*code_ptr & ~0xffffff) | (offset & 0xffffff);
125 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
126 intptr_t value, intptr_t addend)
128 assert(type == R_ARM_PC24);
129 assert(addend == 0);
130 reloc_pc24(code_ptr, (tcg_insn_unit *)value);
133 #define TCG_CT_CONST_ARM 0x100
134 #define TCG_CT_CONST_INV 0x200
135 #define TCG_CT_CONST_NEG 0x400
136 #define TCG_CT_CONST_ZERO 0x800
138 /* parse target specific constraints */
139 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
141 const char *ct_str;
143 ct_str = *pct_str;
144 switch (ct_str[0]) {
145 case 'I':
146 ct->ct |= TCG_CT_CONST_ARM;
147 break;
148 case 'K':
149 ct->ct |= TCG_CT_CONST_INV;
150 break;
151 case 'N': /* The gcc constraint letter is L, already used here. */
152 ct->ct |= TCG_CT_CONST_NEG;
153 break;
154 case 'Z':
155 ct->ct |= TCG_CT_CONST_ZERO;
156 break;
158 case 'r':
159 ct->ct |= TCG_CT_REG;
160 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
161 break;
163 /* qemu_ld address */
164 case 'l':
165 ct->ct |= TCG_CT_REG;
166 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
167 #ifdef CONFIG_SOFTMMU
168 /* r0-r2,lr will be overwritten when reading the tlb entry,
169 so don't use these. */
170 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
171 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
172 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
173 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
174 #endif
175 break;
177 /* qemu_st address & data */
178 case 's':
179 ct->ct |= TCG_CT_REG;
180 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
181 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
182 and r0-r1 doing the byte swapping, so don't use these. */
183 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
184 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
185 #if defined(CONFIG_SOFTMMU)
186 /* Avoid clashes with registers being used for helper args */
187 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
188 #if TARGET_LONG_BITS == 64
189 /* Avoid clashes with registers being used for helper args */
190 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
191 #endif
192 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
193 #endif
194 break;
196 default:
197 return -1;
199 ct_str++;
200 *pct_str = ct_str;
202 return 0;
205 static inline uint32_t rotl(uint32_t val, int n)
207 return (val << n) | (val >> (32 - n));
210 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
211 right-rotated by an even amount between 0 and 30. */
212 static inline int encode_imm(uint32_t imm)
214 int shift;
216 /* simple case, only lower bits */
217 if ((imm & ~0xff) == 0)
218 return 0;
219 /* then try a simple even shift */
220 shift = ctz32(imm) & ~1;
221 if (((imm >> shift) & ~0xff) == 0)
222 return 32 - shift;
223 /* now try harder with rotations */
224 if ((rotl(imm, 2) & ~0xff) == 0)
225 return 2;
226 if ((rotl(imm, 4) & ~0xff) == 0)
227 return 4;
228 if ((rotl(imm, 6) & ~0xff) == 0)
229 return 6;
230 /* imm can't be encoded */
231 return -1;
234 static inline int check_fit_imm(uint32_t imm)
236 return encode_imm(imm) >= 0;
239 /* Test if a constant matches the constraint.
240 * TODO: define constraints for:
242 * ldr/str offset: between -0xfff and 0xfff
243 * ldrh/strh offset: between -0xff and 0xff
244 * mov operand2: values represented with x << (2 * y), x < 0x100
245 * add, sub, eor...: ditto
247 static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
248 const TCGArgConstraint *arg_ct)
250 int ct;
251 ct = arg_ct->ct;
252 if (ct & TCG_CT_CONST) {
253 return 1;
254 } else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
255 return 1;
256 } else if ((ct & TCG_CT_CONST_INV) && check_fit_imm(~val)) {
257 return 1;
258 } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
259 return 1;
260 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
261 return 1;
262 } else {
263 return 0;
267 #define TO_CPSR (1 << 20)
269 typedef enum {
270 ARITH_AND = 0x0 << 21,
271 ARITH_EOR = 0x1 << 21,
272 ARITH_SUB = 0x2 << 21,
273 ARITH_RSB = 0x3 << 21,
274 ARITH_ADD = 0x4 << 21,
275 ARITH_ADC = 0x5 << 21,
276 ARITH_SBC = 0x6 << 21,
277 ARITH_RSC = 0x7 << 21,
278 ARITH_TST = 0x8 << 21 | TO_CPSR,
279 ARITH_CMP = 0xa << 21 | TO_CPSR,
280 ARITH_CMN = 0xb << 21 | TO_CPSR,
281 ARITH_ORR = 0xc << 21,
282 ARITH_MOV = 0xd << 21,
283 ARITH_BIC = 0xe << 21,
284 ARITH_MVN = 0xf << 21,
286 INSN_LDR_IMM = 0x04100000,
287 INSN_LDR_REG = 0x06100000,
288 INSN_STR_IMM = 0x04000000,
289 INSN_STR_REG = 0x06000000,
291 INSN_LDRH_IMM = 0x005000b0,
292 INSN_LDRH_REG = 0x001000b0,
293 INSN_LDRSH_IMM = 0x005000f0,
294 INSN_LDRSH_REG = 0x001000f0,
295 INSN_STRH_IMM = 0x004000b0,
296 INSN_STRH_REG = 0x000000b0,
298 INSN_LDRB_IMM = 0x04500000,
299 INSN_LDRB_REG = 0x06500000,
300 INSN_LDRSB_IMM = 0x005000d0,
301 INSN_LDRSB_REG = 0x001000d0,
302 INSN_STRB_IMM = 0x04400000,
303 INSN_STRB_REG = 0x06400000,
305 INSN_LDRD_IMM = 0x004000d0,
306 INSN_LDRD_REG = 0x000000d0,
307 INSN_STRD_IMM = 0x004000f0,
308 INSN_STRD_REG = 0x000000f0,
309 } ARMInsn;
311 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
312 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
313 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
314 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
315 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
316 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
317 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
318 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
320 enum arm_cond_code_e {
321 COND_EQ = 0x0,
322 COND_NE = 0x1,
323 COND_CS = 0x2, /* Unsigned greater or equal */
324 COND_CC = 0x3, /* Unsigned less than */
325 COND_MI = 0x4, /* Negative */
326 COND_PL = 0x5, /* Zero or greater */
327 COND_VS = 0x6, /* Overflow */
328 COND_VC = 0x7, /* No overflow */
329 COND_HI = 0x8, /* Unsigned greater than */
330 COND_LS = 0x9, /* Unsigned less or equal */
331 COND_GE = 0xa,
332 COND_LT = 0xb,
333 COND_GT = 0xc,
334 COND_LE = 0xd,
335 COND_AL = 0xe,
338 static const uint8_t tcg_cond_to_arm_cond[] = {
339 [TCG_COND_EQ] = COND_EQ,
340 [TCG_COND_NE] = COND_NE,
341 [TCG_COND_LT] = COND_LT,
342 [TCG_COND_GE] = COND_GE,
343 [TCG_COND_LE] = COND_LE,
344 [TCG_COND_GT] = COND_GT,
345 /* unsigned */
346 [TCG_COND_LTU] = COND_CC,
347 [TCG_COND_GEU] = COND_CS,
348 [TCG_COND_LEU] = COND_LS,
349 [TCG_COND_GTU] = COND_HI,
352 static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
354 tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
357 static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
359 tcg_out32(s, (cond << 28) | 0x0a000000 |
360 (((offset - 8) >> 2) & 0x00ffffff));
363 static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
365 /* We pay attention here to not modify the branch target by masking
366 the corresponding bytes. This ensure that caches and memory are
367 kept coherent during retranslation. */
368 tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0a));
371 static inline void tcg_out_bl_noaddr(TCGContext *s, int cond)
373 /* We pay attention here to not modify the branch target by masking
374 the corresponding bytes. This ensure that caches and memory are
375 kept coherent during retranslation. */
376 tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0b));
379 static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
381 tcg_out32(s, (cond << 28) | 0x0b000000 |
382 (((offset - 8) >> 2) & 0x00ffffff));
385 static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
387 tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
390 static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
392 tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
393 (((offset - 8) >> 2) & 0x00ffffff));
396 static inline void tcg_out_dat_reg(TCGContext *s,
397 int cond, int opc, int rd, int rn, int rm, int shift)
399 tcg_out32(s, (cond << 28) | (0 << 25) | opc |
400 (rn << 16) | (rd << 12) | shift | rm);
403 static inline void tcg_out_nop(TCGContext *s)
405 if (use_armv7_instructions) {
406 /* Architected nop introduced in v6k. */
407 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
408 also Just So Happened to do nothing on pre-v6k so that we
409 don't need to conditionalize it? */
410 tcg_out32(s, 0xe320f000);
411 } else {
412 /* Prior to that the assembler uses mov r0, r0. */
413 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 0, 0, 0, SHIFT_IMM_LSL(0));
417 static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
419 /* Simple reg-reg move, optimising out the 'do nothing' case */
420 if (rd != rm) {
421 tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, rm, SHIFT_IMM_LSL(0));
425 static inline void tcg_out_dat_imm(TCGContext *s,
426 int cond, int opc, int rd, int rn, int im)
428 tcg_out32(s, (cond << 28) | (1 << 25) | opc |
429 (rn << 16) | (rd << 12) | im);
432 static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
434 int rot, opc, rn;
436 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
437 Speed things up by only checking when movt would be required.
438 Prior to armv7, have one go at fully rotated immediates before
439 doing the decomposition thing below. */
440 if (!use_armv7_instructions || (arg & 0xffff0000)) {
441 rot = encode_imm(arg);
442 if (rot >= 0) {
443 tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
444 rotl(arg, rot) | (rot << 7));
445 return;
447 rot = encode_imm(~arg);
448 if (rot >= 0) {
449 tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
450 rotl(~arg, rot) | (rot << 7));
451 return;
455 /* Use movw + movt. */
456 if (use_armv7_instructions) {
457 /* movw */
458 tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
459 | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
460 if (arg & 0xffff0000) {
461 /* movt */
462 tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
463 | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
465 return;
468 /* TODO: This is very suboptimal, we can easily have a constant
469 pool somewhere after all the instructions. */
470 opc = ARITH_MOV;
471 rn = 0;
472 /* If we have lots of leading 1's, we can shorten the sequence by
473 beginning with mvn and then clearing higher bits with eor. */
474 if (clz32(~arg) > clz32(arg)) {
475 opc = ARITH_MVN, arg = ~arg;
477 do {
478 int i = ctz32(arg) & ~1;
479 rot = ((32 - i) << 7) & 0xf00;
480 tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
481 arg &= ~(0xff << i);
483 opc = ARITH_EOR;
484 rn = rd;
485 } while (arg);
488 static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
489 TCGArg lhs, TCGArg rhs, int rhs_is_const)
491 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
492 * rhs must satisfy the "rI" constraint.
494 if (rhs_is_const) {
495 int rot = encode_imm(rhs);
496 assert(rot >= 0);
497 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
498 } else {
499 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
503 static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
504 TCGReg dst, TCGReg lhs, TCGArg rhs,
505 bool rhs_is_const)
507 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
508 * rhs must satisfy the "rIK" constraint.
510 if (rhs_is_const) {
511 int rot = encode_imm(rhs);
512 if (rot < 0) {
513 rhs = ~rhs;
514 rot = encode_imm(rhs);
515 assert(rot >= 0);
516 opc = opinv;
518 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
519 } else {
520 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
524 static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
525 TCGArg dst, TCGArg lhs, TCGArg rhs,
526 bool rhs_is_const)
528 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
529 * rhs must satisfy the "rIN" constraint.
531 if (rhs_is_const) {
532 int rot = encode_imm(rhs);
533 if (rot < 0) {
534 rhs = -rhs;
535 rot = encode_imm(rhs);
536 assert(rot >= 0);
537 opc = opneg;
539 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
540 } else {
541 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
545 static inline void tcg_out_mul32(TCGContext *s, int cond, TCGReg rd,
546 TCGReg rn, TCGReg rm)
548 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
549 if (!use_armv6_instructions && rd == rn) {
550 if (rd == rm) {
551 /* rd == rn == rm; copy an input to tmp first. */
552 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
553 rm = rn = TCG_REG_TMP;
554 } else {
555 rn = rm;
556 rm = rd;
559 /* mul */
560 tcg_out32(s, (cond << 28) | 0x90 | (rd << 16) | (rm << 8) | rn);
563 static inline void tcg_out_umull32(TCGContext *s, int cond, TCGReg rd0,
564 TCGReg rd1, TCGReg rn, TCGReg rm)
566 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
567 if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
568 if (rd0 == rm || rd1 == rm) {
569 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
570 rn = TCG_REG_TMP;
571 } else {
572 TCGReg t = rn;
573 rn = rm;
574 rm = t;
577 /* umull */
578 tcg_out32(s, (cond << 28) | 0x00800090 |
579 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
582 static inline void tcg_out_smull32(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 /* smull */
597 tcg_out32(s, (cond << 28) | 0x00c00090 |
598 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
601 static inline void tcg_out_sdiv(TCGContext *s, int cond, int rd, int rn, int rm)
603 tcg_out32(s, 0x0710f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
606 static inline void tcg_out_udiv(TCGContext *s, int cond, int rd, int rn, int rm)
608 tcg_out32(s, 0x0730f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
611 static inline void tcg_out_ext8s(TCGContext *s, int cond,
612 int rd, int rn)
614 if (use_armv6_instructions) {
615 /* sxtb */
616 tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
617 } else {
618 tcg_out_dat_reg(s, cond, ARITH_MOV,
619 rd, 0, rn, SHIFT_IMM_LSL(24));
620 tcg_out_dat_reg(s, cond, ARITH_MOV,
621 rd, 0, rd, SHIFT_IMM_ASR(24));
625 static inline void tcg_out_ext8u(TCGContext *s, int cond,
626 int rd, int rn)
628 tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
631 static inline void tcg_out_ext16s(TCGContext *s, int cond,
632 int rd, int rn)
634 if (use_armv6_instructions) {
635 /* sxth */
636 tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
637 } else {
638 tcg_out_dat_reg(s, cond, ARITH_MOV,
639 rd, 0, rn, SHIFT_IMM_LSL(16));
640 tcg_out_dat_reg(s, cond, ARITH_MOV,
641 rd, 0, rd, SHIFT_IMM_ASR(16));
645 static inline void tcg_out_ext16u(TCGContext *s, int cond,
646 int rd, int rn)
648 if (use_armv6_instructions) {
649 /* uxth */
650 tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
651 } else {
652 tcg_out_dat_reg(s, cond, ARITH_MOV,
653 rd, 0, rn, SHIFT_IMM_LSL(16));
654 tcg_out_dat_reg(s, cond, ARITH_MOV,
655 rd, 0, rd, SHIFT_IMM_LSR(16));
659 static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
661 if (use_armv6_instructions) {
662 /* revsh */
663 tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
664 } else {
665 tcg_out_dat_reg(s, cond, ARITH_MOV,
666 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
667 tcg_out_dat_reg(s, cond, ARITH_MOV,
668 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_ASR(16));
669 tcg_out_dat_reg(s, cond, ARITH_ORR,
670 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
674 static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
676 if (use_armv6_instructions) {
677 /* rev16 */
678 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
679 } else {
680 tcg_out_dat_reg(s, cond, ARITH_MOV,
681 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
682 tcg_out_dat_reg(s, cond, ARITH_MOV,
683 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_LSR(16));
684 tcg_out_dat_reg(s, cond, ARITH_ORR,
685 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
689 /* swap the two low bytes assuming that the two high input bytes and the
690 two high output bit can hold any value. */
691 static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
693 if (use_armv6_instructions) {
694 /* rev16 */
695 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
696 } else {
697 tcg_out_dat_reg(s, cond, ARITH_MOV,
698 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSR(8));
699 tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, 0xff);
700 tcg_out_dat_reg(s, cond, ARITH_ORR,
701 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSL(8));
705 static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
707 if (use_armv6_instructions) {
708 /* rev */
709 tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
710 } else {
711 tcg_out_dat_reg(s, cond, ARITH_EOR,
712 TCG_REG_TMP, rn, rn, SHIFT_IMM_ROR(16));
713 tcg_out_dat_imm(s, cond, ARITH_BIC,
714 TCG_REG_TMP, TCG_REG_TMP, 0xff | 0x800);
715 tcg_out_dat_reg(s, cond, ARITH_MOV,
716 rd, 0, rn, SHIFT_IMM_ROR(8));
717 tcg_out_dat_reg(s, cond, ARITH_EOR,
718 rd, rd, TCG_REG_TMP, SHIFT_IMM_LSR(8));
722 bool tcg_target_deposit_valid(int ofs, int len)
724 /* ??? Without bfi, we could improve over generic code by combining
725 the right-shift from a non-zero ofs with the orr. We do run into
726 problems when rd == rs, and the mask generated from ofs+len doesn't
727 fit into an immediate. We would have to be careful not to pessimize
728 wrt the optimizations performed on the expanded code. */
729 return use_armv7_instructions;
732 static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd,
733 TCGArg a1, int ofs, int len, bool const_a1)
735 if (const_a1) {
736 /* bfi becomes bfc with rn == 15. */
737 a1 = 15;
739 /* bfi/bfc */
740 tcg_out32(s, 0x07c00010 | (cond << 28) | (rd << 12) | a1
741 | (ofs << 7) | ((ofs + len - 1) << 16));
744 /* Note that this routine is used for both LDR and LDRH formats, so we do
745 not wish to include an immediate shift at this point. */
746 static void tcg_out_memop_r(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
747 TCGReg rn, TCGReg rm, bool u, bool p, bool w)
749 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24)
750 | (w << 21) | (rn << 16) | (rt << 12) | rm);
753 static void tcg_out_memop_8(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
754 TCGReg rn, int imm8, bool p, bool w)
756 bool u = 1;
757 if (imm8 < 0) {
758 imm8 = -imm8;
759 u = 0;
761 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
762 (rn << 16) | (rt << 12) | ((imm8 & 0xf0) << 4) | (imm8 & 0xf));
765 static void tcg_out_memop_12(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
766 TCGReg rn, int imm12, bool p, bool w)
768 bool u = 1;
769 if (imm12 < 0) {
770 imm12 = -imm12;
771 u = 0;
773 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
774 (rn << 16) | (rt << 12) | imm12);
777 static inline void tcg_out_ld32_12(TCGContext *s, int cond, TCGReg rt,
778 TCGReg rn, int imm12)
780 tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 0);
783 static inline void tcg_out_st32_12(TCGContext *s, int cond, TCGReg rt,
784 TCGReg rn, int imm12)
786 tcg_out_memop_12(s, cond, INSN_STR_IMM, rt, rn, imm12, 1, 0);
789 static inline void tcg_out_ld32_r(TCGContext *s, int cond, TCGReg rt,
790 TCGReg rn, TCGReg rm)
792 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 0);
795 static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt,
796 TCGReg rn, TCGReg rm)
798 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0);
801 static inline void tcg_out_ldrd_8(TCGContext *s, int cond, TCGReg rt,
802 TCGReg rn, int imm8)
804 tcg_out_memop_8(s, cond, INSN_LDRD_IMM, rt, rn, imm8, 1, 0);
807 static inline void tcg_out_ldrd_r(TCGContext *s, int cond, TCGReg rt,
808 TCGReg rn, TCGReg rm)
810 tcg_out_memop_r(s, cond, INSN_LDRD_REG, rt, rn, rm, 1, 1, 0);
813 static inline void tcg_out_strd_8(TCGContext *s, int cond, TCGReg rt,
814 TCGReg rn, int imm8)
816 tcg_out_memop_8(s, cond, INSN_STRD_IMM, rt, rn, imm8, 1, 0);
819 static inline void tcg_out_strd_r(TCGContext *s, int cond, TCGReg rt,
820 TCGReg rn, TCGReg rm)
822 tcg_out_memop_r(s, cond, INSN_STRD_REG, rt, rn, rm, 1, 1, 0);
825 /* Register pre-increment with base writeback. */
826 static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt,
827 TCGReg rn, TCGReg rm)
829 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 1);
832 static inline void tcg_out_st32_rwb(TCGContext *s, int cond, TCGReg rt,
833 TCGReg rn, TCGReg rm)
835 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 1);
838 static inline void tcg_out_ld16u_8(TCGContext *s, int cond, TCGReg rt,
839 TCGReg rn, int imm8)
841 tcg_out_memop_8(s, cond, INSN_LDRH_IMM, rt, rn, imm8, 1, 0);
844 static inline void tcg_out_st16_8(TCGContext *s, int cond, TCGReg rt,
845 TCGReg rn, int imm8)
847 tcg_out_memop_8(s, cond, INSN_STRH_IMM, rt, rn, imm8, 1, 0);
850 static inline void tcg_out_ld16u_r(TCGContext *s, int cond, TCGReg rt,
851 TCGReg rn, TCGReg rm)
853 tcg_out_memop_r(s, cond, INSN_LDRH_REG, rt, rn, rm, 1, 1, 0);
856 static inline void tcg_out_st16_r(TCGContext *s, int cond, TCGReg rt,
857 TCGReg rn, TCGReg rm)
859 tcg_out_memop_r(s, cond, INSN_STRH_REG, rt, rn, rm, 1, 1, 0);
862 static inline void tcg_out_ld16s_8(TCGContext *s, int cond, TCGReg rt,
863 TCGReg rn, int imm8)
865 tcg_out_memop_8(s, cond, INSN_LDRSH_IMM, rt, rn, imm8, 1, 0);
868 static inline void tcg_out_ld16s_r(TCGContext *s, int cond, TCGReg rt,
869 TCGReg rn, TCGReg rm)
871 tcg_out_memop_r(s, cond, INSN_LDRSH_REG, rt, rn, rm, 1, 1, 0);
874 static inline void tcg_out_ld8_12(TCGContext *s, int cond, TCGReg rt,
875 TCGReg rn, int imm12)
877 tcg_out_memop_12(s, cond, INSN_LDRB_IMM, rt, rn, imm12, 1, 0);
880 static inline void tcg_out_st8_12(TCGContext *s, int cond, TCGReg rt,
881 TCGReg rn, int imm12)
883 tcg_out_memop_12(s, cond, INSN_STRB_IMM, rt, rn, imm12, 1, 0);
886 static inline void tcg_out_ld8_r(TCGContext *s, int cond, TCGReg rt,
887 TCGReg rn, TCGReg rm)
889 tcg_out_memop_r(s, cond, INSN_LDRB_REG, rt, rn, rm, 1, 1, 0);
892 static inline void tcg_out_st8_r(TCGContext *s, int cond, TCGReg rt,
893 TCGReg rn, TCGReg rm)
895 tcg_out_memop_r(s, cond, INSN_STRB_REG, rt, rn, rm, 1, 1, 0);
898 static inline void tcg_out_ld8s_8(TCGContext *s, int cond, TCGReg rt,
899 TCGReg rn, int imm8)
901 tcg_out_memop_8(s, cond, INSN_LDRSB_IMM, rt, rn, imm8, 1, 0);
904 static inline void tcg_out_ld8s_r(TCGContext *s, int cond, TCGReg rt,
905 TCGReg rn, TCGReg rm)
907 tcg_out_memop_r(s, cond, INSN_LDRSB_REG, rt, rn, rm, 1, 1, 0);
910 static inline void tcg_out_ld32u(TCGContext *s, int cond,
911 int rd, int rn, int32_t offset)
913 if (offset > 0xfff || offset < -0xfff) {
914 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
915 tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_TMP);
916 } else
917 tcg_out_ld32_12(s, cond, rd, rn, offset);
920 static inline void tcg_out_st32(TCGContext *s, int cond,
921 int rd, int rn, int32_t offset)
923 if (offset > 0xfff || offset < -0xfff) {
924 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
925 tcg_out_st32_r(s, cond, rd, rn, TCG_REG_TMP);
926 } else
927 tcg_out_st32_12(s, cond, rd, rn, offset);
930 static inline void tcg_out_ld16u(TCGContext *s, int cond,
931 int rd, int rn, int32_t offset)
933 if (offset > 0xff || offset < -0xff) {
934 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
935 tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_TMP);
936 } else
937 tcg_out_ld16u_8(s, cond, rd, rn, offset);
940 static inline void tcg_out_ld16s(TCGContext *s, int cond,
941 int rd, int rn, int32_t offset)
943 if (offset > 0xff || offset < -0xff) {
944 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
945 tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_TMP);
946 } else
947 tcg_out_ld16s_8(s, cond, rd, rn, offset);
950 static inline void tcg_out_st16(TCGContext *s, int cond,
951 int rd, int rn, int32_t offset)
953 if (offset > 0xff || offset < -0xff) {
954 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
955 tcg_out_st16_r(s, cond, rd, rn, TCG_REG_TMP);
956 } else
957 tcg_out_st16_8(s, cond, rd, rn, offset);
960 static inline void tcg_out_ld8u(TCGContext *s, int cond,
961 int rd, int rn, int32_t offset)
963 if (offset > 0xfff || offset < -0xfff) {
964 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
965 tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_TMP);
966 } else
967 tcg_out_ld8_12(s, cond, rd, rn, offset);
970 static inline void tcg_out_ld8s(TCGContext *s, int cond,
971 int rd, int rn, int32_t offset)
973 if (offset > 0xff || offset < -0xff) {
974 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
975 tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_TMP);
976 } else
977 tcg_out_ld8s_8(s, cond, rd, rn, offset);
980 static inline void tcg_out_st8(TCGContext *s, int cond,
981 int rd, int rn, int32_t offset)
983 if (offset > 0xfff || offset < -0xfff) {
984 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
985 tcg_out_st8_r(s, cond, rd, rn, TCG_REG_TMP);
986 } else
987 tcg_out_st8_12(s, cond, rd, rn, offset);
990 /* The _goto case is normally between TBs within the same code buffer, and
991 * with the code buffer limited to 16MB we wouldn't need the long case.
992 * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
994 static inline void tcg_out_goto(TCGContext *s, int cond, tcg_insn_unit *addr)
996 intptr_t addri = (intptr_t)addr;
997 ptrdiff_t disp = tcg_pcrel_diff(s, addr);
999 if ((addri & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) {
1000 tcg_out_b(s, cond, disp);
1001 return;
1004 tcg_out_movi32(s, cond, TCG_REG_TMP, addri);
1005 if (use_armv5t_instructions) {
1006 tcg_out_bx(s, cond, TCG_REG_TMP);
1007 } else {
1008 if (addri & 1) {
1009 tcg_abort();
1011 tcg_out_mov_reg(s, cond, TCG_REG_PC, TCG_REG_TMP);
1015 /* The call case is mostly used for helpers - so it's not unreasonable
1016 * for them to be beyond branch range */
1017 static void tcg_out_call(TCGContext *s, tcg_insn_unit *addr)
1019 intptr_t addri = (intptr_t)addr;
1020 ptrdiff_t disp = tcg_pcrel_diff(s, addr);
1022 if (disp - 8 < 0x02000000 && disp - 8 >= -0x02000000) {
1023 if (addri & 1) {
1024 /* Use BLX if the target is in Thumb mode */
1025 if (!use_armv5t_instructions) {
1026 tcg_abort();
1028 tcg_out_blx_imm(s, disp);
1029 } else {
1030 tcg_out_bl(s, COND_AL, disp);
1032 } else if (use_armv7_instructions) {
1033 tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
1034 tcg_out_blx(s, COND_AL, TCG_REG_TMP);
1035 } else {
1036 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
1037 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1038 tcg_out32(s, addri);
1042 static inline void tcg_out_goto_label(TCGContext *s, int cond, TCGLabel *l)
1044 if (l->has_value) {
1045 tcg_out_goto(s, cond, l->u.value_ptr);
1046 } else {
1047 tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, l, 0);
1048 tcg_out_b_noaddr(s, cond);
1052 #ifdef CONFIG_SOFTMMU
1053 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1054 * int mmu_idx, uintptr_t ra)
1056 static void * const qemu_ld_helpers[16] = {
1057 [MO_UB] = helper_ret_ldub_mmu,
1058 [MO_SB] = helper_ret_ldsb_mmu,
1060 [MO_LEUW] = helper_le_lduw_mmu,
1061 [MO_LEUL] = helper_le_ldul_mmu,
1062 [MO_LEQ] = helper_le_ldq_mmu,
1063 [MO_LESW] = helper_le_ldsw_mmu,
1064 [MO_LESL] = helper_le_ldul_mmu,
1066 [MO_BEUW] = helper_be_lduw_mmu,
1067 [MO_BEUL] = helper_be_ldul_mmu,
1068 [MO_BEQ] = helper_be_ldq_mmu,
1069 [MO_BESW] = helper_be_ldsw_mmu,
1070 [MO_BESL] = helper_be_ldul_mmu,
1073 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1074 * uintxx_t val, int mmu_idx, uintptr_t ra)
1076 static void * const qemu_st_helpers[16] = {
1077 [MO_UB] = helper_ret_stb_mmu,
1078 [MO_LEUW] = helper_le_stw_mmu,
1079 [MO_LEUL] = helper_le_stl_mmu,
1080 [MO_LEQ] = helper_le_stq_mmu,
1081 [MO_BEUW] = helper_be_stw_mmu,
1082 [MO_BEUL] = helper_be_stl_mmu,
1083 [MO_BEQ] = helper_be_stq_mmu,
1086 /* Helper routines for marshalling helper function arguments into
1087 * the correct registers and stack.
1088 * argreg is where we want to put this argument, arg is the argument itself.
1089 * Return value is the updated argreg ready for the next call.
1090 * Note that argreg 0..3 is real registers, 4+ on stack.
1092 * We provide routines for arguments which are: immediate, 32 bit
1093 * value in register, 16 and 8 bit values in register (which must be zero
1094 * extended before use) and 64 bit value in a lo:hi register pair.
1096 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1097 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1099 if (argreg < 4) { \
1100 MOV_ARG(s, COND_AL, argreg, arg); \
1101 } else { \
1102 int ofs = (argreg - 4) * 4; \
1103 EXT_ARG; \
1104 assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1105 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1107 return argreg + 1; \
1110 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
1111 (tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1112 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
1113 (tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1114 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
1115 (tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1116 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
1118 static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
1119 TCGReg arglo, TCGReg arghi)
1121 /* 64 bit arguments must go in even/odd register pairs
1122 * and in 8-aligned stack slots.
1124 if (argreg & 1) {
1125 argreg++;
1127 if (use_armv6_instructions && argreg >= 4
1128 && (arglo & 1) == 0 && arghi == arglo + 1) {
1129 tcg_out_strd_8(s, COND_AL, arglo,
1130 TCG_REG_CALL_STACK, (argreg - 4) * 4);
1131 return argreg + 2;
1132 } else {
1133 argreg = tcg_out_arg_reg32(s, argreg, arglo);
1134 argreg = tcg_out_arg_reg32(s, argreg, arghi);
1135 return argreg;
1139 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1141 /* We're expecting to use an 8-bit immediate and to mask. */
1142 QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
1144 /* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset.
1145 Using the offset of the second entry in the last tlb table ensures
1146 that we can index all of the elements of the first entry. */
1147 QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
1148 > 0xffff);
1150 /* Load and compare a TLB entry, leaving the flags set. Returns the register
1151 containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
1153 static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
1154 TCGMemOp s_bits, int mem_index, bool is_load)
1156 TCGReg base = TCG_AREG0;
1157 int cmp_off =
1158 (is_load
1159 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1160 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1161 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1163 /* Should generate something like the following:
1164 * shr tmp, addrlo, #TARGET_PAGE_BITS (1)
1165 * add r2, env, #high
1166 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1167 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1168 * ldr r0, [r2, #cmp] (4)
1169 * tst addrlo, #s_mask
1170 * ldr r2, [r2, #add] (5)
1171 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS
1173 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
1174 0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1176 /* We checked that the offset is contained within 16 bits above. */
1177 if (add_off > 0xfff || (use_armv6_instructions && cmp_off > 0xff)) {
1178 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1179 (24 << 7) | (cmp_off >> 8));
1180 base = TCG_REG_R2;
1181 add_off -= cmp_off & 0xff00;
1182 cmp_off &= 0xff;
1185 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1186 TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
1187 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1188 TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1190 /* Load the tlb comparator. Use ldrd if needed and available,
1191 but due to how the pointer needs setting up, ldm isn't useful.
1192 Base arm5 doesn't have ldrd, but armv5te does. */
1193 if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
1194 tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1195 } else {
1196 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1197 if (TARGET_LONG_BITS == 64) {
1198 tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, cmp_off + 4);
1202 /* Check alignment. */
1203 if (s_bits) {
1204 tcg_out_dat_imm(s, COND_AL, ARITH_TST,
1205 0, addrlo, (1 << s_bits) - 1);
1208 /* Load the tlb addend. */
1209 tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R2, add_off);
1211 tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
1212 TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1214 if (TARGET_LONG_BITS == 64) {
1215 tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1216 TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
1219 return TCG_REG_R2;
1222 /* Record the context of a call to the out of line helper code for the slow
1223 path for a load or store, so that we can later generate the correct
1224 helper code. */
1225 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
1226 TCGReg datalo, TCGReg datahi, TCGReg addrlo,
1227 TCGReg addrhi, tcg_insn_unit *raddr,
1228 tcg_insn_unit *label_ptr)
1230 TCGLabelQemuLdst *label = new_ldst_label(s);
1232 label->is_ld = is_ld;
1233 label->oi = oi;
1234 label->datalo_reg = datalo;
1235 label->datahi_reg = datahi;
1236 label->addrlo_reg = addrlo;
1237 label->addrhi_reg = addrhi;
1238 label->raddr = raddr;
1239 label->label_ptr[0] = label_ptr;
1242 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1244 TCGReg argreg, datalo, datahi;
1245 TCGMemOpIdx oi = lb->oi;
1246 TCGMemOp opc = get_memop(oi);
1247 void *func;
1249 reloc_pc24(lb->label_ptr[0], s->code_ptr);
1251 argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
1252 if (TARGET_LONG_BITS == 64) {
1253 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1254 } else {
1255 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1257 argreg = tcg_out_arg_imm32(s, argreg, oi);
1258 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1260 /* For armv6 we can use the canonical unsigned helpers and minimize
1261 icache usage. For pre-armv6, use the signed helpers since we do
1262 not have a single insn sign-extend. */
1263 if (use_armv6_instructions) {
1264 func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)];
1265 } else {
1266 func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)];
1267 if (opc & MO_SIGN) {
1268 opc = MO_UL;
1271 tcg_out_call(s, func);
1273 datalo = lb->datalo_reg;
1274 datahi = lb->datahi_reg;
1275 switch (opc & MO_SSIZE) {
1276 case MO_SB:
1277 tcg_out_ext8s(s, COND_AL, datalo, TCG_REG_R0);
1278 break;
1279 case MO_SW:
1280 tcg_out_ext16s(s, COND_AL, datalo, TCG_REG_R0);
1281 break;
1282 default:
1283 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1284 break;
1285 case MO_Q:
1286 if (datalo != TCG_REG_R1) {
1287 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1288 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1289 } else if (datahi != TCG_REG_R0) {
1290 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1291 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1292 } else {
1293 tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0);
1294 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1295 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_TMP);
1297 break;
1300 tcg_out_goto(s, COND_AL, lb->raddr);
1303 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1305 TCGReg argreg, datalo, datahi;
1306 TCGMemOpIdx oi = lb->oi;
1307 TCGMemOp opc = get_memop(oi);
1309 reloc_pc24(lb->label_ptr[0], s->code_ptr);
1311 argreg = TCG_REG_R0;
1312 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
1313 if (TARGET_LONG_BITS == 64) {
1314 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1315 } else {
1316 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1319 datalo = lb->datalo_reg;
1320 datahi = lb->datahi_reg;
1321 switch (opc & MO_SIZE) {
1322 case MO_8:
1323 argreg = tcg_out_arg_reg8(s, argreg, datalo);
1324 break;
1325 case MO_16:
1326 argreg = tcg_out_arg_reg16(s, argreg, datalo);
1327 break;
1328 case MO_32:
1329 default:
1330 argreg = tcg_out_arg_reg32(s, argreg, datalo);
1331 break;
1332 case MO_64:
1333 argreg = tcg_out_arg_reg64(s, argreg, datalo, datahi);
1334 break;
1337 argreg = tcg_out_arg_imm32(s, argreg, oi);
1338 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1340 /* Tail-call to the helper, which will return to the fast path. */
1341 tcg_out_goto(s, COND_AL, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1343 #endif /* SOFTMMU */
1345 static inline void tcg_out_qemu_ld_index(TCGContext *s, TCGMemOp opc,
1346 TCGReg datalo, TCGReg datahi,
1347 TCGReg addrlo, TCGReg addend)
1349 TCGMemOp bswap = opc & MO_BSWAP;
1351 switch (opc & MO_SSIZE) {
1352 case MO_UB:
1353 tcg_out_ld8_r(s, COND_AL, datalo, addrlo, addend);
1354 break;
1355 case MO_SB:
1356 tcg_out_ld8s_r(s, COND_AL, datalo, addrlo, addend);
1357 break;
1358 case MO_UW:
1359 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1360 if (bswap) {
1361 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1363 break;
1364 case MO_SW:
1365 if (bswap) {
1366 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1367 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1368 } else {
1369 tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
1371 break;
1372 case MO_UL:
1373 default:
1374 tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
1375 if (bswap) {
1376 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1378 break;
1379 case MO_Q:
1381 TCGReg dl = (bswap ? datahi : datalo);
1382 TCGReg dh = (bswap ? datalo : datahi);
1384 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1385 if (USING_SOFTMMU && use_armv6_instructions
1386 && (dl & 1) == 0 && dh == dl + 1) {
1387 tcg_out_ldrd_r(s, COND_AL, dl, addrlo, addend);
1388 } else if (dl != addend) {
1389 tcg_out_ld32_rwb(s, COND_AL, dl, addend, addrlo);
1390 tcg_out_ld32_12(s, COND_AL, dh, addend, 4);
1391 } else {
1392 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
1393 addend, addrlo, SHIFT_IMM_LSL(0));
1394 tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0);
1395 tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
1397 if (bswap) {
1398 tcg_out_bswap32(s, COND_AL, dl, dl);
1399 tcg_out_bswap32(s, COND_AL, dh, dh);
1402 break;
1406 static inline void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp opc,
1407 TCGReg datalo, TCGReg datahi,
1408 TCGReg addrlo)
1410 TCGMemOp bswap = opc & MO_BSWAP;
1412 switch (opc & MO_SSIZE) {
1413 case MO_UB:
1414 tcg_out_ld8_12(s, COND_AL, datalo, addrlo, 0);
1415 break;
1416 case MO_SB:
1417 tcg_out_ld8s_8(s, COND_AL, datalo, addrlo, 0);
1418 break;
1419 case MO_UW:
1420 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1421 if (bswap) {
1422 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1424 break;
1425 case MO_SW:
1426 if (bswap) {
1427 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1428 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1429 } else {
1430 tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
1432 break;
1433 case MO_UL:
1434 default:
1435 tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
1436 if (bswap) {
1437 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1439 break;
1440 case MO_Q:
1442 TCGReg dl = (bswap ? datahi : datalo);
1443 TCGReg dh = (bswap ? datalo : datahi);
1445 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1446 if (USING_SOFTMMU && use_armv6_instructions
1447 && (dl & 1) == 0 && dh == dl + 1) {
1448 tcg_out_ldrd_8(s, COND_AL, dl, addrlo, 0);
1449 } else if (dl == addrlo) {
1450 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1451 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1452 } else {
1453 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1454 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1456 if (bswap) {
1457 tcg_out_bswap32(s, COND_AL, dl, dl);
1458 tcg_out_bswap32(s, COND_AL, dh, dh);
1461 break;
1465 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
1467 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1468 TCGMemOpIdx oi;
1469 TCGMemOp opc;
1470 #ifdef CONFIG_SOFTMMU
1471 int mem_index;
1472 TCGReg addend;
1473 tcg_insn_unit *label_ptr;
1474 #endif
1476 datalo = *args++;
1477 datahi = (is64 ? *args++ : 0);
1478 addrlo = *args++;
1479 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1480 oi = *args++;
1481 opc = get_memop(oi);
1483 #ifdef CONFIG_SOFTMMU
1484 mem_index = get_mmuidx(oi);
1485 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc & MO_SIZE, mem_index, 1);
1487 /* This a conditional BL only to load a pointer within this opcode into LR
1488 for the slow path. We will not be using the value for a tail call. */
1489 label_ptr = s->code_ptr;
1490 tcg_out_bl_noaddr(s, COND_NE);
1492 tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
1494 add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
1495 s->code_ptr, label_ptr);
1496 #else /* !CONFIG_SOFTMMU */
1497 if (guest_base) {
1498 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
1499 tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, TCG_REG_TMP);
1500 } else {
1501 tcg_out_qemu_ld_direct(s, opc, datalo, datahi, addrlo);
1503 #endif
1506 static inline void tcg_out_qemu_st_index(TCGContext *s, int cond, TCGMemOp opc,
1507 TCGReg datalo, TCGReg datahi,
1508 TCGReg addrlo, TCGReg addend)
1510 TCGMemOp bswap = opc & MO_BSWAP;
1512 switch (opc & MO_SIZE) {
1513 case MO_8:
1514 tcg_out_st8_r(s, cond, datalo, addrlo, addend);
1515 break;
1516 case MO_16:
1517 if (bswap) {
1518 tcg_out_bswap16st(s, cond, TCG_REG_R0, datalo);
1519 tcg_out_st16_r(s, cond, TCG_REG_R0, addrlo, addend);
1520 } else {
1521 tcg_out_st16_r(s, cond, datalo, addrlo, addend);
1523 break;
1524 case MO_32:
1525 default:
1526 if (bswap) {
1527 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1528 tcg_out_st32_r(s, cond, TCG_REG_R0, addrlo, addend);
1529 } else {
1530 tcg_out_st32_r(s, cond, datalo, addrlo, addend);
1532 break;
1533 case MO_64:
1534 /* Avoid strd for user-only emulation, to handle unaligned. */
1535 if (bswap) {
1536 tcg_out_bswap32(s, cond, TCG_REG_R0, datahi);
1537 tcg_out_st32_rwb(s, cond, TCG_REG_R0, addend, addrlo);
1538 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1539 tcg_out_st32_12(s, cond, TCG_REG_R0, addend, 4);
1540 } else if (USING_SOFTMMU && use_armv6_instructions
1541 && (datalo & 1) == 0 && datahi == datalo + 1) {
1542 tcg_out_strd_r(s, cond, datalo, addrlo, addend);
1543 } else {
1544 tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
1545 tcg_out_st32_12(s, cond, datahi, addend, 4);
1547 break;
1551 static inline void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp opc,
1552 TCGReg datalo, TCGReg datahi,
1553 TCGReg addrlo)
1555 TCGMemOp bswap = opc & MO_BSWAP;
1557 switch (opc & MO_SIZE) {
1558 case MO_8:
1559 tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0);
1560 break;
1561 case MO_16:
1562 if (bswap) {
1563 tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, datalo);
1564 tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
1565 } else {
1566 tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
1568 break;
1569 case MO_32:
1570 default:
1571 if (bswap) {
1572 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1573 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1574 } else {
1575 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1577 break;
1578 case MO_64:
1579 /* Avoid strd for user-only emulation, to handle unaligned. */
1580 if (bswap) {
1581 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datahi);
1582 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1583 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1584 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 4);
1585 } else if (USING_SOFTMMU && use_armv6_instructions
1586 && (datalo & 1) == 0 && datahi == datalo + 1) {
1587 tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
1588 } else {
1589 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1590 tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4);
1592 break;
1596 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
1598 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1599 TCGMemOpIdx oi;
1600 TCGMemOp opc;
1601 #ifdef CONFIG_SOFTMMU
1602 int mem_index;
1603 TCGReg addend;
1604 tcg_insn_unit *label_ptr;
1605 #endif
1607 datalo = *args++;
1608 datahi = (is64 ? *args++ : 0);
1609 addrlo = *args++;
1610 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1611 oi = *args++;
1612 opc = get_memop(oi);
1614 #ifdef CONFIG_SOFTMMU
1615 mem_index = get_mmuidx(oi);
1616 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc & MO_SIZE, mem_index, 0);
1618 tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, addrlo, addend);
1620 /* The conditional call must come last, as we're going to return here. */
1621 label_ptr = s->code_ptr;
1622 tcg_out_bl_noaddr(s, COND_NE);
1624 add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi,
1625 s->code_ptr, label_ptr);
1626 #else /* !CONFIG_SOFTMMU */
1627 if (guest_base) {
1628 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
1629 tcg_out_qemu_st_index(s, COND_AL, opc, datalo,
1630 datahi, addrlo, TCG_REG_TMP);
1631 } else {
1632 tcg_out_qemu_st_direct(s, opc, datalo, datahi, addrlo);
1634 #endif
1637 static tcg_insn_unit *tb_ret_addr;
1639 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1640 const TCGArg *args, const int *const_args)
1642 TCGArg a0, a1, a2, a3, a4, a5;
1643 int c;
1645 switch (opc) {
1646 case INDEX_op_exit_tb:
1647 tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]);
1648 tcg_out_goto(s, COND_AL, tb_ret_addr);
1649 break;
1650 case INDEX_op_goto_tb:
1651 if (s->tb_jmp_offset) {
1652 /* Direct jump method */
1653 s->tb_jmp_offset[args[0]] = tcg_current_code_size(s);
1654 tcg_out_b_noaddr(s, COND_AL);
1655 } else {
1656 /* Indirect jump method */
1657 intptr_t ptr = (intptr_t)(s->tb_next + args[0]);
1658 tcg_out_movi32(s, COND_AL, TCG_REG_R0, ptr & ~0xfff);
1659 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, ptr & 0xfff);
1661 s->tb_next_offset[args[0]] = tcg_current_code_size(s);
1662 break;
1663 case INDEX_op_br:
1664 tcg_out_goto_label(s, COND_AL, arg_label(args[0]));
1665 break;
1667 case INDEX_op_ld8u_i32:
1668 tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1669 break;
1670 case INDEX_op_ld8s_i32:
1671 tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1672 break;
1673 case INDEX_op_ld16u_i32:
1674 tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1675 break;
1676 case INDEX_op_ld16s_i32:
1677 tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1678 break;
1679 case INDEX_op_ld_i32:
1680 tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1681 break;
1682 case INDEX_op_st8_i32:
1683 tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1684 break;
1685 case INDEX_op_st16_i32:
1686 tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1687 break;
1688 case INDEX_op_st_i32:
1689 tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1690 break;
1692 case INDEX_op_movcond_i32:
1693 /* Constraints mean that v2 is always in the same register as dest,
1694 * so we only need to do "if condition passed, move v1 to dest".
1696 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1697 args[1], args[2], const_args[2]);
1698 tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
1699 ARITH_MVN, args[0], 0, args[3], const_args[3]);
1700 break;
1701 case INDEX_op_add_i32:
1702 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
1703 args[0], args[1], args[2], const_args[2]);
1704 break;
1705 case INDEX_op_sub_i32:
1706 if (const_args[1]) {
1707 if (const_args[2]) {
1708 tcg_out_movi32(s, COND_AL, args[0], args[1] - args[2]);
1709 } else {
1710 tcg_out_dat_rI(s, COND_AL, ARITH_RSB,
1711 args[0], args[2], args[1], 1);
1713 } else {
1714 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
1715 args[0], args[1], args[2], const_args[2]);
1717 break;
1718 case INDEX_op_and_i32:
1719 tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
1720 args[0], args[1], args[2], const_args[2]);
1721 break;
1722 case INDEX_op_andc_i32:
1723 tcg_out_dat_rIK(s, COND_AL, ARITH_BIC, ARITH_AND,
1724 args[0], args[1], args[2], const_args[2]);
1725 break;
1726 case INDEX_op_or_i32:
1727 c = ARITH_ORR;
1728 goto gen_arith;
1729 case INDEX_op_xor_i32:
1730 c = ARITH_EOR;
1731 /* Fall through. */
1732 gen_arith:
1733 tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]);
1734 break;
1735 case INDEX_op_add2_i32:
1736 a0 = args[0], a1 = args[1], a2 = args[2];
1737 a3 = args[3], a4 = args[4], a5 = args[5];
1738 if (a0 == a3 || (a0 == a5 && !const_args[5])) {
1739 a0 = TCG_REG_TMP;
1741 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
1742 a0, a2, a4, const_args[4]);
1743 tcg_out_dat_rIK(s, COND_AL, ARITH_ADC, ARITH_SBC,
1744 a1, a3, a5, const_args[5]);
1745 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1746 break;
1747 case INDEX_op_sub2_i32:
1748 a0 = args[0], a1 = args[1], a2 = args[2];
1749 a3 = args[3], a4 = args[4], a5 = args[5];
1750 if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
1751 a0 = TCG_REG_TMP;
1753 if (const_args[2]) {
1754 if (const_args[4]) {
1755 tcg_out_movi32(s, COND_AL, a0, a4);
1756 a4 = a0;
1758 tcg_out_dat_rI(s, COND_AL, ARITH_RSB | TO_CPSR, a0, a4, a2, 1);
1759 } else {
1760 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB | TO_CPSR,
1761 ARITH_ADD | TO_CPSR, a0, a2, a4, const_args[4]);
1763 if (const_args[3]) {
1764 if (const_args[5]) {
1765 tcg_out_movi32(s, COND_AL, a1, a5);
1766 a5 = a1;
1768 tcg_out_dat_rI(s, COND_AL, ARITH_RSC, a1, a5, a3, 1);
1769 } else {
1770 tcg_out_dat_rIK(s, COND_AL, ARITH_SBC, ARITH_ADC,
1771 a1, a3, a5, const_args[5]);
1773 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1774 break;
1775 case INDEX_op_neg_i32:
1776 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1777 break;
1778 case INDEX_op_not_i32:
1779 tcg_out_dat_reg(s, COND_AL,
1780 ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1781 break;
1782 case INDEX_op_mul_i32:
1783 tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1784 break;
1785 case INDEX_op_mulu2_i32:
1786 tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1787 break;
1788 case INDEX_op_muls2_i32:
1789 tcg_out_smull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1790 break;
1791 /* XXX: Perhaps args[2] & 0x1f is wrong */
1792 case INDEX_op_shl_i32:
1793 c = const_args[2] ?
1794 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1795 goto gen_shift32;
1796 case INDEX_op_shr_i32:
1797 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1798 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1799 goto gen_shift32;
1800 case INDEX_op_sar_i32:
1801 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1802 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1803 goto gen_shift32;
1804 case INDEX_op_rotr_i32:
1805 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1806 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1807 /* Fall through. */
1808 gen_shift32:
1809 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1810 break;
1812 case INDEX_op_rotl_i32:
1813 if (const_args[2]) {
1814 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1815 ((0x20 - args[2]) & 0x1f) ?
1816 SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1817 SHIFT_IMM_LSL(0));
1818 } else {
1819 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[2], 0x20);
1820 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1821 SHIFT_REG_ROR(TCG_REG_TMP));
1823 break;
1825 case INDEX_op_brcond_i32:
1826 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1827 args[0], args[1], const_args[1]);
1828 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]],
1829 arg_label(args[3]));
1830 break;
1831 case INDEX_op_brcond2_i32:
1832 /* The resulting conditions are:
1833 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1834 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1835 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1836 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1837 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1838 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1840 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1841 args[1], args[3], const_args[3]);
1842 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1843 args[0], args[2], const_args[2]);
1844 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]],
1845 arg_label(args[5]));
1846 break;
1847 case INDEX_op_setcond_i32:
1848 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1849 args[1], args[2], const_args[2]);
1850 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1851 ARITH_MOV, args[0], 0, 1);
1852 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1853 ARITH_MOV, args[0], 0, 0);
1854 break;
1855 case INDEX_op_setcond2_i32:
1856 /* See brcond2_i32 comment */
1857 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1858 args[2], args[4], const_args[4]);
1859 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1860 args[1], args[3], const_args[3]);
1861 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1862 ARITH_MOV, args[0], 0, 1);
1863 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1864 ARITH_MOV, args[0], 0, 0);
1865 break;
1867 case INDEX_op_qemu_ld_i32:
1868 tcg_out_qemu_ld(s, args, 0);
1869 break;
1870 case INDEX_op_qemu_ld_i64:
1871 tcg_out_qemu_ld(s, args, 1);
1872 break;
1873 case INDEX_op_qemu_st_i32:
1874 tcg_out_qemu_st(s, args, 0);
1875 break;
1876 case INDEX_op_qemu_st_i64:
1877 tcg_out_qemu_st(s, args, 1);
1878 break;
1880 case INDEX_op_bswap16_i32:
1881 tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1882 break;
1883 case INDEX_op_bswap32_i32:
1884 tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1885 break;
1887 case INDEX_op_ext8s_i32:
1888 tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1889 break;
1890 case INDEX_op_ext16s_i32:
1891 tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1892 break;
1893 case INDEX_op_ext16u_i32:
1894 tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1895 break;
1897 case INDEX_op_deposit_i32:
1898 tcg_out_deposit(s, COND_AL, args[0], args[2],
1899 args[3], args[4], const_args[2]);
1900 break;
1902 case INDEX_op_div_i32:
1903 tcg_out_sdiv(s, COND_AL, args[0], args[1], args[2]);
1904 break;
1905 case INDEX_op_divu_i32:
1906 tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
1907 break;
1909 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1910 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1911 case INDEX_op_call: /* Always emitted via tcg_out_call. */
1912 default:
1913 tcg_abort();
1917 static const TCGTargetOpDef arm_op_defs[] = {
1918 { INDEX_op_exit_tb, { } },
1919 { INDEX_op_goto_tb, { } },
1920 { INDEX_op_br, { } },
1922 { INDEX_op_ld8u_i32, { "r", "r" } },
1923 { INDEX_op_ld8s_i32, { "r", "r" } },
1924 { INDEX_op_ld16u_i32, { "r", "r" } },
1925 { INDEX_op_ld16s_i32, { "r", "r" } },
1926 { INDEX_op_ld_i32, { "r", "r" } },
1927 { INDEX_op_st8_i32, { "r", "r" } },
1928 { INDEX_op_st16_i32, { "r", "r" } },
1929 { INDEX_op_st_i32, { "r", "r" } },
1931 /* TODO: "r", "r", "ri" */
1932 { INDEX_op_add_i32, { "r", "r", "rIN" } },
1933 { INDEX_op_sub_i32, { "r", "rI", "rIN" } },
1934 { INDEX_op_mul_i32, { "r", "r", "r" } },
1935 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1936 { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
1937 { INDEX_op_and_i32, { "r", "r", "rIK" } },
1938 { INDEX_op_andc_i32, { "r", "r", "rIK" } },
1939 { INDEX_op_or_i32, { "r", "r", "rI" } },
1940 { INDEX_op_xor_i32, { "r", "r", "rI" } },
1941 { INDEX_op_neg_i32, { "r", "r" } },
1942 { INDEX_op_not_i32, { "r", "r" } },
1944 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1945 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1946 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1947 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1948 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1950 { INDEX_op_brcond_i32, { "r", "rIN" } },
1951 { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
1952 { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
1954 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
1955 { INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1956 { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
1957 { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
1959 #if TARGET_LONG_BITS == 32
1960 { INDEX_op_qemu_ld_i32, { "r", "l" } },
1961 { INDEX_op_qemu_ld_i64, { "r", "r", "l" } },
1962 { INDEX_op_qemu_st_i32, { "s", "s" } },
1963 { INDEX_op_qemu_st_i64, { "s", "s", "s" } },
1964 #else
1965 { INDEX_op_qemu_ld_i32, { "r", "l", "l" } },
1966 { INDEX_op_qemu_ld_i64, { "r", "r", "l", "l" } },
1967 { INDEX_op_qemu_st_i32, { "s", "s", "s" } },
1968 { INDEX_op_qemu_st_i64, { "s", "s", "s", "s" } },
1969 #endif
1971 { INDEX_op_bswap16_i32, { "r", "r" } },
1972 { INDEX_op_bswap32_i32, { "r", "r" } },
1974 { INDEX_op_ext8s_i32, { "r", "r" } },
1975 { INDEX_op_ext16s_i32, { "r", "r" } },
1976 { INDEX_op_ext16u_i32, { "r", "r" } },
1978 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1980 { INDEX_op_div_i32, { "r", "r", "r" } },
1981 { INDEX_op_divu_i32, { "r", "r", "r" } },
1983 { -1 },
1986 static void tcg_target_init(TCGContext *s)
1988 /* Only probe for the platform and capabilities if we havn't already
1989 determined maximum values at compile time. */
1990 #ifndef use_idiv_instructions
1992 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
1993 use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
1995 #endif
1996 if (__ARM_ARCH < 7) {
1997 const char *pl = (const char *)qemu_getauxval(AT_PLATFORM);
1998 if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
1999 arm_arch = pl[1] - '0';
2003 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
2004 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
2005 (1 << TCG_REG_R0) |
2006 (1 << TCG_REG_R1) |
2007 (1 << TCG_REG_R2) |
2008 (1 << TCG_REG_R3) |
2009 (1 << TCG_REG_R12) |
2010 (1 << TCG_REG_R14));
2012 tcg_regset_clear(s->reserved_regs);
2013 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
2014 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
2015 tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
2017 tcg_add_target_add_op_defs(arm_op_defs);
2020 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
2021 TCGReg arg1, intptr_t arg2)
2023 tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
2026 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
2027 TCGReg arg1, intptr_t arg2)
2029 tcg_out_st32(s, COND_AL, arg, arg1, arg2);
2032 static inline void tcg_out_mov(TCGContext *s, TCGType type,
2033 TCGReg ret, TCGReg arg)
2035 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
2038 static inline void tcg_out_movi(TCGContext *s, TCGType type,
2039 TCGReg ret, tcg_target_long arg)
2041 tcg_out_movi32(s, COND_AL, ret, arg);
2044 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2045 and tcg_register_jit. */
2047 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2049 #define FRAME_SIZE \
2050 ((PUSH_SIZE \
2051 + TCG_STATIC_CALL_ARGS_SIZE \
2052 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2053 + TCG_TARGET_STACK_ALIGN - 1) \
2054 & -TCG_TARGET_STACK_ALIGN)
2056 static void tcg_target_qemu_prologue(TCGContext *s)
2058 int stack_addend;
2060 /* Calling convention requires us to save r4-r11 and lr. */
2061 /* stmdb sp!, { r4 - r11, lr } */
2062 tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
2064 /* Reserve callee argument and tcg temp space. */
2065 stack_addend = FRAME_SIZE - PUSH_SIZE;
2067 tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
2068 TCG_REG_CALL_STACK, stack_addend, 1);
2069 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
2070 CPU_TEMP_BUF_NLONGS * sizeof(long));
2072 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2074 tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
2075 tb_ret_addr = s->code_ptr;
2077 /* Epilogue. We branch here via tb_ret_addr. */
2078 tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
2079 TCG_REG_CALL_STACK, stack_addend, 1);
2081 /* ldmia sp!, { r4 - r11, pc } */
2082 tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
2085 typedef struct {
2086 DebugFrameHeader h;
2087 uint8_t fde_def_cfa[4];
2088 uint8_t fde_reg_ofs[18];
2089 } DebugFrame;
2091 #define ELF_HOST_MACHINE EM_ARM
2093 /* We're expecting a 2 byte uleb128 encoded value. */
2094 QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
2096 static const DebugFrame debug_frame = {
2097 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
2098 .h.cie.id = -1,
2099 .h.cie.version = 1,
2100 .h.cie.code_align = 1,
2101 .h.cie.data_align = 0x7c, /* sleb128 -4 */
2102 .h.cie.return_column = 14,
2104 /* Total FDE size does not include the "len" member. */
2105 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2107 .fde_def_cfa = {
2108 12, 13, /* DW_CFA_def_cfa sp, ... */
2109 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2110 (FRAME_SIZE >> 7)
2112 .fde_reg_ofs = {
2113 /* The following must match the stmdb in the prologue. */
2114 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2115 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2116 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2117 0x89, 4, /* DW_CFA_offset, r9, -16 */
2118 0x88, 5, /* DW_CFA_offset, r8, -20 */
2119 0x87, 6, /* DW_CFA_offset, r7, -24 */
2120 0x86, 7, /* DW_CFA_offset, r6, -28 */
2121 0x85, 8, /* DW_CFA_offset, r5, -32 */
2122 0x84, 9, /* DW_CFA_offset, r4, -36 */
2126 void tcg_register_jit(void *buf, size_t buf_size)
2128 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));