Statistics
| Branch: | Revision:

root / tcg / arm / tcg-target.c @ 419bafa5

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