Statistics
| Branch: | Revision:

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

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