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