Statistics
| Branch: | Revision:

root / tcg / arm / tcg-target.c @ 614f104d

History | View | Annotate | Download (59.2 kB)

1 811d4cf4 balrog
/*
2 811d4cf4 balrog
 * Tiny Code Generator for QEMU
3 811d4cf4 balrog
 *
4 811d4cf4 balrog
 * Copyright (c) 2008 Andrzej Zaborowski
5 811d4cf4 balrog
 *
6 811d4cf4 balrog
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 811d4cf4 balrog
 * of this software and associated documentation files (the "Software"), to deal
8 811d4cf4 balrog
 * in the Software without restriction, including without limitation the rights
9 811d4cf4 balrog
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 811d4cf4 balrog
 * copies of the Software, and to permit persons to whom the Software is
11 811d4cf4 balrog
 * furnished to do so, subject to the following conditions:
12 811d4cf4 balrog
 *
13 811d4cf4 balrog
 * The above copyright notice and this permission notice shall be included in
14 811d4cf4 balrog
 * all copies or substantial portions of the Software.
15 811d4cf4 balrog
 *
16 811d4cf4 balrog
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 811d4cf4 balrog
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 811d4cf4 balrog
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 811d4cf4 balrog
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 811d4cf4 balrog
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 811d4cf4 balrog
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 811d4cf4 balrog
 * THE SOFTWARE.
23 811d4cf4 balrog
 */
24 d4a9eb1f blueswir1
25 ac34fb5c Aurelien Jarno
#if defined(__ARM_ARCH_7__) ||  \
26 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_7A__) || \
27 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_7EM__) || \
28 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_7M__) || \
29 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_7R__)
30 ac34fb5c Aurelien Jarno
#define USE_ARMV7_INSTRUCTIONS
31 ac34fb5c Aurelien Jarno
#endif
32 ac34fb5c Aurelien Jarno
33 ac34fb5c Aurelien Jarno
#if defined(USE_ARMV7_INSTRUCTIONS) || \
34 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_6J__) || \
35 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_6K__) || \
36 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_6T2__) || \
37 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_6Z__) || \
38 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_6ZK__)
39 ac34fb5c Aurelien Jarno
#define USE_ARMV6_INSTRUCTIONS
40 ac34fb5c Aurelien Jarno
#endif
41 ac34fb5c Aurelien Jarno
42 ac34fb5c Aurelien Jarno
#if defined(USE_ARMV6_INSTRUCTIONS) || \
43 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_5T__) || \
44 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_5TE__) || \
45 ac34fb5c Aurelien Jarno
    defined(__ARM_ARCH_5TEJ__)
46 ac34fb5c Aurelien Jarno
#define USE_ARMV5_INSTRUCTIONS
47 ac34fb5c Aurelien Jarno
#endif
48 ac34fb5c Aurelien Jarno
49 ac34fb5c Aurelien Jarno
#ifdef USE_ARMV5_INSTRUCTIONS
50 ac34fb5c Aurelien Jarno
static const int use_armv5_instructions = 1;
51 ac34fb5c Aurelien Jarno
#else
52 ac34fb5c Aurelien Jarno
static const int use_armv5_instructions = 0;
53 ac34fb5c Aurelien Jarno
#endif
54 ac34fb5c Aurelien Jarno
#undef USE_ARMV5_INSTRUCTIONS
55 ac34fb5c Aurelien Jarno
56 ac34fb5c Aurelien Jarno
#ifdef USE_ARMV6_INSTRUCTIONS
57 ac34fb5c Aurelien Jarno
static const int use_armv6_instructions = 1;
58 ac34fb5c Aurelien Jarno
#else
59 ac34fb5c Aurelien Jarno
static const int use_armv6_instructions = 0;
60 ac34fb5c Aurelien Jarno
#endif
61 ac34fb5c Aurelien Jarno
#undef USE_ARMV6_INSTRUCTIONS
62 ac34fb5c Aurelien Jarno
63 ac34fb5c Aurelien Jarno
#ifdef USE_ARMV7_INSTRUCTIONS
64 ac34fb5c Aurelien Jarno
static const int use_armv7_instructions = 1;
65 ac34fb5c Aurelien Jarno
#else
66 ac34fb5c Aurelien Jarno
static const int use_armv7_instructions = 0;
67 ac34fb5c Aurelien Jarno
#endif
68 ac34fb5c Aurelien Jarno
#undef USE_ARMV7_INSTRUCTIONS
69 ac34fb5c Aurelien Jarno
70 d4a9eb1f blueswir1
#ifndef NDEBUG
71 d4a9eb1f blueswir1
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
72 811d4cf4 balrog
    "%r0",
73 811d4cf4 balrog
    "%r1",
74 811d4cf4 balrog
    "%r2",
75 811d4cf4 balrog
    "%r3",
76 811d4cf4 balrog
    "%r4",
77 811d4cf4 balrog
    "%r5",
78 811d4cf4 balrog
    "%r6",
79 811d4cf4 balrog
    "%r7",
80 811d4cf4 balrog
    "%r8",
81 811d4cf4 balrog
    "%r9",
82 811d4cf4 balrog
    "%r10",
83 811d4cf4 balrog
    "%r11",
84 811d4cf4 balrog
    "%r12",
85 811d4cf4 balrog
    "%r13",
86 811d4cf4 balrog
    "%r14",
87 e4a7d5e8 Aurelien Jarno
    "%pc",
88 811d4cf4 balrog
};
89 d4a9eb1f blueswir1
#endif
90 811d4cf4 balrog
91 d4a9eb1f blueswir1
static const int tcg_target_reg_alloc_order[] = {
92 811d4cf4 balrog
    TCG_REG_R4,
93 811d4cf4 balrog
    TCG_REG_R5,
94 811d4cf4 balrog
    TCG_REG_R6,
95 811d4cf4 balrog
    TCG_REG_R7,
96 811d4cf4 balrog
    TCG_REG_R8,
97 811d4cf4 balrog
    TCG_REG_R9,
98 811d4cf4 balrog
    TCG_REG_R10,
99 811d4cf4 balrog
    TCG_REG_R11,
100 811d4cf4 balrog
    TCG_REG_R13,
101 914ccf51 Aurelien Jarno
    TCG_REG_R0,
102 914ccf51 Aurelien Jarno
    TCG_REG_R1,
103 914ccf51 Aurelien Jarno
    TCG_REG_R2,
104 914ccf51 Aurelien Jarno
    TCG_REG_R3,
105 914ccf51 Aurelien Jarno
    TCG_REG_R12,
106 811d4cf4 balrog
    TCG_REG_R14,
107 811d4cf4 balrog
};
108 811d4cf4 balrog
109 d4a9eb1f blueswir1
static const int tcg_target_call_iarg_regs[4] = {
110 811d4cf4 balrog
    TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
111 811d4cf4 balrog
};
112 d4a9eb1f blueswir1
static const int tcg_target_call_oarg_regs[2] = {
113 811d4cf4 balrog
    TCG_REG_R0, TCG_REG_R1
114 811d4cf4 balrog
};
115 811d4cf4 balrog
116 c69806ab Aurelien Jarno
static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
117 c69806ab Aurelien Jarno
{
118 c69806ab Aurelien Jarno
    *(uint32_t *) code_ptr = target;
119 c69806ab Aurelien Jarno
}
120 c69806ab Aurelien Jarno
121 c69806ab Aurelien Jarno
static inline void reloc_pc24(void *code_ptr, tcg_target_long target)
122 c69806ab Aurelien Jarno
{
123 c69806ab Aurelien Jarno
    uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2);
124 c69806ab Aurelien Jarno
125 c69806ab Aurelien Jarno
    *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
126 c69806ab Aurelien Jarno
                             | (offset & 0xffffff);
127 c69806ab Aurelien Jarno
}
128 c69806ab Aurelien Jarno
129 650bbb36 balrog
static void patch_reloc(uint8_t *code_ptr, int type,
130 811d4cf4 balrog
                tcg_target_long value, tcg_target_long addend)
131 811d4cf4 balrog
{
132 811d4cf4 balrog
    switch (type) {
133 811d4cf4 balrog
    case R_ARM_ABS32:
134 c69806ab Aurelien Jarno
        reloc_abs32(code_ptr, value);
135 811d4cf4 balrog
        break;
136 811d4cf4 balrog
137 811d4cf4 balrog
    case R_ARM_CALL:
138 811d4cf4 balrog
    case R_ARM_JUMP24:
139 811d4cf4 balrog
    default:
140 811d4cf4 balrog
        tcg_abort();
141 811d4cf4 balrog
142 811d4cf4 balrog
    case R_ARM_PC24:
143 c69806ab Aurelien Jarno
        reloc_pc24(code_ptr, value);
144 811d4cf4 balrog
        break;
145 811d4cf4 balrog
    }
146 811d4cf4 balrog
}
147 811d4cf4 balrog
148 811d4cf4 balrog
/* maximum number of register used for input function arguments */
149 811d4cf4 balrog
static inline int tcg_target_get_call_iarg_regs_count(int flags)
150 811d4cf4 balrog
{
151 811d4cf4 balrog
    return 4;
152 811d4cf4 balrog
}
153 811d4cf4 balrog
154 811d4cf4 balrog
/* parse target specific constraints */
155 d4a9eb1f blueswir1
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
156 811d4cf4 balrog
{
157 811d4cf4 balrog
    const char *ct_str;
158 811d4cf4 balrog
159 811d4cf4 balrog
    ct_str = *pct_str;
160 811d4cf4 balrog
    switch (ct_str[0]) {
161 cb4e581f Laurent Desnogues
    case 'I':
162 cb4e581f Laurent Desnogues
         ct->ct |= TCG_CT_CONST_ARM;
163 cb4e581f Laurent Desnogues
         break;
164 cb4e581f Laurent Desnogues
165 811d4cf4 balrog
    case 'r':
166 811d4cf4 balrog
        ct->ct |= TCG_CT_REG;
167 811d4cf4 balrog
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
168 811d4cf4 balrog
        break;
169 811d4cf4 balrog
170 67dcab73 Aurelien Jarno
    /* qemu_ld address */
171 67dcab73 Aurelien Jarno
    case 'l':
172 811d4cf4 balrog
        ct->ct |= TCG_CT_REG;
173 811d4cf4 balrog
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
174 67dcab73 Aurelien Jarno
#ifdef CONFIG_SOFTMMU
175 67dcab73 Aurelien Jarno
        /* r0 and r1 will be overwritten when reading the tlb entry,
176 67dcab73 Aurelien Jarno
           so don't use these. */
177 811d4cf4 balrog
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
178 811d4cf4 balrog
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
179 67dcab73 Aurelien Jarno
#endif
180 811d4cf4 balrog
        break;
181 67dcab73 Aurelien Jarno
    case 'L':
182 d0660ed4 balrog
        ct->ct |= TCG_CT_REG;
183 d0660ed4 balrog
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
184 67dcab73 Aurelien Jarno
#ifdef CONFIG_SOFTMMU
185 67dcab73 Aurelien Jarno
        /* r1 is still needed to load data_reg or data_reg2,
186 67dcab73 Aurelien Jarno
           so don't use it. */
187 d0660ed4 balrog
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
188 67dcab73 Aurelien Jarno
#endif
189 d0660ed4 balrog
        break;
190 d0660ed4 balrog
191 67dcab73 Aurelien Jarno
    /* qemu_st address & data_reg */
192 67dcab73 Aurelien Jarno
    case 's':
193 811d4cf4 balrog
        ct->ct |= TCG_CT_REG;
194 811d4cf4 balrog
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
195 67dcab73 Aurelien Jarno
        /* r0 and r1 will be overwritten when reading the tlb entry
196 67dcab73 Aurelien Jarno
           (softmmu only) and doing the byte swapping, so don't
197 67dcab73 Aurelien Jarno
           use these. */
198 811d4cf4 balrog
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
199 811d4cf4 balrog
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
200 811d4cf4 balrog
        break;
201 67dcab73 Aurelien Jarno
    /* qemu_st64 data_reg2 */
202 67dcab73 Aurelien Jarno
    case 'S':
203 811d4cf4 balrog
        ct->ct |= TCG_CT_REG;
204 811d4cf4 balrog
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
205 67dcab73 Aurelien Jarno
        /* r0 and r1 will be overwritten when reading the tlb entry
206 67dcab73 Aurelien Jarno
            (softmmu only) and doing the byte swapping, so don't
207 67dcab73 Aurelien Jarno
            use these. */
208 811d4cf4 balrog
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
209 811d4cf4 balrog
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
210 67dcab73 Aurelien Jarno
#ifdef CONFIG_SOFTMMU
211 67dcab73 Aurelien Jarno
        /* r2 is still needed to load data_reg, so don't use it. */
212 67dcab73 Aurelien Jarno
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
213 811d4cf4 balrog
#endif
214 67dcab73 Aurelien Jarno
        break;
215 811d4cf4 balrog
216 811d4cf4 balrog
    default:
217 811d4cf4 balrog
        return -1;
218 811d4cf4 balrog
    }
219 811d4cf4 balrog
    ct_str++;
220 811d4cf4 balrog
    *pct_str = ct_str;
221 811d4cf4 balrog
222 811d4cf4 balrog
    return 0;
223 811d4cf4 balrog
}
224 811d4cf4 balrog
225 94953e6d Laurent Desnogues
static inline uint32_t rotl(uint32_t val, int n)
226 94953e6d Laurent Desnogues
{
227 94953e6d Laurent Desnogues
  return (val << n) | (val >> (32 - n));
228 94953e6d Laurent Desnogues
}
229 94953e6d Laurent Desnogues
230 94953e6d Laurent Desnogues
/* ARM immediates for ALU instructions are made of an unsigned 8-bit
231 94953e6d Laurent Desnogues
   right-rotated by an even amount between 0 and 30. */
232 94953e6d Laurent Desnogues
static inline int encode_imm(uint32_t imm)
233 94953e6d Laurent Desnogues
{
234 4e6f6d4c Laurent Desnogues
    int shift;
235 4e6f6d4c Laurent Desnogues
236 94953e6d Laurent Desnogues
    /* simple case, only lower bits */
237 94953e6d Laurent Desnogues
    if ((imm & ~0xff) == 0)
238 94953e6d Laurent Desnogues
        return 0;
239 94953e6d Laurent Desnogues
    /* then try a simple even shift */
240 94953e6d Laurent Desnogues
    shift = ctz32(imm) & ~1;
241 94953e6d Laurent Desnogues
    if (((imm >> shift) & ~0xff) == 0)
242 94953e6d Laurent Desnogues
        return 32 - shift;
243 94953e6d Laurent Desnogues
    /* now try harder with rotations */
244 94953e6d Laurent Desnogues
    if ((rotl(imm, 2) & ~0xff) == 0)
245 94953e6d Laurent Desnogues
        return 2;
246 94953e6d Laurent Desnogues
    if ((rotl(imm, 4) & ~0xff) == 0)
247 94953e6d Laurent Desnogues
        return 4;
248 94953e6d Laurent Desnogues
    if ((rotl(imm, 6) & ~0xff) == 0)
249 94953e6d Laurent Desnogues
        return 6;
250 94953e6d Laurent Desnogues
    /* imm can't be encoded */
251 94953e6d Laurent Desnogues
    return -1;
252 94953e6d Laurent Desnogues
}
253 cb4e581f Laurent Desnogues
254 cb4e581f Laurent Desnogues
static inline int check_fit_imm(uint32_t imm)
255 cb4e581f Laurent Desnogues
{
256 94953e6d Laurent Desnogues
    return encode_imm(imm) >= 0;
257 cb4e581f Laurent Desnogues
}
258 cb4e581f Laurent Desnogues
259 811d4cf4 balrog
/* Test if a constant matches the constraint.
260 811d4cf4 balrog
 * TODO: define constraints for:
261 811d4cf4 balrog
 *
262 811d4cf4 balrog
 * ldr/str offset:   between -0xfff and 0xfff
263 811d4cf4 balrog
 * ldrh/strh offset: between -0xff and 0xff
264 811d4cf4 balrog
 * mov operand2:     values represented with x << (2 * y), x < 0x100
265 811d4cf4 balrog
 * add, sub, eor...: ditto
266 811d4cf4 balrog
 */
267 811d4cf4 balrog
static inline int tcg_target_const_match(tcg_target_long val,
268 811d4cf4 balrog
                const TCGArgConstraint *arg_ct)
269 811d4cf4 balrog
{
270 811d4cf4 balrog
    int ct;
271 811d4cf4 balrog
    ct = arg_ct->ct;
272 811d4cf4 balrog
    if (ct & TCG_CT_CONST)
273 811d4cf4 balrog
        return 1;
274 cb4e581f Laurent Desnogues
    else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val))
275 cb4e581f Laurent Desnogues
        return 1;
276 811d4cf4 balrog
    else
277 811d4cf4 balrog
        return 0;
278 811d4cf4 balrog
}
279 811d4cf4 balrog
280 811d4cf4 balrog
enum arm_data_opc_e {
281 811d4cf4 balrog
    ARITH_AND = 0x0,
282 811d4cf4 balrog
    ARITH_EOR = 0x1,
283 811d4cf4 balrog
    ARITH_SUB = 0x2,
284 811d4cf4 balrog
    ARITH_RSB = 0x3,
285 811d4cf4 balrog
    ARITH_ADD = 0x4,
286 811d4cf4 balrog
    ARITH_ADC = 0x5,
287 811d4cf4 balrog
    ARITH_SBC = 0x6,
288 811d4cf4 balrog
    ARITH_RSC = 0x7,
289 3979144c pbrook
    ARITH_TST = 0x8,
290 811d4cf4 balrog
    ARITH_CMP = 0xa,
291 811d4cf4 balrog
    ARITH_CMN = 0xb,
292 811d4cf4 balrog
    ARITH_ORR = 0xc,
293 811d4cf4 balrog
    ARITH_MOV = 0xd,
294 811d4cf4 balrog
    ARITH_BIC = 0xe,
295 811d4cf4 balrog
    ARITH_MVN = 0xf,
296 811d4cf4 balrog
};
297 811d4cf4 balrog
298 3979144c pbrook
#define TO_CPSR(opc) \
299 3979144c pbrook
  ((opc == ARITH_CMP || opc == ARITH_CMN || opc == ARITH_TST) << 20)
300 811d4cf4 balrog
301 811d4cf4 balrog
#define SHIFT_IMM_LSL(im)        (((im) << 7) | 0x00)
302 811d4cf4 balrog
#define SHIFT_IMM_LSR(im)        (((im) << 7) | 0x20)
303 811d4cf4 balrog
#define SHIFT_IMM_ASR(im)        (((im) << 7) | 0x40)
304 811d4cf4 balrog
#define SHIFT_IMM_ROR(im)        (((im) << 7) | 0x60)
305 811d4cf4 balrog
#define SHIFT_REG_LSL(rs)        (((rs) << 8) | 0x10)
306 811d4cf4 balrog
#define SHIFT_REG_LSR(rs)        (((rs) << 8) | 0x30)
307 811d4cf4 balrog
#define SHIFT_REG_ASR(rs)        (((rs) << 8) | 0x50)
308 811d4cf4 balrog
#define SHIFT_REG_ROR(rs)        (((rs) << 8) | 0x70)
309 811d4cf4 balrog
310 811d4cf4 balrog
enum arm_cond_code_e {
311 811d4cf4 balrog
    COND_EQ = 0x0,
312 811d4cf4 balrog
    COND_NE = 0x1,
313 811d4cf4 balrog
    COND_CS = 0x2,        /* Unsigned greater or equal */
314 811d4cf4 balrog
    COND_CC = 0x3,        /* Unsigned less than */
315 811d4cf4 balrog
    COND_MI = 0x4,        /* Negative */
316 811d4cf4 balrog
    COND_PL = 0x5,        /* Zero or greater */
317 811d4cf4 balrog
    COND_VS = 0x6,        /* Overflow */
318 811d4cf4 balrog
    COND_VC = 0x7,        /* No overflow */
319 811d4cf4 balrog
    COND_HI = 0x8,        /* Unsigned greater than */
320 811d4cf4 balrog
    COND_LS = 0x9,        /* Unsigned less or equal */
321 811d4cf4 balrog
    COND_GE = 0xa,
322 811d4cf4 balrog
    COND_LT = 0xb,
323 811d4cf4 balrog
    COND_GT = 0xc,
324 811d4cf4 balrog
    COND_LE = 0xd,
325 811d4cf4 balrog
    COND_AL = 0xe,
326 811d4cf4 balrog
};
327 811d4cf4 balrog
328 811d4cf4 balrog
static const uint8_t tcg_cond_to_arm_cond[10] = {
329 811d4cf4 balrog
    [TCG_COND_EQ] = COND_EQ,
330 811d4cf4 balrog
    [TCG_COND_NE] = COND_NE,
331 811d4cf4 balrog
    [TCG_COND_LT] = COND_LT,
332 811d4cf4 balrog
    [TCG_COND_GE] = COND_GE,
333 811d4cf4 balrog
    [TCG_COND_LE] = COND_LE,
334 811d4cf4 balrog
    [TCG_COND_GT] = COND_GT,
335 811d4cf4 balrog
    /* unsigned */
336 811d4cf4 balrog
    [TCG_COND_LTU] = COND_CC,
337 811d4cf4 balrog
    [TCG_COND_GEU] = COND_CS,
338 811d4cf4 balrog
    [TCG_COND_LEU] = COND_LS,
339 811d4cf4 balrog
    [TCG_COND_GTU] = COND_HI,
340 811d4cf4 balrog
};
341 811d4cf4 balrog
342 811d4cf4 balrog
static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
343 811d4cf4 balrog
{
344 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
345 811d4cf4 balrog
}
346 811d4cf4 balrog
347 811d4cf4 balrog
static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
348 811d4cf4 balrog
{
349 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x0a000000 |
350 811d4cf4 balrog
                    (((offset - 8) >> 2) & 0x00ffffff));
351 811d4cf4 balrog
}
352 811d4cf4 balrog
353 e936243a balrog
static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
354 e936243a balrog
{
355 56779034 Aurelien Jarno
    /* We pay attention here to not modify the branch target by skipping
356 56779034 Aurelien Jarno
       the corresponding bytes. This ensure that caches and memory are
357 56779034 Aurelien Jarno
       kept coherent during retranslation. */
358 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
359 e936243a balrog
    tcg_out8(s, (cond << 4) | 0x0a);
360 e936243a balrog
    s->code_ptr += 3;
361 e936243a balrog
#else
362 e936243a balrog
    s->code_ptr += 3;
363 e936243a balrog
    tcg_out8(s, (cond << 4) | 0x0a);
364 e936243a balrog
#endif
365 e936243a balrog
}
366 e936243a balrog
367 811d4cf4 balrog
static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
368 811d4cf4 balrog
{
369 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x0b000000 |
370 811d4cf4 balrog
                    (((offset - 8) >> 2) & 0x00ffffff));
371 811d4cf4 balrog
}
372 811d4cf4 balrog
373 23401b58 Aurelien Jarno
static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
374 23401b58 Aurelien Jarno
{
375 23401b58 Aurelien Jarno
    tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
376 23401b58 Aurelien Jarno
}
377 23401b58 Aurelien Jarno
378 24e838b7 Peter Maydell
static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
379 24e838b7 Peter Maydell
{
380 24e838b7 Peter Maydell
    tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
381 24e838b7 Peter Maydell
                (((offset - 8) >> 2) & 0x00ffffff));
382 24e838b7 Peter Maydell
}
383 24e838b7 Peter Maydell
384 811d4cf4 balrog
static inline void tcg_out_dat_reg(TCGContext *s,
385 811d4cf4 balrog
                int cond, int opc, int rd, int rn, int rm, int shift)
386 811d4cf4 balrog
{
387 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | (0 << 25) | (opc << 21) | TO_CPSR(opc) |
388 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | shift | rm);
389 811d4cf4 balrog
}
390 811d4cf4 balrog
391 811d4cf4 balrog
static inline void tcg_out_dat_reg2(TCGContext *s,
392 811d4cf4 balrog
                int cond, int opc0, int opc1, int rd0, int rd1,
393 811d4cf4 balrog
                int rn0, int rn1, int rm0, int rm1, int shift)
394 811d4cf4 balrog
{
395 0c9c3a9e balrog
    if (rd0 == rn1 || rd0 == rm1) {
396 0c9c3a9e balrog
        tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
397 0c9c3a9e balrog
                        (rn0 << 16) | (8 << 12) | shift | rm0);
398 0c9c3a9e balrog
        tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
399 0c9c3a9e balrog
                        (rn1 << 16) | (rd1 << 12) | shift | rm1);
400 0c9c3a9e balrog
        tcg_out_dat_reg(s, cond, ARITH_MOV,
401 0c9c3a9e balrog
                        rd0, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
402 0c9c3a9e balrog
    } else {
403 0c9c3a9e balrog
        tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
404 0c9c3a9e balrog
                        (rn0 << 16) | (rd0 << 12) | shift | rm0);
405 0c9c3a9e balrog
        tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
406 0c9c3a9e balrog
                        (rn1 << 16) | (rd1 << 12) | shift | rm1);
407 0c9c3a9e balrog
    }
408 811d4cf4 balrog
}
409 811d4cf4 balrog
410 811d4cf4 balrog
static inline void tcg_out_dat_imm(TCGContext *s,
411 811d4cf4 balrog
                int cond, int opc, int rd, int rn, int im)
412 811d4cf4 balrog
{
413 3979144c pbrook
    tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) | TO_CPSR(opc) |
414 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | im);
415 811d4cf4 balrog
}
416 811d4cf4 balrog
417 811d4cf4 balrog
static inline void tcg_out_movi32(TCGContext *s,
418 0f11f25a Aurelien Jarno
                int cond, int rd, uint32_t arg)
419 811d4cf4 balrog
{
420 811d4cf4 balrog
    /* TODO: This is very suboptimal, we can easily have a constant
421 811d4cf4 balrog
     * pool somewhere after all the instructions.  */
422 0f11f25a Aurelien Jarno
    if ((int)arg < 0 && (int)arg >= -0x100) {
423 0f11f25a Aurelien Jarno
        tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
424 0f11f25a Aurelien Jarno
    } else if (use_armv7_instructions) {
425 ac34fb5c Aurelien Jarno
        /* use movw/movt */
426 ac34fb5c Aurelien Jarno
        /* movw */
427 ac34fb5c Aurelien Jarno
        tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
428 ac34fb5c Aurelien Jarno
                  | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
429 0f11f25a Aurelien Jarno
        if (arg & 0xffff0000) {
430 ac34fb5c Aurelien Jarno
            /* movt */
431 ac34fb5c Aurelien Jarno
            tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
432 ac34fb5c Aurelien Jarno
                      | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
433 ac34fb5c Aurelien Jarno
        }
434 0f11f25a Aurelien Jarno
    } else {
435 0f11f25a Aurelien Jarno
        int opc = ARITH_MOV;
436 0f11f25a Aurelien Jarno
        int rn = 0;
437 0f11f25a Aurelien Jarno
438 0f11f25a Aurelien Jarno
        do {
439 0f11f25a Aurelien Jarno
            int i, rot;
440 0f11f25a Aurelien Jarno
441 0f11f25a Aurelien Jarno
            i = ctz32(arg) & ~1;
442 0f11f25a Aurelien Jarno
            rot = ((32 - i) << 7) & 0xf00;
443 0f11f25a Aurelien Jarno
            tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
444 0f11f25a Aurelien Jarno
            arg &= ~(0xff << i);
445 0f11f25a Aurelien Jarno
446 0f11f25a Aurelien Jarno
            opc = ARITH_ORR;
447 0f11f25a Aurelien Jarno
            rn = rd;
448 0f11f25a Aurelien Jarno
        } while (arg);
449 0f11f25a Aurelien Jarno
    }
450 811d4cf4 balrog
}
451 811d4cf4 balrog
452 811d4cf4 balrog
static inline void tcg_out_mul32(TCGContext *s,
453 811d4cf4 balrog
                int cond, int rd, int rs, int rm)
454 811d4cf4 balrog
{
455 811d4cf4 balrog
    if (rd != rm)
456 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
457 811d4cf4 balrog
                        (rs << 8) | 0x90 | rm);
458 811d4cf4 balrog
    else if (rd != rs)
459 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
460 811d4cf4 balrog
                        (rm << 8) | 0x90 | rs);
461 811d4cf4 balrog
    else {
462 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | ( 8 << 16) | (0 << 12) |
463 811d4cf4 balrog
                        (rs << 8) | 0x90 | rm);
464 811d4cf4 balrog
        tcg_out_dat_reg(s, cond, ARITH_MOV,
465 c8d80cef Aurelien Jarno
                        rd, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
466 811d4cf4 balrog
    }
467 811d4cf4 balrog
}
468 811d4cf4 balrog
469 811d4cf4 balrog
static inline void tcg_out_umull32(TCGContext *s,
470 811d4cf4 balrog
                int cond, int rd0, int rd1, int rs, int rm)
471 811d4cf4 balrog
{
472 811d4cf4 balrog
    if (rd0 != rm && rd1 != rm)
473 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x800090 |
474 811d4cf4 balrog
                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
475 811d4cf4 balrog
    else if (rd0 != rs && rd1 != rs)
476 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x800090 |
477 811d4cf4 balrog
                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
478 811d4cf4 balrog
    else {
479 811d4cf4 balrog
        tcg_out_dat_reg(s, cond, ARITH_MOV,
480 811d4cf4 balrog
                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
481 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x800098 |
482 811d4cf4 balrog
                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
483 811d4cf4 balrog
    }
484 811d4cf4 balrog
}
485 811d4cf4 balrog
486 811d4cf4 balrog
static inline void tcg_out_smull32(TCGContext *s,
487 811d4cf4 balrog
                int cond, int rd0, int rd1, int rs, int rm)
488 811d4cf4 balrog
{
489 811d4cf4 balrog
    if (rd0 != rm && rd1 != rm)
490 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0xc00090 |
491 811d4cf4 balrog
                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
492 811d4cf4 balrog
    else if (rd0 != rs && rd1 != rs)
493 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0xc00090 |
494 811d4cf4 balrog
                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
495 811d4cf4 balrog
    else {
496 811d4cf4 balrog
        tcg_out_dat_reg(s, cond, ARITH_MOV,
497 811d4cf4 balrog
                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
498 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0xc00098 |
499 811d4cf4 balrog
                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
500 811d4cf4 balrog
    }
501 811d4cf4 balrog
}
502 811d4cf4 balrog
503 9517094f Aurelien Jarno
static inline void tcg_out_ext8s(TCGContext *s, int cond,
504 9517094f Aurelien Jarno
                                 int rd, int rn)
505 9517094f Aurelien Jarno
{
506 9517094f Aurelien Jarno
    if (use_armv6_instructions) {
507 9517094f Aurelien Jarno
        /* sxtb */
508 9517094f Aurelien Jarno
        tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
509 9517094f Aurelien Jarno
    } else {
510 e23886a9 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
511 9517094f Aurelien Jarno
                        rd, 0, rn, SHIFT_IMM_LSL(24));
512 e23886a9 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
513 9517094f Aurelien Jarno
                        rd, 0, rd, SHIFT_IMM_ASR(24));
514 9517094f Aurelien Jarno
    }
515 9517094f Aurelien Jarno
}
516 9517094f Aurelien Jarno
517 e854b6d3 Aurelien Jarno
static inline void tcg_out_ext8u(TCGContext *s, int cond,
518 e854b6d3 Aurelien Jarno
                                 int rd, int rn)
519 e854b6d3 Aurelien Jarno
{
520 e854b6d3 Aurelien Jarno
    tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
521 e854b6d3 Aurelien Jarno
}
522 e854b6d3 Aurelien Jarno
523 9517094f Aurelien Jarno
static inline void tcg_out_ext16s(TCGContext *s, int cond,
524 9517094f Aurelien Jarno
                                  int rd, int rn)
525 9517094f Aurelien Jarno
{
526 9517094f Aurelien Jarno
    if (use_armv6_instructions) {
527 9517094f Aurelien Jarno
        /* sxth */
528 9517094f Aurelien Jarno
        tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
529 9517094f Aurelien Jarno
    } else {
530 e23886a9 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
531 9517094f Aurelien Jarno
                        rd, 0, rn, SHIFT_IMM_LSL(16));
532 e23886a9 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
533 9517094f Aurelien Jarno
                        rd, 0, rd, SHIFT_IMM_ASR(16));
534 9517094f Aurelien Jarno
    }
535 9517094f Aurelien Jarno
}
536 9517094f Aurelien Jarno
537 9517094f Aurelien Jarno
static inline void tcg_out_ext16u(TCGContext *s, int cond,
538 9517094f Aurelien Jarno
                                  int rd, int rn)
539 9517094f Aurelien Jarno
{
540 9517094f Aurelien Jarno
    if (use_armv6_instructions) {
541 9517094f Aurelien Jarno
        /* uxth */
542 9517094f Aurelien Jarno
        tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
543 9517094f Aurelien Jarno
    } else {
544 e23886a9 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
545 9517094f Aurelien Jarno
                        rd, 0, rn, SHIFT_IMM_LSL(16));
546 e23886a9 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
547 9517094f Aurelien Jarno
                        rd, 0, rd, SHIFT_IMM_LSR(16));
548 9517094f Aurelien Jarno
    }
549 9517094f Aurelien Jarno
}
550 9517094f Aurelien Jarno
551 67dcab73 Aurelien Jarno
static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
552 67dcab73 Aurelien Jarno
{
553 67dcab73 Aurelien Jarno
    if (use_armv6_instructions) {
554 67dcab73 Aurelien Jarno
        /* revsh */
555 67dcab73 Aurelien Jarno
        tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
556 67dcab73 Aurelien Jarno
    } else {
557 67dcab73 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
558 67dcab73 Aurelien Jarno
                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
559 67dcab73 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
560 67dcab73 Aurelien Jarno
                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_ASR(16));
561 67dcab73 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_ORR,
562 67dcab73 Aurelien Jarno
                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
563 67dcab73 Aurelien Jarno
    }
564 67dcab73 Aurelien Jarno
}
565 67dcab73 Aurelien Jarno
566 244b1e81 Aurelien Jarno
static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
567 244b1e81 Aurelien Jarno
{
568 244b1e81 Aurelien Jarno
    if (use_armv6_instructions) {
569 244b1e81 Aurelien Jarno
        /* rev16 */
570 244b1e81 Aurelien Jarno
        tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
571 244b1e81 Aurelien Jarno
    } else {
572 244b1e81 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
573 244b1e81 Aurelien Jarno
                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
574 244b1e81 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
575 244b1e81 Aurelien Jarno
                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_LSR(16));
576 244b1e81 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_ORR,
577 244b1e81 Aurelien Jarno
                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
578 244b1e81 Aurelien Jarno
    }
579 244b1e81 Aurelien Jarno
}
580 244b1e81 Aurelien Jarno
581 244b1e81 Aurelien Jarno
static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
582 244b1e81 Aurelien Jarno
{
583 244b1e81 Aurelien Jarno
    if (use_armv6_instructions) {
584 244b1e81 Aurelien Jarno
        /* rev */
585 244b1e81 Aurelien Jarno
        tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
586 244b1e81 Aurelien Jarno
    } else {
587 244b1e81 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_EOR,
588 244b1e81 Aurelien Jarno
                        TCG_REG_R8, rn, rn, SHIFT_IMM_ROR(16));
589 244b1e81 Aurelien Jarno
        tcg_out_dat_imm(s, cond, ARITH_BIC,
590 244b1e81 Aurelien Jarno
                        TCG_REG_R8, TCG_REG_R8, 0xff | 0x800);
591 244b1e81 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV,
592 244b1e81 Aurelien Jarno
                        rd, 0, rn, SHIFT_IMM_ROR(8));
593 244b1e81 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_EOR,
594 244b1e81 Aurelien Jarno
                        rd, rd, TCG_REG_R8, SHIFT_IMM_LSR(8));
595 244b1e81 Aurelien Jarno
    }
596 244b1e81 Aurelien Jarno
}
597 244b1e81 Aurelien Jarno
598 811d4cf4 balrog
static inline void tcg_out_ld32_12(TCGContext *s, int cond,
599 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
600 811d4cf4 balrog
{
601 811d4cf4 balrog
    if (im >= 0)
602 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05900000 |
603 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | (im & 0xfff));
604 811d4cf4 balrog
    else
605 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05100000 |
606 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
607 811d4cf4 balrog
}
608 811d4cf4 balrog
609 811d4cf4 balrog
static inline void tcg_out_st32_12(TCGContext *s, int cond,
610 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
611 811d4cf4 balrog
{
612 811d4cf4 balrog
    if (im >= 0)
613 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05800000 |
614 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | (im & 0xfff));
615 811d4cf4 balrog
    else
616 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05000000 |
617 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
618 811d4cf4 balrog
}
619 811d4cf4 balrog
620 811d4cf4 balrog
static inline void tcg_out_ld32_r(TCGContext *s, int cond,
621 811d4cf4 balrog
                int rd, int rn, int rm)
622 811d4cf4 balrog
{
623 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x07900000 |
624 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
625 811d4cf4 balrog
}
626 811d4cf4 balrog
627 811d4cf4 balrog
static inline void tcg_out_st32_r(TCGContext *s, int cond,
628 811d4cf4 balrog
                int rd, int rn, int rm)
629 811d4cf4 balrog
{
630 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x07800000 |
631 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
632 811d4cf4 balrog
}
633 811d4cf4 balrog
634 3979144c pbrook
/* Register pre-increment with base writeback.  */
635 3979144c pbrook
static inline void tcg_out_ld32_rwb(TCGContext *s, int cond,
636 3979144c pbrook
                int rd, int rn, int rm)
637 3979144c pbrook
{
638 3979144c pbrook
    tcg_out32(s, (cond << 28) | 0x07b00000 |
639 3979144c pbrook
                    (rn << 16) | (rd << 12) | rm);
640 3979144c pbrook
}
641 3979144c pbrook
642 3979144c pbrook
static inline void tcg_out_st32_rwb(TCGContext *s, int cond,
643 3979144c pbrook
                int rd, int rn, int rm)
644 3979144c pbrook
{
645 3979144c pbrook
    tcg_out32(s, (cond << 28) | 0x07a00000 |
646 3979144c pbrook
                    (rn << 16) | (rd << 12) | rm);
647 3979144c pbrook
}
648 3979144c pbrook
649 811d4cf4 balrog
static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
650 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
651 811d4cf4 balrog
{
652 811d4cf4 balrog
    if (im >= 0)
653 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x01d000b0 |
654 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
655 811d4cf4 balrog
                        ((im & 0xf0) << 4) | (im & 0xf));
656 811d4cf4 balrog
    else
657 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x015000b0 |
658 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
659 811d4cf4 balrog
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
660 811d4cf4 balrog
}
661 811d4cf4 balrog
662 f694a27e Aurelien Jarno
static inline void tcg_out_st16_8(TCGContext *s, int cond,
663 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
664 811d4cf4 balrog
{
665 811d4cf4 balrog
    if (im >= 0)
666 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x01c000b0 |
667 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
668 811d4cf4 balrog
                        ((im & 0xf0) << 4) | (im & 0xf));
669 811d4cf4 balrog
    else
670 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x014000b0 |
671 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
672 811d4cf4 balrog
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
673 811d4cf4 balrog
}
674 811d4cf4 balrog
675 811d4cf4 balrog
static inline void tcg_out_ld16u_r(TCGContext *s, int cond,
676 811d4cf4 balrog
                int rd, int rn, int rm)
677 811d4cf4 balrog
{
678 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x019000b0 |
679 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
680 811d4cf4 balrog
}
681 811d4cf4 balrog
682 f694a27e Aurelien Jarno
static inline void tcg_out_st16_r(TCGContext *s, int cond,
683 811d4cf4 balrog
                int rd, int rn, int rm)
684 811d4cf4 balrog
{
685 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x018000b0 |
686 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
687 811d4cf4 balrog
}
688 811d4cf4 balrog
689 811d4cf4 balrog
static inline void tcg_out_ld16s_8(TCGContext *s, int cond,
690 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
691 811d4cf4 balrog
{
692 811d4cf4 balrog
    if (im >= 0)
693 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x01d000f0 |
694 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
695 811d4cf4 balrog
                        ((im & 0xf0) << 4) | (im & 0xf));
696 811d4cf4 balrog
    else
697 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x015000f0 |
698 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
699 811d4cf4 balrog
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
700 811d4cf4 balrog
}
701 811d4cf4 balrog
702 811d4cf4 balrog
static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
703 811d4cf4 balrog
                int rd, int rn, int rm)
704 811d4cf4 balrog
{
705 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x019000f0 |
706 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
707 811d4cf4 balrog
}
708 811d4cf4 balrog
709 811d4cf4 balrog
static inline void tcg_out_ld8_12(TCGContext *s, int cond,
710 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
711 811d4cf4 balrog
{
712 811d4cf4 balrog
    if (im >= 0)
713 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05d00000 |
714 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | (im & 0xfff));
715 811d4cf4 balrog
    else
716 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05500000 |
717 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
718 811d4cf4 balrog
}
719 811d4cf4 balrog
720 811d4cf4 balrog
static inline void tcg_out_st8_12(TCGContext *s, int cond,
721 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
722 811d4cf4 balrog
{
723 811d4cf4 balrog
    if (im >= 0)
724 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05c00000 |
725 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | (im & 0xfff));
726 811d4cf4 balrog
    else
727 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x05400000 |
728 811d4cf4 balrog
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
729 811d4cf4 balrog
}
730 811d4cf4 balrog
731 811d4cf4 balrog
static inline void tcg_out_ld8_r(TCGContext *s, int cond,
732 811d4cf4 balrog
                int rd, int rn, int rm)
733 811d4cf4 balrog
{
734 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x07d00000 |
735 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
736 811d4cf4 balrog
}
737 811d4cf4 balrog
738 811d4cf4 balrog
static inline void tcg_out_st8_r(TCGContext *s, int cond,
739 811d4cf4 balrog
                int rd, int rn, int rm)
740 811d4cf4 balrog
{
741 811d4cf4 balrog
    tcg_out32(s, (cond << 28) | 0x07c00000 |
742 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
743 811d4cf4 balrog
}
744 811d4cf4 balrog
745 811d4cf4 balrog
static inline void tcg_out_ld8s_8(TCGContext *s, int cond,
746 811d4cf4 balrog
                int rd, int rn, tcg_target_long im)
747 811d4cf4 balrog
{
748 811d4cf4 balrog
    if (im >= 0)
749 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x01d000d0 |
750 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
751 811d4cf4 balrog
                        ((im & 0xf0) << 4) | (im & 0xf));
752 811d4cf4 balrog
    else
753 811d4cf4 balrog
        tcg_out32(s, (cond << 28) | 0x015000d0 |
754 811d4cf4 balrog
                        (rn << 16) | (rd << 12) |
755 811d4cf4 balrog
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
756 811d4cf4 balrog
}
757 811d4cf4 balrog
758 811d4cf4 balrog
static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
759 811d4cf4 balrog
                int rd, int rn, int rm)
760 811d4cf4 balrog
{
761 204c1674 balrog
    tcg_out32(s, (cond << 28) | 0x019000d0 |
762 811d4cf4 balrog
                    (rn << 16) | (rd << 12) | rm);
763 811d4cf4 balrog
}
764 811d4cf4 balrog
765 811d4cf4 balrog
static inline void tcg_out_ld32u(TCGContext *s, int cond,
766 811d4cf4 balrog
                int rd, int rn, int32_t offset)
767 811d4cf4 balrog
{
768 811d4cf4 balrog
    if (offset > 0xfff || offset < -0xfff) {
769 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
770 811d4cf4 balrog
        tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_R8);
771 811d4cf4 balrog
    } else
772 811d4cf4 balrog
        tcg_out_ld32_12(s, cond, rd, rn, offset);
773 811d4cf4 balrog
}
774 811d4cf4 balrog
775 811d4cf4 balrog
static inline void tcg_out_st32(TCGContext *s, int cond,
776 811d4cf4 balrog
                int rd, int rn, int32_t offset)
777 811d4cf4 balrog
{
778 811d4cf4 balrog
    if (offset > 0xfff || offset < -0xfff) {
779 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
780 811d4cf4 balrog
        tcg_out_st32_r(s, cond, rd, rn, TCG_REG_R8);
781 811d4cf4 balrog
    } else
782 811d4cf4 balrog
        tcg_out_st32_12(s, cond, rd, rn, offset);
783 811d4cf4 balrog
}
784 811d4cf4 balrog
785 811d4cf4 balrog
static inline void tcg_out_ld16u(TCGContext *s, int cond,
786 811d4cf4 balrog
                int rd, int rn, int32_t offset)
787 811d4cf4 balrog
{
788 811d4cf4 balrog
    if (offset > 0xff || offset < -0xff) {
789 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
790 811d4cf4 balrog
        tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_R8);
791 811d4cf4 balrog
    } else
792 811d4cf4 balrog
        tcg_out_ld16u_8(s, cond, rd, rn, offset);
793 811d4cf4 balrog
}
794 811d4cf4 balrog
795 811d4cf4 balrog
static inline void tcg_out_ld16s(TCGContext *s, int cond,
796 811d4cf4 balrog
                int rd, int rn, int32_t offset)
797 811d4cf4 balrog
{
798 811d4cf4 balrog
    if (offset > 0xff || offset < -0xff) {
799 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
800 811d4cf4 balrog
        tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_R8);
801 811d4cf4 balrog
    } else
802 811d4cf4 balrog
        tcg_out_ld16s_8(s, cond, rd, rn, offset);
803 811d4cf4 balrog
}
804 811d4cf4 balrog
805 f694a27e Aurelien Jarno
static inline void tcg_out_st16(TCGContext *s, int cond,
806 811d4cf4 balrog
                int rd, int rn, int32_t offset)
807 811d4cf4 balrog
{
808 811d4cf4 balrog
    if (offset > 0xff || offset < -0xff) {
809 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
810 f694a27e Aurelien Jarno
        tcg_out_st16_r(s, cond, rd, rn, TCG_REG_R8);
811 811d4cf4 balrog
    } else
812 f694a27e Aurelien Jarno
        tcg_out_st16_8(s, cond, rd, rn, offset);
813 811d4cf4 balrog
}
814 811d4cf4 balrog
815 811d4cf4 balrog
static inline void tcg_out_ld8u(TCGContext *s, int cond,
816 811d4cf4 balrog
                int rd, int rn, int32_t offset)
817 811d4cf4 balrog
{
818 811d4cf4 balrog
    if (offset > 0xfff || offset < -0xfff) {
819 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
820 811d4cf4 balrog
        tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_R8);
821 811d4cf4 balrog
    } else
822 811d4cf4 balrog
        tcg_out_ld8_12(s, cond, rd, rn, offset);
823 811d4cf4 balrog
}
824 811d4cf4 balrog
825 811d4cf4 balrog
static inline void tcg_out_ld8s(TCGContext *s, int cond,
826 811d4cf4 balrog
                int rd, int rn, int32_t offset)
827 811d4cf4 balrog
{
828 811d4cf4 balrog
    if (offset > 0xff || offset < -0xff) {
829 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
830 811d4cf4 balrog
        tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_R8);
831 811d4cf4 balrog
    } else
832 811d4cf4 balrog
        tcg_out_ld8s_8(s, cond, rd, rn, offset);
833 811d4cf4 balrog
}
834 811d4cf4 balrog
835 f694a27e Aurelien Jarno
static inline void tcg_out_st8(TCGContext *s, int cond,
836 811d4cf4 balrog
                int rd, int rn, int32_t offset)
837 811d4cf4 balrog
{
838 811d4cf4 balrog
    if (offset > 0xfff || offset < -0xfff) {
839 811d4cf4 balrog
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
840 811d4cf4 balrog
        tcg_out_st8_r(s, cond, rd, rn, TCG_REG_R8);
841 811d4cf4 balrog
    } else
842 811d4cf4 balrog
        tcg_out_st8_12(s, cond, rd, rn, offset);
843 811d4cf4 balrog
}
844 811d4cf4 balrog
845 811d4cf4 balrog
static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
846 811d4cf4 balrog
{
847 811d4cf4 balrog
    int32_t val;
848 811d4cf4 balrog
849 24e838b7 Peter Maydell
    if (addr & 1) {
850 24e838b7 Peter Maydell
        /* goto to a Thumb destination isn't supported */
851 24e838b7 Peter Maydell
        tcg_abort();
852 24e838b7 Peter Maydell
    }
853 24e838b7 Peter Maydell
854 811d4cf4 balrog
    val = addr - (tcg_target_long) s->code_ptr;
855 811d4cf4 balrog
    if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
856 811d4cf4 balrog
        tcg_out_b(s, cond, val);
857 811d4cf4 balrog
    else {
858 811d4cf4 balrog
#if 1
859 811d4cf4 balrog
        tcg_abort();
860 811d4cf4 balrog
#else
861 811d4cf4 balrog
        if (cond == COND_AL) {
862 c8d80cef Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
863 811d4cf4 balrog
            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
864 811d4cf4 balrog
        } else {
865 811d4cf4 balrog
            tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
866 811d4cf4 balrog
            tcg_out_dat_reg(s, cond, ARITH_ADD,
867 c8d80cef Aurelien Jarno
                            TCG_REG_PC, TCG_REG_PC,
868 c8d80cef Aurelien Jarno
                            TCG_REG_R8, SHIFT_IMM_LSL(0));
869 811d4cf4 balrog
        }
870 811d4cf4 balrog
#endif
871 811d4cf4 balrog
    }
872 811d4cf4 balrog
}
873 811d4cf4 balrog
874 24e838b7 Peter Maydell
static inline void tcg_out_call(TCGContext *s, uint32_t addr)
875 811d4cf4 balrog
{
876 811d4cf4 balrog
    int32_t val;
877 811d4cf4 balrog
878 811d4cf4 balrog
    val = addr - (tcg_target_long) s->code_ptr;
879 24e838b7 Peter Maydell
    if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
880 24e838b7 Peter Maydell
        if (addr & 1) {
881 24e838b7 Peter Maydell
            /* Use BLX if the target is in Thumb mode */
882 24e838b7 Peter Maydell
            if (!use_armv5_instructions) {
883 24e838b7 Peter Maydell
                tcg_abort();
884 24e838b7 Peter Maydell
            }
885 24e838b7 Peter Maydell
            tcg_out_blx_imm(s, val);
886 24e838b7 Peter Maydell
        } else {
887 24e838b7 Peter Maydell
            tcg_out_bl(s, COND_AL, val);
888 24e838b7 Peter Maydell
        }
889 24e838b7 Peter Maydell
    } else {
890 811d4cf4 balrog
#if 1
891 811d4cf4 balrog
        tcg_abort();
892 811d4cf4 balrog
#else
893 811d4cf4 balrog
        if (cond == COND_AL) {
894 c8d80cef Aurelien Jarno
            tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
895 c8d80cef Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
896 811d4cf4 balrog
            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
897 811d4cf4 balrog
        } else {
898 811d4cf4 balrog
            tcg_out_movi32(s, cond, TCG_REG_R9, addr);
899 c8d80cef Aurelien Jarno
            tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
900 c8d80cef Aurelien Jarno
                            TCG_REG_PC, SHIFT_IMM_LSL(0));
901 811d4cf4 balrog
            tcg_out_bx(s, cond, TCG_REG_R9);
902 811d4cf4 balrog
        }
903 811d4cf4 balrog
#endif
904 811d4cf4 balrog
    }
905 811d4cf4 balrog
}
906 811d4cf4 balrog
907 811d4cf4 balrog
static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
908 811d4cf4 balrog
{
909 23401b58 Aurelien Jarno
    if (use_armv5_instructions) {
910 23401b58 Aurelien Jarno
        tcg_out_blx(s, cond, arg);
911 23401b58 Aurelien Jarno
    } else {
912 23401b58 Aurelien Jarno
        tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
913 23401b58 Aurelien Jarno
                        TCG_REG_PC, SHIFT_IMM_LSL(0));
914 23401b58 Aurelien Jarno
        tcg_out_bx(s, cond, arg);
915 23401b58 Aurelien Jarno
    }
916 811d4cf4 balrog
}
917 811d4cf4 balrog
918 811d4cf4 balrog
static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
919 811d4cf4 balrog
{
920 811d4cf4 balrog
    TCGLabel *l = &s->labels[label_index];
921 811d4cf4 balrog
922 811d4cf4 balrog
    if (l->has_value)
923 811d4cf4 balrog
        tcg_out_goto(s, cond, l->u.value);
924 811d4cf4 balrog
    else if (cond == COND_AL) {
925 c8d80cef Aurelien Jarno
        tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
926 811d4cf4 balrog
        tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
927 811d4cf4 balrog
        s->code_ptr += 4;
928 811d4cf4 balrog
    } else {
929 811d4cf4 balrog
        /* Probably this should be preferred even for COND_AL... */
930 811d4cf4 balrog
        tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
931 e936243a balrog
        tcg_out_b_noaddr(s, cond);
932 811d4cf4 balrog
    }
933 811d4cf4 balrog
}
934 811d4cf4 balrog
935 811d4cf4 balrog
#ifdef CONFIG_SOFTMMU
936 79383c9c blueswir1
937 79383c9c blueswir1
#include "../../softmmu_defs.h"
938 811d4cf4 balrog
939 811d4cf4 balrog
static void *qemu_ld_helpers[4] = {
940 811d4cf4 balrog
    __ldb_mmu,
941 811d4cf4 balrog
    __ldw_mmu,
942 811d4cf4 balrog
    __ldl_mmu,
943 811d4cf4 balrog
    __ldq_mmu,
944 811d4cf4 balrog
};
945 811d4cf4 balrog
946 811d4cf4 balrog
static void *qemu_st_helpers[4] = {
947 811d4cf4 balrog
    __stb_mmu,
948 811d4cf4 balrog
    __stw_mmu,
949 811d4cf4 balrog
    __stl_mmu,
950 811d4cf4 balrog
    __stq_mmu,
951 811d4cf4 balrog
};
952 811d4cf4 balrog
#endif
953 811d4cf4 balrog
954 3979144c pbrook
#define TLB_SHIFT        (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
955 3979144c pbrook
956 7e0d9562 Aurelien Jarno
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
957 811d4cf4 balrog
{
958 67dcab73 Aurelien Jarno
    int addr_reg, data_reg, data_reg2, bswap;
959 811d4cf4 balrog
#ifdef CONFIG_SOFTMMU
960 811d4cf4 balrog
    int mem_index, s_bits;
961 811d4cf4 balrog
# if TARGET_LONG_BITS == 64
962 811d4cf4 balrog
    int addr_reg2;
963 811d4cf4 balrog
# endif
964 811d4cf4 balrog
    uint32_t *label_ptr;
965 811d4cf4 balrog
#endif
966 811d4cf4 balrog
967 67dcab73 Aurelien Jarno
#ifdef TARGET_WORDS_BIGENDIAN
968 67dcab73 Aurelien Jarno
    bswap = 1;
969 67dcab73 Aurelien Jarno
#else
970 67dcab73 Aurelien Jarno
    bswap = 0;
971 67dcab73 Aurelien Jarno
#endif
972 811d4cf4 balrog
    data_reg = *args++;
973 811d4cf4 balrog
    if (opc == 3)
974 811d4cf4 balrog
        data_reg2 = *args++;
975 811d4cf4 balrog
    else
976 d89c682f Stefan Weil
        data_reg2 = 0; /* suppress warning */
977 811d4cf4 balrog
    addr_reg = *args++;
978 811d4cf4 balrog
#ifdef CONFIG_SOFTMMU
979 aef3a282 balrog
# if TARGET_LONG_BITS == 64
980 aef3a282 balrog
    addr_reg2 = *args++;
981 aef3a282 balrog
# endif
982 811d4cf4 balrog
    mem_index = *args;
983 811d4cf4 balrog
    s_bits = opc & 3;
984 811d4cf4 balrog
985 91a3c1b0 balrog
    /* Should generate something like the following:
986 3979144c pbrook
     *  shr r8, addr_reg, #TARGET_PAGE_BITS
987 91a3c1b0 balrog
     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
988 3979144c pbrook
     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
989 91a3c1b0 balrog
     */
990 91a3c1b0 balrog
#  if CPU_TLB_BITS > 8
991 91a3c1b0 balrog
#   error
992 91a3c1b0 balrog
#  endif
993 c8d80cef Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_R8,
994 c8d80cef Aurelien Jarno
                    0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
995 811d4cf4 balrog
    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
996 c8d80cef Aurelien Jarno
                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
997 c8d80cef Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
998 c8d80cef Aurelien Jarno
                    TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
999 91a3c1b0 balrog
    /* In the
1000 91a3c1b0 balrog
     *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_read))]
1001 91a3c1b0 balrog
     * below, the offset is likely to exceed 12 bits if mem_index != 0 and
1002 91a3c1b0 balrog
     * not exceed otherwise, so use an
1003 91a3c1b0 balrog
     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
1004 91a3c1b0 balrog
     * before.
1005 91a3c1b0 balrog
     */
1006 225b4376 balrog
    if (mem_index)
1007 c8d80cef Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1008 225b4376 balrog
                        (mem_index << (TLB_SHIFT & 1)) |
1009 225b4376 balrog
                        ((16 - (TLB_SHIFT >> 1)) << 8));
1010 c8d80cef Aurelien Jarno
    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1011 225b4376 balrog
                    offsetof(CPUState, tlb_table[0][0].addr_read));
1012 c8d80cef Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
1013 c8d80cef Aurelien Jarno
                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1014 3979144c pbrook
    /* Check alignment.  */
1015 3979144c pbrook
    if (s_bits)
1016 3979144c pbrook
        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1017 3979144c pbrook
                        0, addr_reg, (1 << s_bits) - 1);
1018 811d4cf4 balrog
#  if TARGET_LONG_BITS == 64
1019 811d4cf4 balrog
    /* XXX: possibly we could use a block data load or writeback in
1020 811d4cf4 balrog
     * the first access.  */
1021 c8d80cef Aurelien Jarno
    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1022 225b4376 balrog
                    offsetof(CPUState, tlb_table[0][0].addr_read) + 4);
1023 c8d80cef Aurelien Jarno
    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1024 c8d80cef Aurelien Jarno
                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1025 811d4cf4 balrog
#  endif
1026 c8d80cef Aurelien Jarno
    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1027 225b4376 balrog
                    offsetof(CPUState, tlb_table[0][0].addend));
1028 811d4cf4 balrog
1029 811d4cf4 balrog
    switch (opc) {
1030 811d4cf4 balrog
    case 0:
1031 c8d80cef Aurelien Jarno
        tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1032 811d4cf4 balrog
        break;
1033 811d4cf4 balrog
    case 0 | 4:
1034 c8d80cef Aurelien Jarno
        tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1035 811d4cf4 balrog
        break;
1036 811d4cf4 balrog
    case 1:
1037 c8d80cef Aurelien Jarno
        tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1038 67dcab73 Aurelien Jarno
        if (bswap) {
1039 67dcab73 Aurelien Jarno
            tcg_out_bswap16(s, COND_EQ, data_reg, data_reg);
1040 67dcab73 Aurelien Jarno
        }
1041 811d4cf4 balrog
        break;
1042 811d4cf4 balrog
    case 1 | 4:
1043 67dcab73 Aurelien Jarno
        if (bswap) {
1044 67dcab73 Aurelien Jarno
            tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1045 67dcab73 Aurelien Jarno
            tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg);
1046 67dcab73 Aurelien Jarno
        } else {
1047 67dcab73 Aurelien Jarno
            tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1048 67dcab73 Aurelien Jarno
        }
1049 811d4cf4 balrog
        break;
1050 811d4cf4 balrog
    case 2:
1051 811d4cf4 balrog
    default:
1052 c8d80cef Aurelien Jarno
        tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1053 67dcab73 Aurelien Jarno
        if (bswap) {
1054 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
1055 67dcab73 Aurelien Jarno
        }
1056 811d4cf4 balrog
        break;
1057 811d4cf4 balrog
    case 3:
1058 67dcab73 Aurelien Jarno
        if (bswap) {
1059 67dcab73 Aurelien Jarno
            tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg);
1060 67dcab73 Aurelien Jarno
            tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
1061 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2);
1062 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
1063 67dcab73 Aurelien Jarno
        } else {
1064 67dcab73 Aurelien Jarno
            tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
1065 67dcab73 Aurelien Jarno
            tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
1066 67dcab73 Aurelien Jarno
        }
1067 811d4cf4 balrog
        break;
1068 811d4cf4 balrog
    }
1069 811d4cf4 balrog
1070 811d4cf4 balrog
    label_ptr = (void *) s->code_ptr;
1071 c69806ab Aurelien Jarno
    tcg_out_b_noaddr(s, COND_EQ);
1072 811d4cf4 balrog
1073 811d4cf4 balrog
    /* TODO: move this code to where the constants pool will be */
1074 c8d80cef Aurelien Jarno
    if (addr_reg != TCG_REG_R0) {
1075 7e0d9562 Aurelien Jarno
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1076 c8d80cef Aurelien Jarno
                        TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
1077 c8d80cef Aurelien Jarno
    }
1078 811d4cf4 balrog
# if TARGET_LONG_BITS == 32
1079 7e0d9562 Aurelien Jarno
    tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index);
1080 811d4cf4 balrog
# else
1081 2633a2d0 Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1082 2633a2d0 Aurelien Jarno
                    TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1083 7e0d9562 Aurelien Jarno
    tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1084 811d4cf4 balrog
# endif
1085 24e838b7 Peter Maydell
    tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
1086 811d4cf4 balrog
1087 811d4cf4 balrog
    switch (opc) {
1088 811d4cf4 balrog
    case 0 | 4:
1089 e854b6d3 Aurelien Jarno
        tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
1090 811d4cf4 balrog
        break;
1091 811d4cf4 balrog
    case 1 | 4:
1092 e854b6d3 Aurelien Jarno
        tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
1093 811d4cf4 balrog
        break;
1094 811d4cf4 balrog
    case 0:
1095 811d4cf4 balrog
    case 1:
1096 811d4cf4 balrog
    case 2:
1097 811d4cf4 balrog
    default:
1098 c8d80cef Aurelien Jarno
        if (data_reg != TCG_REG_R0) {
1099 7e0d9562 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1100 c8d80cef Aurelien Jarno
                            data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
1101 c8d80cef Aurelien Jarno
        }
1102 811d4cf4 balrog
        break;
1103 811d4cf4 balrog
    case 3:
1104 c8d80cef Aurelien Jarno
        if (data_reg != TCG_REG_R0) {
1105 7e0d9562 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1106 c8d80cef Aurelien Jarno
                            data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
1107 c8d80cef Aurelien Jarno
        }
1108 c8d80cef Aurelien Jarno
        if (data_reg2 != TCG_REG_R1) {
1109 7e0d9562 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1110 c8d80cef Aurelien Jarno
                            data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0));
1111 c8d80cef Aurelien Jarno
        }
1112 811d4cf4 balrog
        break;
1113 811d4cf4 balrog
    }
1114 811d4cf4 balrog
1115 c69806ab Aurelien Jarno
    reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1116 379f6698 Paul Brook
#else /* !CONFIG_SOFTMMU */
1117 379f6698 Paul Brook
    if (GUEST_BASE) {
1118 379f6698 Paul Brook
        uint32_t offset = GUEST_BASE;
1119 379f6698 Paul Brook
        int i;
1120 379f6698 Paul Brook
        int rot;
1121 379f6698 Paul Brook
1122 379f6698 Paul Brook
        while (offset) {
1123 379f6698 Paul Brook
            i = ctz32(offset) & ~1;
1124 379f6698 Paul Brook
            rot = ((32 - i) << 7) & 0xf00;
1125 379f6698 Paul Brook
1126 c8d80cef Aurelien Jarno
            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
1127 379f6698 Paul Brook
                            ((offset >> i) & 0xff) | rot);
1128 c8d80cef Aurelien Jarno
            addr_reg = TCG_REG_R8;
1129 379f6698 Paul Brook
            offset &= ~(0xff << i);
1130 379f6698 Paul Brook
        }
1131 379f6698 Paul Brook
    }
1132 811d4cf4 balrog
    switch (opc) {
1133 811d4cf4 balrog
    case 0:
1134 811d4cf4 balrog
        tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
1135 811d4cf4 balrog
        break;
1136 811d4cf4 balrog
    case 0 | 4:
1137 811d4cf4 balrog
        tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
1138 811d4cf4 balrog
        break;
1139 811d4cf4 balrog
    case 1:
1140 811d4cf4 balrog
        tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1141 67dcab73 Aurelien Jarno
        if (bswap) {
1142 67dcab73 Aurelien Jarno
            tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
1143 67dcab73 Aurelien Jarno
        }
1144 811d4cf4 balrog
        break;
1145 811d4cf4 balrog
    case 1 | 4:
1146 67dcab73 Aurelien Jarno
        if (bswap) {
1147 67dcab73 Aurelien Jarno
            tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1148 67dcab73 Aurelien Jarno
            tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
1149 67dcab73 Aurelien Jarno
        } else {
1150 67dcab73 Aurelien Jarno
            tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
1151 67dcab73 Aurelien Jarno
        }
1152 811d4cf4 balrog
        break;
1153 811d4cf4 balrog
    case 2:
1154 811d4cf4 balrog
    default:
1155 811d4cf4 balrog
        tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1156 67dcab73 Aurelien Jarno
        if (bswap) {
1157 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1158 67dcab73 Aurelien Jarno
        }
1159 811d4cf4 balrog
        break;
1160 811d4cf4 balrog
    case 3:
1161 eae6ce52 balrog
        /* TODO: use block load -
1162 eae6ce52 balrog
         * check that data_reg2 > data_reg or the other way */
1163 419bafa5 aurel32
        if (data_reg == addr_reg) {
1164 67dcab73 Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1165 67dcab73 Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1166 419bafa5 aurel32
        } else {
1167 67dcab73 Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1168 67dcab73 Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1169 67dcab73 Aurelien Jarno
        }
1170 67dcab73 Aurelien Jarno
        if (bswap) {
1171 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1172 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
1173 419bafa5 aurel32
        }
1174 811d4cf4 balrog
        break;
1175 811d4cf4 balrog
    }
1176 811d4cf4 balrog
#endif
1177 811d4cf4 balrog
}
1178 811d4cf4 balrog
1179 7e0d9562 Aurelien Jarno
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
1180 811d4cf4 balrog
{
1181 67dcab73 Aurelien Jarno
    int addr_reg, data_reg, data_reg2, bswap;
1182 811d4cf4 balrog
#ifdef CONFIG_SOFTMMU
1183 811d4cf4 balrog
    int mem_index, s_bits;
1184 811d4cf4 balrog
# if TARGET_LONG_BITS == 64
1185 811d4cf4 balrog
    int addr_reg2;
1186 811d4cf4 balrog
# endif
1187 811d4cf4 balrog
    uint32_t *label_ptr;
1188 811d4cf4 balrog
#endif
1189 811d4cf4 balrog
1190 67dcab73 Aurelien Jarno
#ifdef TARGET_WORDS_BIGENDIAN
1191 67dcab73 Aurelien Jarno
    bswap = 1;
1192 67dcab73 Aurelien Jarno
#else
1193 67dcab73 Aurelien Jarno
    bswap = 0;
1194 67dcab73 Aurelien Jarno
#endif
1195 811d4cf4 balrog
    data_reg = *args++;
1196 811d4cf4 balrog
    if (opc == 3)
1197 811d4cf4 balrog
        data_reg2 = *args++;
1198 811d4cf4 balrog
    else
1199 d89c682f Stefan Weil
        data_reg2 = 0; /* suppress warning */
1200 811d4cf4 balrog
    addr_reg = *args++;
1201 811d4cf4 balrog
#ifdef CONFIG_SOFTMMU
1202 aef3a282 balrog
# if TARGET_LONG_BITS == 64
1203 aef3a282 balrog
    addr_reg2 = *args++;
1204 aef3a282 balrog
# endif
1205 811d4cf4 balrog
    mem_index = *args;
1206 811d4cf4 balrog
    s_bits = opc & 3;
1207 811d4cf4 balrog
1208 91a3c1b0 balrog
    /* Should generate something like the following:
1209 3979144c pbrook
     *  shr r8, addr_reg, #TARGET_PAGE_BITS
1210 91a3c1b0 balrog
     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
1211 3979144c pbrook
     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1212 91a3c1b0 balrog
     */
1213 811d4cf4 balrog
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1214 c8d80cef Aurelien Jarno
                    TCG_REG_R8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1215 811d4cf4 balrog
    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1216 c8d80cef Aurelien Jarno
                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
1217 c8d80cef Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
1218 c8d80cef Aurelien Jarno
                    TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1219 91a3c1b0 balrog
    /* In the
1220 91a3c1b0 balrog
     *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
1221 91a3c1b0 balrog
     * below, the offset is likely to exceed 12 bits if mem_index != 0 and
1222 91a3c1b0 balrog
     * not exceed otherwise, so use an
1223 91a3c1b0 balrog
     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
1224 91a3c1b0 balrog
     * before.
1225 91a3c1b0 balrog
     */
1226 225b4376 balrog
    if (mem_index)
1227 c8d80cef Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1228 225b4376 balrog
                        (mem_index << (TLB_SHIFT & 1)) |
1229 225b4376 balrog
                        ((16 - (TLB_SHIFT >> 1)) << 8));
1230 c8d80cef Aurelien Jarno
    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1231 225b4376 balrog
                    offsetof(CPUState, tlb_table[0][0].addr_write));
1232 c8d80cef Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
1233 c8d80cef Aurelien Jarno
                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1234 3979144c pbrook
    /* Check alignment.  */
1235 3979144c pbrook
    if (s_bits)
1236 3979144c pbrook
        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1237 3979144c pbrook
                        0, addr_reg, (1 << s_bits) - 1);
1238 811d4cf4 balrog
#  if TARGET_LONG_BITS == 64
1239 811d4cf4 balrog
    /* XXX: possibly we could use a block data load or writeback in
1240 811d4cf4 balrog
     * the first access.  */
1241 c8d80cef Aurelien Jarno
    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1242 c8d80cef Aurelien Jarno
                    offsetof(CPUState, tlb_table[0][0].addr_write) + 4);
1243 c8d80cef Aurelien Jarno
    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1244 c8d80cef Aurelien Jarno
                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1245 811d4cf4 balrog
#  endif
1246 c8d80cef Aurelien Jarno
    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1247 225b4376 balrog
                    offsetof(CPUState, tlb_table[0][0].addend));
1248 811d4cf4 balrog
1249 811d4cf4 balrog
    switch (opc) {
1250 811d4cf4 balrog
    case 0:
1251 c8d80cef Aurelien Jarno
        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1252 811d4cf4 balrog
        break;
1253 811d4cf4 balrog
    case 1:
1254 67dcab73 Aurelien Jarno
        if (bswap) {
1255 67dcab73 Aurelien Jarno
            tcg_out_bswap16(s, COND_EQ, TCG_REG_R0, data_reg);
1256 67dcab73 Aurelien Jarno
            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
1257 67dcab73 Aurelien Jarno
        } else {
1258 67dcab73 Aurelien Jarno
            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1259 67dcab73 Aurelien Jarno
        }
1260 811d4cf4 balrog
        break;
1261 811d4cf4 balrog
    case 2:
1262 811d4cf4 balrog
    default:
1263 67dcab73 Aurelien Jarno
        if (bswap) {
1264 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1265 67dcab73 Aurelien Jarno
            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
1266 67dcab73 Aurelien Jarno
        } else {
1267 67dcab73 Aurelien Jarno
            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1268 67dcab73 Aurelien Jarno
        }
1269 811d4cf4 balrog
        break;
1270 811d4cf4 balrog
    case 3:
1271 67dcab73 Aurelien Jarno
        if (bswap) {
1272 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
1273 67dcab73 Aurelien Jarno
            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
1274 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1275 9a3abc21 Aurelien Jarno
            tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
1276 67dcab73 Aurelien Jarno
        } else {
1277 67dcab73 Aurelien Jarno
            tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
1278 67dcab73 Aurelien Jarno
            tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
1279 67dcab73 Aurelien Jarno
        }
1280 811d4cf4 balrog
        break;
1281 811d4cf4 balrog
    }
1282 811d4cf4 balrog
1283 811d4cf4 balrog
    label_ptr = (void *) s->code_ptr;
1284 c69806ab Aurelien Jarno
    tcg_out_b_noaddr(s, COND_EQ);
1285 811d4cf4 balrog
1286 811d4cf4 balrog
    /* TODO: move this code to where the constants pool will be */
1287 2633a2d0 Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1288 2633a2d0 Aurelien Jarno
                    TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
1289 811d4cf4 balrog
# if TARGET_LONG_BITS == 32
1290 811d4cf4 balrog
    switch (opc) {
1291 811d4cf4 balrog
    case 0:
1292 e854b6d3 Aurelien Jarno
        tcg_out_ext8u(s, COND_AL, TCG_REG_R1, data_reg);
1293 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1294 811d4cf4 balrog
        break;
1295 811d4cf4 balrog
    case 1:
1296 e854b6d3 Aurelien Jarno
        tcg_out_ext16u(s, COND_AL, TCG_REG_R1, data_reg);
1297 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1298 811d4cf4 balrog
        break;
1299 811d4cf4 balrog
    case 2:
1300 2633a2d0 Aurelien Jarno
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1301 2633a2d0 Aurelien Jarno
                        TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
1302 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1303 811d4cf4 balrog
        break;
1304 811d4cf4 balrog
    case 3:
1305 bf5675ef Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
1306 bf5675ef Aurelien Jarno
        tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
1307 bf5675ef Aurelien Jarno
        if (data_reg != TCG_REG_R2) {
1308 7e0d9562 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1309 bf5675ef Aurelien Jarno
                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
1310 bf5675ef Aurelien Jarno
        }
1311 bf5675ef Aurelien Jarno
        if (data_reg2 != TCG_REG_R3) {
1312 bf5675ef Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1313 bf5675ef Aurelien Jarno
                            TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
1314 c8d80cef Aurelien Jarno
        }
1315 811d4cf4 balrog
        break;
1316 811d4cf4 balrog
    }
1317 811d4cf4 balrog
# else
1318 2633a2d0 Aurelien Jarno
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1319 2633a2d0 Aurelien Jarno
                    TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1320 811d4cf4 balrog
    switch (opc) {
1321 811d4cf4 balrog
    case 0:
1322 e854b6d3 Aurelien Jarno
        tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg);
1323 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1324 811d4cf4 balrog
        break;
1325 811d4cf4 balrog
    case 1:
1326 e854b6d3 Aurelien Jarno
        tcg_out_ext16u(s, COND_AL, TCG_REG_R2, data_reg);
1327 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1328 811d4cf4 balrog
        break;
1329 811d4cf4 balrog
    case 2:
1330 c8d80cef Aurelien Jarno
        if (data_reg != TCG_REG_R2) {
1331 7e0d9562 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1332 c8d80cef Aurelien Jarno
                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
1333 c8d80cef Aurelien Jarno
        }
1334 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1335 811d4cf4 balrog
        break;
1336 811d4cf4 balrog
    case 3:
1337 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
1338 7e0d9562 Aurelien Jarno
        tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
1339 c8d80cef Aurelien Jarno
        if (data_reg != TCG_REG_R2) {
1340 7e0d9562 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1341 c8d80cef Aurelien Jarno
                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
1342 c8d80cef Aurelien Jarno
        }
1343 c8d80cef Aurelien Jarno
        if (data_reg2 != TCG_REG_R3) {
1344 7e0d9562 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1345 c8d80cef Aurelien Jarno
                            TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
1346 c8d80cef Aurelien Jarno
        }
1347 811d4cf4 balrog
        break;
1348 811d4cf4 balrog
    }
1349 811d4cf4 balrog
# endif
1350 811d4cf4 balrog
1351 24e838b7 Peter Maydell
    tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
1352 811d4cf4 balrog
    if (opc == 3)
1353 7e0d9562 Aurelien Jarno
        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
1354 811d4cf4 balrog
1355 c69806ab Aurelien Jarno
    reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1356 379f6698 Paul Brook
#else /* !CONFIG_SOFTMMU */
1357 379f6698 Paul Brook
    if (GUEST_BASE) {
1358 379f6698 Paul Brook
        uint32_t offset = GUEST_BASE;
1359 379f6698 Paul Brook
        int i;
1360 379f6698 Paul Brook
        int rot;
1361 379f6698 Paul Brook
1362 379f6698 Paul Brook
        while (offset) {
1363 379f6698 Paul Brook
            i = ctz32(offset) & ~1;
1364 379f6698 Paul Brook
            rot = ((32 - i) << 7) & 0xf00;
1365 379f6698 Paul Brook
1366 67dcab73 Aurelien Jarno
            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
1367 379f6698 Paul Brook
                            ((offset >> i) & 0xff) | rot);
1368 67dcab73 Aurelien Jarno
            addr_reg = TCG_REG_R1;
1369 379f6698 Paul Brook
            offset &= ~(0xff << i);
1370 379f6698 Paul Brook
        }
1371 379f6698 Paul Brook
    }
1372 811d4cf4 balrog
    switch (opc) {
1373 811d4cf4 balrog
    case 0:
1374 811d4cf4 balrog
        tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
1375 811d4cf4 balrog
        break;
1376 811d4cf4 balrog
    case 1:
1377 67dcab73 Aurelien Jarno
        if (bswap) {
1378 67dcab73 Aurelien Jarno
            tcg_out_bswap16(s, COND_AL, TCG_REG_R0, data_reg);
1379 67dcab73 Aurelien Jarno
            tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1380 67dcab73 Aurelien Jarno
        } else {
1381 67dcab73 Aurelien Jarno
            tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
1382 67dcab73 Aurelien Jarno
        }
1383 811d4cf4 balrog
        break;
1384 811d4cf4 balrog
    case 2:
1385 811d4cf4 balrog
    default:
1386 67dcab73 Aurelien Jarno
        if (bswap) {
1387 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1388 67dcab73 Aurelien Jarno
            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1389 67dcab73 Aurelien Jarno
        } else {
1390 67dcab73 Aurelien Jarno
            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1391 67dcab73 Aurelien Jarno
        }
1392 811d4cf4 balrog
        break;
1393 811d4cf4 balrog
    case 3:
1394 eae6ce52 balrog
        /* TODO: use block store -
1395 eae6ce52 balrog
         * check that data_reg2 > data_reg or the other way */
1396 67dcab73 Aurelien Jarno
        if (bswap) {
1397 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
1398 67dcab73 Aurelien Jarno
            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1399 67dcab73 Aurelien Jarno
            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1400 67dcab73 Aurelien Jarno
            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
1401 67dcab73 Aurelien Jarno
        } else {
1402 67dcab73 Aurelien Jarno
            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1403 67dcab73 Aurelien Jarno
            tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
1404 67dcab73 Aurelien Jarno
        }
1405 811d4cf4 balrog
        break;
1406 811d4cf4 balrog
    }
1407 811d4cf4 balrog
#endif
1408 811d4cf4 balrog
}
1409 811d4cf4 balrog
1410 811d4cf4 balrog
static uint8_t *tb_ret_addr;
1411 811d4cf4 balrog
1412 a9751609 Richard Henderson
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1413 811d4cf4 balrog
                const TCGArg *args, const int *const_args)
1414 811d4cf4 balrog
{
1415 811d4cf4 balrog
    int c;
1416 811d4cf4 balrog
1417 811d4cf4 balrog
    switch (opc) {
1418 811d4cf4 balrog
    case INDEX_op_exit_tb:
1419 fe33867b balrog
        {
1420 fe33867b balrog
            uint8_t *ld_ptr = s->code_ptr;
1421 fe33867b balrog
            if (args[0] >> 8)
1422 c8d80cef Aurelien Jarno
                tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1423 fe33867b balrog
            else
1424 c8d80cef Aurelien Jarno
                tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1425 fe33867b balrog
            tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1426 fe33867b balrog
            if (args[0] >> 8) {
1427 fe33867b balrog
                *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
1428 fe33867b balrog
                tcg_out32(s, args[0]);
1429 fe33867b balrog
            }
1430 fe33867b balrog
        }
1431 811d4cf4 balrog
        break;
1432 811d4cf4 balrog
    case INDEX_op_goto_tb:
1433 811d4cf4 balrog
        if (s->tb_jmp_offset) {
1434 811d4cf4 balrog
            /* Direct jump method */
1435 fe33867b balrog
#if defined(USE_DIRECT_JUMP)
1436 811d4cf4 balrog
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1437 c69806ab Aurelien Jarno
            tcg_out_b_noaddr(s, COND_AL);
1438 811d4cf4 balrog
#else
1439 c8d80cef Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1440 811d4cf4 balrog
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1441 811d4cf4 balrog
            tcg_out32(s, 0);
1442 811d4cf4 balrog
#endif
1443 811d4cf4 balrog
        } else {
1444 811d4cf4 balrog
            /* Indirect jump method */
1445 811d4cf4 balrog
#if 1
1446 811d4cf4 balrog
            c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
1447 811d4cf4 balrog
            if (c > 0xfff || c < -0xfff) {
1448 811d4cf4 balrog
                tcg_out_movi32(s, COND_AL, TCG_REG_R0,
1449 811d4cf4 balrog
                                (tcg_target_long) (s->tb_next + args[0]));
1450 c8d80cef Aurelien Jarno
                tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1451 811d4cf4 balrog
            } else
1452 c8d80cef Aurelien Jarno
                tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
1453 811d4cf4 balrog
#else
1454 c8d80cef Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1455 c8d80cef Aurelien Jarno
            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1456 811d4cf4 balrog
            tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
1457 811d4cf4 balrog
#endif
1458 811d4cf4 balrog
        }
1459 811d4cf4 balrog
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1460 811d4cf4 balrog
        break;
1461 811d4cf4 balrog
    case INDEX_op_call:
1462 811d4cf4 balrog
        if (const_args[0])
1463 24e838b7 Peter Maydell
            tcg_out_call(s, args[0]);
1464 811d4cf4 balrog
        else
1465 811d4cf4 balrog
            tcg_out_callr(s, COND_AL, args[0]);
1466 811d4cf4 balrog
        break;
1467 811d4cf4 balrog
    case INDEX_op_jmp:
1468 811d4cf4 balrog
        if (const_args[0])
1469 811d4cf4 balrog
            tcg_out_goto(s, COND_AL, args[0]);
1470 811d4cf4 balrog
        else
1471 811d4cf4 balrog
            tcg_out_bx(s, COND_AL, args[0]);
1472 811d4cf4 balrog
        break;
1473 811d4cf4 balrog
    case INDEX_op_br:
1474 811d4cf4 balrog
        tcg_out_goto_label(s, COND_AL, args[0]);
1475 811d4cf4 balrog
        break;
1476 811d4cf4 balrog
1477 811d4cf4 balrog
    case INDEX_op_ld8u_i32:
1478 811d4cf4 balrog
        tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1479 811d4cf4 balrog
        break;
1480 811d4cf4 balrog
    case INDEX_op_ld8s_i32:
1481 811d4cf4 balrog
        tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1482 811d4cf4 balrog
        break;
1483 811d4cf4 balrog
    case INDEX_op_ld16u_i32:
1484 811d4cf4 balrog
        tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1485 811d4cf4 balrog
        break;
1486 811d4cf4 balrog
    case INDEX_op_ld16s_i32:
1487 811d4cf4 balrog
        tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1488 811d4cf4 balrog
        break;
1489 811d4cf4 balrog
    case INDEX_op_ld_i32:
1490 811d4cf4 balrog
        tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1491 811d4cf4 balrog
        break;
1492 811d4cf4 balrog
    case INDEX_op_st8_i32:
1493 f694a27e Aurelien Jarno
        tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1494 811d4cf4 balrog
        break;
1495 811d4cf4 balrog
    case INDEX_op_st16_i32:
1496 f694a27e Aurelien Jarno
        tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1497 811d4cf4 balrog
        break;
1498 811d4cf4 balrog
    case INDEX_op_st_i32:
1499 811d4cf4 balrog
        tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1500 811d4cf4 balrog
        break;
1501 811d4cf4 balrog
1502 811d4cf4 balrog
    case INDEX_op_mov_i32:
1503 811d4cf4 balrog
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1504 811d4cf4 balrog
                        args[0], 0, args[1], SHIFT_IMM_LSL(0));
1505 811d4cf4 balrog
        break;
1506 811d4cf4 balrog
    case INDEX_op_movi_i32:
1507 811d4cf4 balrog
        tcg_out_movi32(s, COND_AL, args[0], args[1]);
1508 811d4cf4 balrog
        break;
1509 811d4cf4 balrog
    case INDEX_op_add_i32:
1510 811d4cf4 balrog
        c = ARITH_ADD;
1511 811d4cf4 balrog
        goto gen_arith;
1512 811d4cf4 balrog
    case INDEX_op_sub_i32:
1513 811d4cf4 balrog
        c = ARITH_SUB;
1514 811d4cf4 balrog
        goto gen_arith;
1515 811d4cf4 balrog
    case INDEX_op_and_i32:
1516 811d4cf4 balrog
        c = ARITH_AND;
1517 811d4cf4 balrog
        goto gen_arith;
1518 932234f6 Aurelien Jarno
    case INDEX_op_andc_i32:
1519 932234f6 Aurelien Jarno
        c = ARITH_BIC;
1520 932234f6 Aurelien Jarno
        goto gen_arith;
1521 811d4cf4 balrog
    case INDEX_op_or_i32:
1522 811d4cf4 balrog
        c = ARITH_ORR;
1523 811d4cf4 balrog
        goto gen_arith;
1524 811d4cf4 balrog
    case INDEX_op_xor_i32:
1525 811d4cf4 balrog
        c = ARITH_EOR;
1526 811d4cf4 balrog
        /* Fall through.  */
1527 811d4cf4 balrog
    gen_arith:
1528 94953e6d Laurent Desnogues
        if (const_args[2]) {
1529 94953e6d Laurent Desnogues
            int rot;
1530 94953e6d Laurent Desnogues
            rot = encode_imm(args[2]);
1531 cb4e581f Laurent Desnogues
            tcg_out_dat_imm(s, COND_AL, c,
1532 94953e6d Laurent Desnogues
                            args[0], args[1], rotl(args[2], rot) | (rot << 7));
1533 94953e6d Laurent Desnogues
        } else
1534 cb4e581f Laurent Desnogues
            tcg_out_dat_reg(s, COND_AL, c,
1535 cb4e581f Laurent Desnogues
                            args[0], args[1], args[2], SHIFT_IMM_LSL(0));
1536 811d4cf4 balrog
        break;
1537 811d4cf4 balrog
    case INDEX_op_add2_i32:
1538 811d4cf4 balrog
        tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
1539 811d4cf4 balrog
                        args[0], args[1], args[2], args[3],
1540 811d4cf4 balrog
                        args[4], args[5], SHIFT_IMM_LSL(0));
1541 811d4cf4 balrog
        break;
1542 811d4cf4 balrog
    case INDEX_op_sub2_i32:
1543 811d4cf4 balrog
        tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
1544 811d4cf4 balrog
                        args[0], args[1], args[2], args[3],
1545 811d4cf4 balrog
                        args[4], args[5], SHIFT_IMM_LSL(0));
1546 811d4cf4 balrog
        break;
1547 650bbb36 balrog
    case INDEX_op_neg_i32:
1548 650bbb36 balrog
        tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1549 650bbb36 balrog
        break;
1550 f878d2d2 Laurent Desnogues
    case INDEX_op_not_i32:
1551 f878d2d2 Laurent Desnogues
        tcg_out_dat_reg(s, COND_AL,
1552 f878d2d2 Laurent Desnogues
                        ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1553 f878d2d2 Laurent Desnogues
        break;
1554 811d4cf4 balrog
    case INDEX_op_mul_i32:
1555 811d4cf4 balrog
        tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1556 811d4cf4 balrog
        break;
1557 811d4cf4 balrog
    case INDEX_op_mulu2_i32:
1558 811d4cf4 balrog
        tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1559 811d4cf4 balrog
        break;
1560 811d4cf4 balrog
    /* XXX: Perhaps args[2] & 0x1f is wrong */
1561 811d4cf4 balrog
    case INDEX_op_shl_i32:
1562 811d4cf4 balrog
        c = const_args[2] ?
1563 811d4cf4 balrog
                SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1564 811d4cf4 balrog
        goto gen_shift32;
1565 811d4cf4 balrog
    case INDEX_op_shr_i32:
1566 811d4cf4 balrog
        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1567 811d4cf4 balrog
                SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1568 811d4cf4 balrog
        goto gen_shift32;
1569 811d4cf4 balrog
    case INDEX_op_sar_i32:
1570 811d4cf4 balrog
        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1571 811d4cf4 balrog
                SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1572 293579e5 Aurelien Jarno
        goto gen_shift32;
1573 293579e5 Aurelien Jarno
    case INDEX_op_rotr_i32:
1574 293579e5 Aurelien Jarno
        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1575 293579e5 Aurelien Jarno
                SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1576 811d4cf4 balrog
        /* Fall through.  */
1577 811d4cf4 balrog
    gen_shift32:
1578 811d4cf4 balrog
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1579 811d4cf4 balrog
        break;
1580 811d4cf4 balrog
1581 293579e5 Aurelien Jarno
    case INDEX_op_rotl_i32:
1582 293579e5 Aurelien Jarno
        if (const_args[2]) {
1583 293579e5 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1584 293579e5 Aurelien Jarno
                            ((0x20 - args[2]) & 0x1f) ?
1585 293579e5 Aurelien Jarno
                            SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1586 293579e5 Aurelien Jarno
                            SHIFT_IMM_LSL(0));
1587 293579e5 Aurelien Jarno
        } else {
1588 293579e5 Aurelien Jarno
            tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_R8, args[1], 0x20);
1589 293579e5 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1590 293579e5 Aurelien Jarno
                            SHIFT_REG_ROR(TCG_REG_R8));
1591 293579e5 Aurelien Jarno
        }
1592 293579e5 Aurelien Jarno
        break;
1593 293579e5 Aurelien Jarno
1594 811d4cf4 balrog
    case INDEX_op_brcond_i32:
1595 023e77f8 Aurelien Jarno
        if (const_args[1]) {
1596 023e77f8 Aurelien Jarno
            int rot;
1597 023e77f8 Aurelien Jarno
            rot = encode_imm(args[1]);
1598 c8d80cef Aurelien Jarno
            tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
1599 c8d80cef Aurelien Jarno
                            args[0], rotl(args[1], rot) | (rot << 7));
1600 023e77f8 Aurelien Jarno
        } else {
1601 023e77f8 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1602 023e77f8 Aurelien Jarno
                            args[0], args[1], SHIFT_IMM_LSL(0));
1603 023e77f8 Aurelien Jarno
        }
1604 811d4cf4 balrog
        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
1605 811d4cf4 balrog
        break;
1606 811d4cf4 balrog
    case INDEX_op_brcond2_i32:
1607 811d4cf4 balrog
        /* The resulting conditions are:
1608 811d4cf4 balrog
         * TCG_COND_EQ    -->  a0 == a2 && a1 == a3,
1609 811d4cf4 balrog
         * TCG_COND_NE    --> (a0 != a2 && a1 == a3) ||  a1 != a3,
1610 811d4cf4 balrog
         * TCG_COND_LT(U) --> (a0 <  a2 && a1 == a3) ||  a1 <  a3,
1611 811d4cf4 balrog
         * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1612 811d4cf4 balrog
         * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1613 811d4cf4 balrog
         * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
1614 811d4cf4 balrog
         */
1615 811d4cf4 balrog
        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1616 811d4cf4 balrog
                        args[1], args[3], SHIFT_IMM_LSL(0));
1617 811d4cf4 balrog
        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1618 811d4cf4 balrog
                        args[0], args[2], SHIFT_IMM_LSL(0));
1619 811d4cf4 balrog
        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
1620 811d4cf4 balrog
        break;
1621 f72a6cd7 Aurelien Jarno
    case INDEX_op_setcond_i32:
1622 023e77f8 Aurelien Jarno
        if (const_args[2]) {
1623 023e77f8 Aurelien Jarno
            int rot;
1624 023e77f8 Aurelien Jarno
            rot = encode_imm(args[2]);
1625 c8d80cef Aurelien Jarno
            tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
1626 c8d80cef Aurelien Jarno
                            args[1], rotl(args[2], rot) | (rot << 7));
1627 023e77f8 Aurelien Jarno
        } else {
1628 023e77f8 Aurelien Jarno
            tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1629 023e77f8 Aurelien Jarno
                            args[1], args[2], SHIFT_IMM_LSL(0));
1630 023e77f8 Aurelien Jarno
        }
1631 f72a6cd7 Aurelien Jarno
        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1632 f72a6cd7 Aurelien Jarno
                        ARITH_MOV, args[0], 0, 1);
1633 f72a6cd7 Aurelien Jarno
        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1634 f72a6cd7 Aurelien Jarno
                        ARITH_MOV, args[0], 0, 0);
1635 f72a6cd7 Aurelien Jarno
        break;
1636 e0404769 Aurelien Jarno
    case INDEX_op_setcond2_i32:
1637 e0404769 Aurelien Jarno
        /* See brcond2_i32 comment */
1638 e0404769 Aurelien Jarno
        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1639 e0404769 Aurelien Jarno
                        args[2], args[4], SHIFT_IMM_LSL(0));
1640 e0404769 Aurelien Jarno
        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1641 e0404769 Aurelien Jarno
                        args[1], args[3], SHIFT_IMM_LSL(0));
1642 e0404769 Aurelien Jarno
        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1643 e0404769 Aurelien Jarno
                        ARITH_MOV, args[0], 0, 1);
1644 e0404769 Aurelien Jarno
        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1645 e0404769 Aurelien Jarno
                        ARITH_MOV, args[0], 0, 0);
1646 b525f0a9 Andrzej Zaborowski
        break;
1647 811d4cf4 balrog
1648 811d4cf4 balrog
    case INDEX_op_qemu_ld8u:
1649 7e0d9562 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 0);
1650 811d4cf4 balrog
        break;
1651 811d4cf4 balrog
    case INDEX_op_qemu_ld8s:
1652 7e0d9562 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 0 | 4);
1653 811d4cf4 balrog
        break;
1654 811d4cf4 balrog
    case INDEX_op_qemu_ld16u:
1655 7e0d9562 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 1);
1656 811d4cf4 balrog
        break;
1657 811d4cf4 balrog
    case INDEX_op_qemu_ld16s:
1658 7e0d9562 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 1 | 4);
1659 811d4cf4 balrog
        break;
1660 86feb1c8 Richard Henderson
    case INDEX_op_qemu_ld32:
1661 7e0d9562 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 2);
1662 811d4cf4 balrog
        break;
1663 811d4cf4 balrog
    case INDEX_op_qemu_ld64:
1664 7e0d9562 Aurelien Jarno
        tcg_out_qemu_ld(s, args, 3);
1665 811d4cf4 balrog
        break;
1666 650bbb36 balrog
1667 811d4cf4 balrog
    case INDEX_op_qemu_st8:
1668 7e0d9562 Aurelien Jarno
        tcg_out_qemu_st(s, args, 0);
1669 811d4cf4 balrog
        break;
1670 811d4cf4 balrog
    case INDEX_op_qemu_st16:
1671 7e0d9562 Aurelien Jarno
        tcg_out_qemu_st(s, args, 1);
1672 811d4cf4 balrog
        break;
1673 811d4cf4 balrog
    case INDEX_op_qemu_st32:
1674 7e0d9562 Aurelien Jarno
        tcg_out_qemu_st(s, args, 2);
1675 811d4cf4 balrog
        break;
1676 811d4cf4 balrog
    case INDEX_op_qemu_st64:
1677 7e0d9562 Aurelien Jarno
        tcg_out_qemu_st(s, args, 3);
1678 811d4cf4 balrog
        break;
1679 811d4cf4 balrog
1680 244b1e81 Aurelien Jarno
    case INDEX_op_bswap16_i32:
1681 244b1e81 Aurelien Jarno
        tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1682 244b1e81 Aurelien Jarno
        break;
1683 244b1e81 Aurelien Jarno
    case INDEX_op_bswap32_i32:
1684 244b1e81 Aurelien Jarno
        tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1685 244b1e81 Aurelien Jarno
        break;
1686 244b1e81 Aurelien Jarno
1687 811d4cf4 balrog
    case INDEX_op_ext8s_i32:
1688 9517094f Aurelien Jarno
        tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1689 811d4cf4 balrog
        break;
1690 811d4cf4 balrog
    case INDEX_op_ext16s_i32:
1691 9517094f Aurelien Jarno
        tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1692 9517094f Aurelien Jarno
        break;
1693 9517094f Aurelien Jarno
    case INDEX_op_ext16u_i32:
1694 9517094f Aurelien Jarno
        tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1695 811d4cf4 balrog
        break;
1696 811d4cf4 balrog
1697 811d4cf4 balrog
    default:
1698 811d4cf4 balrog
        tcg_abort();
1699 811d4cf4 balrog
    }
1700 811d4cf4 balrog
}
1701 811d4cf4 balrog
1702 811d4cf4 balrog
static const TCGTargetOpDef arm_op_defs[] = {
1703 811d4cf4 balrog
    { INDEX_op_exit_tb, { } },
1704 811d4cf4 balrog
    { INDEX_op_goto_tb, { } },
1705 811d4cf4 balrog
    { INDEX_op_call, { "ri" } },
1706 811d4cf4 balrog
    { INDEX_op_jmp, { "ri" } },
1707 811d4cf4 balrog
    { INDEX_op_br, { } },
1708 811d4cf4 balrog
1709 811d4cf4 balrog
    { INDEX_op_mov_i32, { "r", "r" } },
1710 811d4cf4 balrog
    { INDEX_op_movi_i32, { "r" } },
1711 811d4cf4 balrog
1712 811d4cf4 balrog
    { INDEX_op_ld8u_i32, { "r", "r" } },
1713 811d4cf4 balrog
    { INDEX_op_ld8s_i32, { "r", "r" } },
1714 811d4cf4 balrog
    { INDEX_op_ld16u_i32, { "r", "r" } },
1715 811d4cf4 balrog
    { INDEX_op_ld16s_i32, { "r", "r" } },
1716 811d4cf4 balrog
    { INDEX_op_ld_i32, { "r", "r" } },
1717 811d4cf4 balrog
    { INDEX_op_st8_i32, { "r", "r" } },
1718 811d4cf4 balrog
    { INDEX_op_st16_i32, { "r", "r" } },
1719 811d4cf4 balrog
    { INDEX_op_st_i32, { "r", "r" } },
1720 811d4cf4 balrog
1721 811d4cf4 balrog
    /* TODO: "r", "r", "ri" */
1722 cb4e581f Laurent Desnogues
    { INDEX_op_add_i32, { "r", "r", "rI" } },
1723 cb4e581f Laurent Desnogues
    { INDEX_op_sub_i32, { "r", "r", "rI" } },
1724 811d4cf4 balrog
    { INDEX_op_mul_i32, { "r", "r", "r" } },
1725 811d4cf4 balrog
    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1726 cb4e581f Laurent Desnogues
    { INDEX_op_and_i32, { "r", "r", "rI" } },
1727 932234f6 Aurelien Jarno
    { INDEX_op_andc_i32, { "r", "r", "rI" } },
1728 cb4e581f Laurent Desnogues
    { INDEX_op_or_i32, { "r", "r", "rI" } },
1729 cb4e581f Laurent Desnogues
    { INDEX_op_xor_i32, { "r", "r", "rI" } },
1730 650bbb36 balrog
    { INDEX_op_neg_i32, { "r", "r" } },
1731 f878d2d2 Laurent Desnogues
    { INDEX_op_not_i32, { "r", "r" } },
1732 811d4cf4 balrog
1733 811d4cf4 balrog
    { INDEX_op_shl_i32, { "r", "r", "ri" } },
1734 811d4cf4 balrog
    { INDEX_op_shr_i32, { "r", "r", "ri" } },
1735 811d4cf4 balrog
    { INDEX_op_sar_i32, { "r", "r", "ri" } },
1736 293579e5 Aurelien Jarno
    { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1737 293579e5 Aurelien Jarno
    { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1738 811d4cf4 balrog
1739 023e77f8 Aurelien Jarno
    { INDEX_op_brcond_i32, { "r", "rI" } },
1740 023e77f8 Aurelien Jarno
    { INDEX_op_setcond_i32, { "r", "r", "rI" } },
1741 811d4cf4 balrog
1742 811d4cf4 balrog
    /* TODO: "r", "r", "r", "r", "ri", "ri" */
1743 811d4cf4 balrog
    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1744 811d4cf4 balrog
    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1745 811d4cf4 balrog
    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1746 e0404769 Aurelien Jarno
    { INDEX_op_setcond2_i32, { "r", "r", "r", "r", "r" } },
1747 811d4cf4 balrog
1748 26c5d372 Aurelien Jarno
#if TARGET_LONG_BITS == 32
1749 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld8u, { "r", "l" } },
1750 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld8s, { "r", "l" } },
1751 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld16u, { "r", "l" } },
1752 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld16s, { "r", "l" } },
1753 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld32, { "r", "l" } },
1754 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld64, { "L", "L", "l" } },
1755 67dcab73 Aurelien Jarno
1756 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_st8, { "s", "s" } },
1757 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_st16, { "s", "s" } },
1758 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_st32, { "s", "s" } },
1759 bf5675ef Aurelien Jarno
    { INDEX_op_qemu_st64, { "S", "S", "s" } },
1760 26c5d372 Aurelien Jarno
#else
1761 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
1762 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
1763 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
1764 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
1765 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld32, { "r", "l", "l" } },
1766 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
1767 67dcab73 Aurelien Jarno
1768 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_st8, { "s", "s", "s" } },
1769 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_st16, { "s", "s", "s" } },
1770 67dcab73 Aurelien Jarno
    { INDEX_op_qemu_st32, { "s", "s", "s" } },
1771 bf5675ef Aurelien Jarno
    { INDEX_op_qemu_st64, { "S", "S", "s", "s" } },
1772 26c5d372 Aurelien Jarno
#endif
1773 811d4cf4 balrog
1774 244b1e81 Aurelien Jarno
    { INDEX_op_bswap16_i32, { "r", "r" } },
1775 244b1e81 Aurelien Jarno
    { INDEX_op_bswap32_i32, { "r", "r" } },
1776 244b1e81 Aurelien Jarno
1777 811d4cf4 balrog
    { INDEX_op_ext8s_i32, { "r", "r" } },
1778 811d4cf4 balrog
    { INDEX_op_ext16s_i32, { "r", "r" } },
1779 9517094f Aurelien Jarno
    { INDEX_op_ext16u_i32, { "r", "r" } },
1780 811d4cf4 balrog
1781 811d4cf4 balrog
    { -1 },
1782 811d4cf4 balrog
};
1783 811d4cf4 balrog
1784 e4d58b41 Richard Henderson
static void tcg_target_init(TCGContext *s)
1785 811d4cf4 balrog
{
1786 20cb400d Paul Brook
#if !defined(CONFIG_USER_ONLY)
1787 811d4cf4 balrog
    /* fail safe */
1788 811d4cf4 balrog
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1789 811d4cf4 balrog
        tcg_abort();
1790 20cb400d Paul Brook
#endif
1791 811d4cf4 balrog
1792 e4a7d5e8 Aurelien Jarno
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1793 811d4cf4 balrog
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1794 e4a7d5e8 Aurelien Jarno
                     (1 << TCG_REG_R0) |
1795 e4a7d5e8 Aurelien Jarno
                     (1 << TCG_REG_R1) |
1796 e4a7d5e8 Aurelien Jarno
                     (1 << TCG_REG_R2) |
1797 e4a7d5e8 Aurelien Jarno
                     (1 << TCG_REG_R3) |
1798 e4a7d5e8 Aurelien Jarno
                     (1 << TCG_REG_R12) |
1799 e4a7d5e8 Aurelien Jarno
                     (1 << TCG_REG_R14));
1800 811d4cf4 balrog
1801 811d4cf4 balrog
    tcg_regset_clear(s->reserved_regs);
1802 811d4cf4 balrog
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
1803 811d4cf4 balrog
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
1804 e4a7d5e8 Aurelien Jarno
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
1805 811d4cf4 balrog
1806 811d4cf4 balrog
    tcg_add_target_add_op_defs(arm_op_defs);
1807 614f104d Blue Swirl
    tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
1808 614f104d Blue Swirl
                  CPU_TEMP_BUF_NLONGS * sizeof(long));
1809 811d4cf4 balrog
}
1810 811d4cf4 balrog
1811 811d4cf4 balrog
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
1812 811d4cf4 balrog
                int arg1, tcg_target_long arg2)
1813 811d4cf4 balrog
{
1814 811d4cf4 balrog
    tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
1815 811d4cf4 balrog
}
1816 811d4cf4 balrog
1817 811d4cf4 balrog
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
1818 811d4cf4 balrog
                int arg1, tcg_target_long arg2)
1819 811d4cf4 balrog
{
1820 811d4cf4 balrog
    tcg_out_st32(s, COND_AL, arg, arg1, arg2);
1821 811d4cf4 balrog
}
1822 811d4cf4 balrog
1823 2d69f359 Paul Brook
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
1824 811d4cf4 balrog
{
1825 811d4cf4 balrog
    if (val > 0)
1826 811d4cf4 balrog
        if (val < 0x100)
1827 811d4cf4 balrog
            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, reg, reg, val);
1828 811d4cf4 balrog
        else
1829 811d4cf4 balrog
            tcg_abort();
1830 811d4cf4 balrog
    else if (val < 0) {
1831 811d4cf4 balrog
        if (val > -0x100)
1832 811d4cf4 balrog
            tcg_out_dat_imm(s, COND_AL, ARITH_SUB, reg, reg, -val);
1833 811d4cf4 balrog
        else
1834 811d4cf4 balrog
            tcg_abort();
1835 811d4cf4 balrog
    }
1836 811d4cf4 balrog
}
1837 811d4cf4 balrog
1838 3b6dac34 Richard Henderson
static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
1839 811d4cf4 balrog
{
1840 811d4cf4 balrog
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
1841 811d4cf4 balrog
}
1842 811d4cf4 balrog
1843 811d4cf4 balrog
static inline void tcg_out_movi(TCGContext *s, TCGType type,
1844 811d4cf4 balrog
                int ret, tcg_target_long arg)
1845 811d4cf4 balrog
{
1846 811d4cf4 balrog
    tcg_out_movi32(s, COND_AL, ret, arg);
1847 811d4cf4 balrog
}
1848 811d4cf4 balrog
1849 e4d58b41 Richard Henderson
static void tcg_target_qemu_prologue(TCGContext *s)
1850 811d4cf4 balrog
{
1851 cea5f9a2 Blue Swirl
    /* Calling convention requires us to save r4-r11 and lr;
1852 cea5f9a2 Blue Swirl
     * save also r12 to maintain stack 8-alignment.
1853 cea5f9a2 Blue Swirl
     */
1854 cea5f9a2 Blue Swirl
1855 cea5f9a2 Blue Swirl
    /* stmdb sp!, { r4 - r12, lr } */
1856 cea5f9a2 Blue Swirl
    tcg_out32(s, (COND_AL << 28) | 0x092d5ff0);
1857 4e17eae9 Aurelien Jarno
1858 cea5f9a2 Blue Swirl
    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1859 811d4cf4 balrog
1860 cea5f9a2 Blue Swirl
    tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
1861 811d4cf4 balrog
    tb_ret_addr = s->code_ptr;
1862 811d4cf4 balrog
1863 cea5f9a2 Blue Swirl
    /* ldmia sp!, { r4 - r12, pc } */
1864 cea5f9a2 Blue Swirl
    tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0);
1865 811d4cf4 balrog
}