~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to tcg/arm/tcg-target.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-22 10:13:17 UTC
  • mfrom: (1.2.1 upstream) (6.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090322101317-iigjtnu5qil35dtb
Tags: 0.10.1-1
[ Aurelien Jarno ]
* New upstream stable release:
  - patches/80_stable-branch.patch: remove.
* debian/control: 
  - Remove depends on proll.
  - Move depends on device-tree-compiler to build-depends.
  - Bump Standards-Version to 3.8.1 (no changes).
* patches/82_qemu-img_decimal.patch: new patch from upstream to make
  qemu-img accept sizes with decimal values (closes: bug#501400).

Show diffs side-by-side

added added

removed removed

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