c4cae8a3bc127f3cc5fe47aa3d14c2d37b74615b
[qemu] / tcg / arm / tcg-target.c
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 #if TARGET_LONG_BITS == 64
862     addr_reg2 = *args++;
863 #endif
864 #ifdef CONFIG_SOFTMMU
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 #if TARGET_LONG_BITS == 64
1040     addr_reg2 = *args++;
1041 #endif
1042 #ifdef CONFIG_SOFTMMU
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 }