Statistics
| Branch: | Revision:

root / tcg / arm / tcg-target.c @ 4e17eae9

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