Statistics
| Branch: | Revision:

root / tcg / arm / tcg-target.c @ b9e946c7

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