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