Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (50.6 kB)

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
        if (data_reg == addr_reg) {
1015
            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
1016
            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1017
        } else {
1018
            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1019
            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
1020
        }
1021
        break;
1022
    }
1023
#endif
1024
}
1025

    
1026
static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1027
                const TCGArg *args, int opc)
1028
{
1029
    int addr_reg, data_reg, data_reg2;
1030
#ifdef CONFIG_SOFTMMU
1031
    int mem_index, s_bits;
1032
# if TARGET_LONG_BITS == 64
1033
    int addr_reg2;
1034
# endif
1035
    uint32_t *label_ptr;
1036
#endif
1037

    
1038
    data_reg = *args++;
1039
    if (opc == 3)
1040
        data_reg2 = *args++;
1041
    else
1042
        data_reg2 = 0; /* surpress warning */
1043
    addr_reg = *args++;
1044
#ifdef CONFIG_SOFTMMU
1045
# if TARGET_LONG_BITS == 64
1046
    addr_reg2 = *args++;
1047
# endif
1048
    mem_index = *args;
1049
    s_bits = opc & 3;
1050

    
1051
    /* Should generate something like the following:
1052
     *  shr r8, addr_reg, #TARGET_PAGE_BITS
1053
     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
1054
     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1055
     */
1056
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1057
                    8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1058
    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1059
                    0, 8, CPU_TLB_SIZE - 1);
1060
    tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
1061
                    0, TCG_AREG0, 0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1062
    /* In the
1063
     *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
1064
     * below, the offset is likely to exceed 12 bits if mem_index != 0 and
1065
     * not exceed otherwise, so use an
1066
     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
1067
     * before.
1068
     */
1069
    if (mem_index)
1070
        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
1071
                        (mem_index << (TLB_SHIFT & 1)) |
1072
                        ((16 - (TLB_SHIFT >> 1)) << 8));
1073
    tcg_out_ld32_12(s, COND_AL, 1, 0,
1074
                    offsetof(CPUState, tlb_table[0][0].addr_write));
1075
    tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
1076
                    0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1077
    /* Check alignment.  */
1078
    if (s_bits)
1079
        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1080
                        0, addr_reg, (1 << s_bits) - 1);
1081
#  if TARGET_LONG_BITS == 64
1082
    /* XXX: possibly we could use a block data load or writeback in
1083
     * the first access.  */
1084
    tcg_out_ld32_12(s, COND_EQ, 1, 0,
1085
                    offsetof(CPUState, tlb_table[0][0].addr_write)
1086
                    + 4);
1087
    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP,
1088
                    0, 1, addr_reg2, SHIFT_IMM_LSL(0));
1089
#  endif
1090
    tcg_out_ld32_12(s, COND_EQ, 1, 0,
1091
                    offsetof(CPUState, tlb_table[0][0].addend));
1092

    
1093
    switch (opc) {
1094
    case 0:
1095
        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, 1);
1096
        break;
1097
    case 0 | 4:
1098
        tcg_out_st8s_r(s, COND_EQ, data_reg, addr_reg, 1);
1099
        break;
1100
    case 1:
1101
        tcg_out_st16u_r(s, COND_EQ, data_reg, addr_reg, 1);
1102
        break;
1103
    case 1 | 4:
1104
        tcg_out_st16s_r(s, COND_EQ, data_reg, addr_reg, 1);
1105
        break;
1106
    case 2:
1107
    default:
1108
        tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, 1);
1109
        break;
1110
    case 3:
1111
        tcg_out_st32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
1112
        tcg_out_st32_12(s, COND_EQ, data_reg2, 1, 4);
1113
        break;
1114
    }
1115

    
1116
    label_ptr = (void *) s->code_ptr;
1117
    tcg_out_b(s, COND_EQ, 8);
1118

    
1119
    /* TODO: move this code to where the constants pool will be */
1120
    if (addr_reg)
1121
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1122
                        0, 0, addr_reg, SHIFT_IMM_LSL(0));
1123
# if TARGET_LONG_BITS == 32
1124
    switch (opc) {
1125
    case 0:
1126
        tcg_out_dat_imm(s, cond, ARITH_AND, 1, data_reg, 0xff);
1127
        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
1128
        break;
1129
    case 1:
1130
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1131
                        1, 0, data_reg, SHIFT_IMM_LSL(16));
1132
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1133
                        1, 0, 1, SHIFT_IMM_LSR(16));
1134
        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
1135
        break;
1136
    case 2:
1137
        if (data_reg != 1)
1138
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1139
                            1, 0, data_reg, SHIFT_IMM_LSL(0));
1140
        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
1141
        break;
1142
    case 3:
1143
        if (data_reg != 1)
1144
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1145
                            1, 0, data_reg, SHIFT_IMM_LSL(0));
1146
        if (data_reg2 != 2)
1147
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1148
                            2, 0, data_reg2, SHIFT_IMM_LSL(0));
1149
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1150
        break;
1151
    }
1152
# else
1153
    if (addr_reg2 != 1)
1154
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1155
                        1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1156
    switch (opc) {
1157
    case 0:
1158
        tcg_out_dat_imm(s, cond, ARITH_AND, 2, data_reg, 0xff);
1159
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1160
        break;
1161
    case 1:
1162
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1163
                        2, 0, data_reg, SHIFT_IMM_LSL(16));
1164
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1165
                        2, 0, 2, SHIFT_IMM_LSR(16));
1166
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1167
        break;
1168
    case 2:
1169
        if (data_reg != 2)
1170
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1171
                            2, 0, data_reg, SHIFT_IMM_LSL(0));
1172
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1173
        break;
1174
    case 3:
1175
        tcg_out_dat_imm(s, cond, ARITH_MOV, 8, 0, mem_index);
1176
        tcg_out32(s, (cond << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
1177
        if (data_reg != 2)
1178
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1179
                            2, 0, data_reg, SHIFT_IMM_LSL(0));
1180
        if (data_reg2 != 3)
1181
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1182
                            3, 0, data_reg2, SHIFT_IMM_LSL(0));
1183
        break;
1184
    }
1185
# endif
1186

    
1187
# ifdef SAVE_LR
1188
    tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
1189
# endif
1190

    
1191
    tcg_out_bl(s, cond, (tcg_target_long) qemu_st_helpers[s_bits] -
1192
                    (tcg_target_long) s->code_ptr);
1193
# if TARGET_LONG_BITS == 64
1194
    if (opc == 3)
1195
        tcg_out_dat_imm(s, cond, ARITH_ADD, 13, 13, 0x10);
1196
# endif
1197

    
1198
# ifdef SAVE_LR
1199
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
1200
# endif
1201

    
1202
    *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
1203
#else
1204
    switch (opc) {
1205
    case 0:
1206
        tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
1207
        break;
1208
    case 0 | 4:
1209
        tcg_out_st8s_8(s, COND_AL, data_reg, addr_reg, 0);
1210
        break;
1211
    case 1:
1212
        tcg_out_st16u_8(s, COND_AL, data_reg, addr_reg, 0);
1213
        break;
1214
    case 1 | 4:
1215
        tcg_out_st16s_8(s, COND_AL, data_reg, addr_reg, 0);
1216
        break;
1217
    case 2:
1218
    default:
1219
        tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1220
        break;
1221
    case 3:
1222
        /* TODO: use block store -
1223
         * check that data_reg2 > data_reg or the other way */
1224
        tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1225
        tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
1226
        break;
1227
    }
1228
#endif
1229
}
1230

    
1231
static uint8_t *tb_ret_addr;
1232

    
1233
static inline void tcg_out_op(TCGContext *s, int opc,
1234
                const TCGArg *args, const int *const_args)
1235
{
1236
    int c;
1237

    
1238
    switch (opc) {
1239
    case INDEX_op_exit_tb:
1240
#ifdef SAVE_LR
1241
        if (args[0] >> 8)
1242
            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
1243
        else
1244
            tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1245
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 15, 0, 14, SHIFT_IMM_LSL(0));
1246
        if (args[0] >> 8)
1247
            tcg_out32(s, args[0]);
1248
#else
1249
        {
1250
            uint8_t *ld_ptr = s->code_ptr;
1251
            if (args[0] >> 8)
1252
                tcg_out_ld32_12(s, COND_AL, 0, 15, 0);
1253
            else
1254
                tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);
1255
            tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1256
            if (args[0] >> 8) {
1257
                *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
1258
                tcg_out32(s, args[0]);
1259
            }
1260
        }
1261
#endif
1262
        break;
1263
    case INDEX_op_goto_tb:
1264
        if (s->tb_jmp_offset) {
1265
            /* Direct jump method */
1266
#if defined(USE_DIRECT_JUMP)
1267
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1268
            tcg_out_b(s, COND_AL, 8);
1269
#else
1270
            tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
1271
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1272
            tcg_out32(s, 0);
1273
#endif
1274
        } else {
1275
            /* Indirect jump method */
1276
#if 1
1277
            c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
1278
            if (c > 0xfff || c < -0xfff) {
1279
                tcg_out_movi32(s, COND_AL, TCG_REG_R0,
1280
                                (tcg_target_long) (s->tb_next + args[0]));
1281
                tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
1282
            } else
1283
                tcg_out_ld32_12(s, COND_AL, 15, 15, c);
1284
#else
1285
            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
1286
            tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
1287
            tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
1288
#endif
1289
        }
1290
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1291
        break;
1292
    case INDEX_op_call:
1293
        if (const_args[0])
1294
            tcg_out_call(s, COND_AL, args[0]);
1295
        else
1296
            tcg_out_callr(s, COND_AL, args[0]);
1297
        break;
1298
    case INDEX_op_jmp:
1299
        if (const_args[0])
1300
            tcg_out_goto(s, COND_AL, args[0]);
1301
        else
1302
            tcg_out_bx(s, COND_AL, args[0]);
1303
        break;
1304
    case INDEX_op_br:
1305
        tcg_out_goto_label(s, COND_AL, args[0]);
1306
        break;
1307

    
1308
    case INDEX_op_ld8u_i32:
1309
        tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1310
        break;
1311
    case INDEX_op_ld8s_i32:
1312
        tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1313
        break;
1314
    case INDEX_op_ld16u_i32:
1315
        tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1316
        break;
1317
    case INDEX_op_ld16s_i32:
1318
        tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1319
        break;
1320
    case INDEX_op_ld_i32:
1321
        tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1322
        break;
1323
    case INDEX_op_st8_i32:
1324
        tcg_out_st8u(s, COND_AL, args[0], args[1], args[2]);
1325
        break;
1326
    case INDEX_op_st16_i32:
1327
        tcg_out_st16u(s, COND_AL, args[0], args[1], args[2]);
1328
        break;
1329
    case INDEX_op_st_i32:
1330
        tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1331
        break;
1332

    
1333
    case INDEX_op_mov_i32:
1334
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1335
                        args[0], 0, args[1], SHIFT_IMM_LSL(0));
1336
        break;
1337
    case INDEX_op_movi_i32:
1338
        tcg_out_movi32(s, COND_AL, args[0], args[1]);
1339
        break;
1340
    case INDEX_op_add_i32:
1341
        c = ARITH_ADD;
1342
        goto gen_arith;
1343
    case INDEX_op_sub_i32:
1344
        c = ARITH_SUB;
1345
        goto gen_arith;
1346
    case INDEX_op_and_i32:
1347
        c = ARITH_AND;
1348
        goto gen_arith;
1349
    case INDEX_op_or_i32:
1350
        c = ARITH_ORR;
1351
        goto gen_arith;
1352
    case INDEX_op_xor_i32:
1353
        c = ARITH_EOR;
1354
        /* Fall through.  */
1355
    gen_arith:
1356
        tcg_out_dat_reg(s, COND_AL, c,
1357
                        args[0], args[1], args[2], SHIFT_IMM_LSL(0));
1358
        break;
1359
    case INDEX_op_add2_i32:
1360
        tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
1361
                        args[0], args[1], args[2], args[3],
1362
                        args[4], args[5], SHIFT_IMM_LSL(0));
1363
        break;
1364
    case INDEX_op_sub2_i32:
1365
        tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
1366
                        args[0], args[1], args[2], args[3],
1367
                        args[4], args[5], SHIFT_IMM_LSL(0));
1368
        break;
1369
    case INDEX_op_neg_i32:
1370
        tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1371
        break;
1372
    case INDEX_op_mul_i32:
1373
        tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1374
        break;
1375
    case INDEX_op_mulu2_i32:
1376
        tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1377
        break;
1378
    case INDEX_op_div2_i32:
1379
        tcg_out_div_helper(s, COND_AL, args,
1380
                        tcg_helper_div_i64, tcg_helper_rem_i64,
1381
                        SHIFT_IMM_ASR(31));
1382
        break;
1383
    case INDEX_op_divu2_i32:
1384
        tcg_out_div_helper(s, COND_AL, args,
1385
                        tcg_helper_divu_i64, tcg_helper_remu_i64,
1386
                        SHIFT_IMM_LSR(31));
1387
        break;
1388
    /* XXX: Perhaps args[2] & 0x1f is wrong */
1389
    case INDEX_op_shl_i32:
1390
        c = const_args[2] ?
1391
                SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1392
        goto gen_shift32;
1393
    case INDEX_op_shr_i32:
1394
        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1395
                SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1396
        goto gen_shift32;
1397
    case INDEX_op_sar_i32:
1398
        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1399
                SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1400
        /* Fall through.  */
1401
    gen_shift32:
1402
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1403
        break;
1404

    
1405
    case INDEX_op_brcond_i32:
1406
        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1407
                        args[0], args[1], SHIFT_IMM_LSL(0));
1408
        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
1409
        break;
1410
    case INDEX_op_brcond2_i32:
1411
        /* The resulting conditions are:
1412
         * TCG_COND_EQ    -->  a0 == a2 && a1 == a3,
1413
         * TCG_COND_NE    --> (a0 != a2 && a1 == a3) ||  a1 != a3,
1414
         * TCG_COND_LT(U) --> (a0 <  a2 && a1 == a3) ||  a1 <  a3,
1415
         * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1416
         * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1417
         * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
1418
         */
1419
        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1420
                        args[1], args[3], SHIFT_IMM_LSL(0));
1421
        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1422
                        args[0], args[2], SHIFT_IMM_LSL(0));
1423
        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
1424
        break;
1425

    
1426
    case INDEX_op_qemu_ld8u:
1427
        tcg_out_qemu_ld(s, COND_AL, args, 0);
1428
        break;
1429
    case INDEX_op_qemu_ld8s:
1430
        tcg_out_qemu_ld(s, COND_AL, args, 0 | 4);
1431
        break;
1432
    case INDEX_op_qemu_ld16u:
1433
        tcg_out_qemu_ld(s, COND_AL, args, 1);
1434
        break;
1435
    case INDEX_op_qemu_ld16s:
1436
        tcg_out_qemu_ld(s, COND_AL, args, 1 | 4);
1437
        break;
1438
    case INDEX_op_qemu_ld32u:
1439
        tcg_out_qemu_ld(s, COND_AL, args, 2);
1440
        break;
1441
    case INDEX_op_qemu_ld64:
1442
        tcg_out_qemu_ld(s, COND_AL, args, 3);
1443
        break;
1444

    
1445
    case INDEX_op_qemu_st8:
1446
        tcg_out_qemu_st(s, COND_AL, args, 0);
1447
        break;
1448
    case INDEX_op_qemu_st16:
1449
        tcg_out_qemu_st(s, COND_AL, args, 1);
1450
        break;
1451
    case INDEX_op_qemu_st32:
1452
        tcg_out_qemu_st(s, COND_AL, args, 2);
1453
        break;
1454
    case INDEX_op_qemu_st64:
1455
        tcg_out_qemu_st(s, COND_AL, args, 3);
1456
        break;
1457

    
1458
    case INDEX_op_ext8s_i32:
1459
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1460
                        args[0], 0, args[1], SHIFT_IMM_LSL(24));
1461
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1462
                        args[0], 0, args[0], SHIFT_IMM_ASR(24));
1463
        break;
1464
    case INDEX_op_ext16s_i32:
1465
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1466
                        args[0], 0, args[1], SHIFT_IMM_LSL(16));
1467
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1468
                        args[0], 0, args[0], SHIFT_IMM_ASR(16));
1469
        break;
1470

    
1471
    default:
1472
        tcg_abort();
1473
    }
1474
}
1475

    
1476
static const TCGTargetOpDef arm_op_defs[] = {
1477
    { INDEX_op_exit_tb, { } },
1478
    { INDEX_op_goto_tb, { } },
1479
    { INDEX_op_call, { "ri" } },
1480
    { INDEX_op_jmp, { "ri" } },
1481
    { INDEX_op_br, { } },
1482

    
1483
    { INDEX_op_mov_i32, { "r", "r" } },
1484
    { INDEX_op_movi_i32, { "r" } },
1485

    
1486
    { INDEX_op_ld8u_i32, { "r", "r" } },
1487
    { INDEX_op_ld8s_i32, { "r", "r" } },
1488
    { INDEX_op_ld16u_i32, { "r", "r" } },
1489
    { INDEX_op_ld16s_i32, { "r", "r" } },
1490
    { INDEX_op_ld_i32, { "r", "r" } },
1491
    { INDEX_op_st8_i32, { "r", "r" } },
1492
    { INDEX_op_st16_i32, { "r", "r" } },
1493
    { INDEX_op_st_i32, { "r", "r" } },
1494

    
1495
    /* TODO: "r", "r", "ri" */
1496
    { INDEX_op_add_i32, { "r", "r", "r" } },
1497
    { INDEX_op_sub_i32, { "r", "r", "r" } },
1498
    { INDEX_op_mul_i32, { "r", "r", "r" } },
1499
    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1500
    { INDEX_op_div2_i32, { "r", "r", "r", "1", "2" } },
1501
    { INDEX_op_divu2_i32, { "r", "r", "r", "1", "2" } },
1502
    { INDEX_op_and_i32, { "r", "r", "r" } },
1503
    { INDEX_op_or_i32, { "r", "r", "r" } },
1504
    { INDEX_op_xor_i32, { "r", "r", "r" } },
1505
    { INDEX_op_neg_i32, { "r", "r" } },
1506

    
1507
    { INDEX_op_shl_i32, { "r", "r", "ri" } },
1508
    { INDEX_op_shr_i32, { "r", "r", "ri" } },
1509
    { INDEX_op_sar_i32, { "r", "r", "ri" } },
1510

    
1511
    { INDEX_op_brcond_i32, { "r", "r" } },
1512

    
1513
    /* TODO: "r", "r", "r", "r", "ri", "ri" */
1514
    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1515
    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1516
    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1517

    
1518
    { INDEX_op_qemu_ld8u, { "r", "x", "X" } },
1519
    { INDEX_op_qemu_ld8s, { "r", "x", "X" } },
1520
    { INDEX_op_qemu_ld16u, { "r", "x", "X" } },
1521
    { INDEX_op_qemu_ld16s, { "r", "x", "X" } },
1522
    { INDEX_op_qemu_ld32u, { "r", "x", "X" } },
1523
    { INDEX_op_qemu_ld64, { "d", "r", "x", "X" } },
1524

    
1525
    { INDEX_op_qemu_st8, { "x", "x", "X" } },
1526
    { INDEX_op_qemu_st16, { "x", "x", "X" } },
1527
    { INDEX_op_qemu_st32, { "x", "x", "X" } },
1528
    { INDEX_op_qemu_st64, { "x", "D", "x", "X" } },
1529

    
1530
    { INDEX_op_ext8s_i32, { "r", "r" } },
1531
    { INDEX_op_ext16s_i32, { "r", "r" } },
1532

    
1533
    { -1 },
1534
};
1535

    
1536
void tcg_target_init(TCGContext *s)
1537
{
1538
    /* fail safe */
1539
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1540
        tcg_abort();
1541

    
1542
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0,
1543
                    ((2 << TCG_REG_R14) - 1) & ~(1 << TCG_REG_R8));
1544
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1545
                    ((2 << TCG_REG_R3) - 1) |
1546
                    (1 << TCG_REG_R12) | (1 << TCG_REG_R14));
1547

    
1548
    tcg_regset_clear(s->reserved_regs);
1549
#ifdef SAVE_LR
1550
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R14);
1551
#endif
1552
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
1553
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
1554

    
1555
    tcg_add_target_add_op_defs(arm_op_defs);
1556
}
1557

    
1558
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
1559
                int arg1, tcg_target_long arg2)
1560
{
1561
    tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
1562
}
1563

    
1564
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
1565
                int arg1, tcg_target_long arg2)
1566
{
1567
    tcg_out_st32(s, COND_AL, arg, arg1, arg2);
1568
}
1569

    
1570
void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
1571
{
1572
    if (val > 0)
1573
        if (val < 0x100)
1574
            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, reg, reg, val);
1575
        else
1576
            tcg_abort();
1577
    else if (val < 0) {
1578
        if (val > -0x100)
1579
            tcg_out_dat_imm(s, COND_AL, ARITH_SUB, reg, reg, -val);
1580
        else
1581
            tcg_abort();
1582
    }
1583
}
1584

    
1585
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
1586
{
1587
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
1588
}
1589

    
1590
static inline void tcg_out_movi(TCGContext *s, TCGType type,
1591
                int ret, tcg_target_long arg)
1592
{
1593
    tcg_out_movi32(s, COND_AL, ret, arg);
1594
}
1595

    
1596
void tcg_target_qemu_prologue(TCGContext *s)
1597
{
1598
    /* stmdb sp!, { r9 - r11, lr } */
1599
    tcg_out32(s, (COND_AL << 28) | 0x092d4e00);
1600

    
1601
    tcg_out_bx(s, COND_AL, TCG_REG_R0);
1602
    tb_ret_addr = s->code_ptr;
1603

    
1604
    /* ldmia sp!, { r9 - r11, pc } */
1605
    tcg_out32(s, (COND_AL << 28) | 0x08bd8e00);
1606
}