]> git.proxmox.com Git - qemu.git/blob - tcg/arm/tcg-target.c
tcg-arm: Implement deposit for armv7
[qemu.git] / tcg / arm / tcg-target.c
1 /*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008 Andrzej Zaborowski
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 #if defined(__ARM_ARCH_7__) || \
26 defined(__ARM_ARCH_7A__) || \
27 defined(__ARM_ARCH_7EM__) || \
28 defined(__ARM_ARCH_7M__) || \
29 defined(__ARM_ARCH_7R__)
30 #define USE_ARMV7_INSTRUCTIONS
31 #endif
32
33 #if defined(USE_ARMV7_INSTRUCTIONS) || \
34 defined(__ARM_ARCH_6J__) || \
35 defined(__ARM_ARCH_6K__) || \
36 defined(__ARM_ARCH_6T2__) || \
37 defined(__ARM_ARCH_6Z__) || \
38 defined(__ARM_ARCH_6ZK__)
39 #define USE_ARMV6_INSTRUCTIONS
40 #endif
41
42 #if defined(USE_ARMV6_INSTRUCTIONS) || \
43 defined(__ARM_ARCH_5T__) || \
44 defined(__ARM_ARCH_5TE__) || \
45 defined(__ARM_ARCH_5TEJ__)
46 #define USE_ARMV5_INSTRUCTIONS
47 #endif
48
49 #ifdef USE_ARMV5_INSTRUCTIONS
50 static const int use_armv5_instructions = 1;
51 #else
52 static const int use_armv5_instructions = 0;
53 #endif
54 #undef USE_ARMV5_INSTRUCTIONS
55
56 #ifdef USE_ARMV6_INSTRUCTIONS
57 static const int use_armv6_instructions = 1;
58 #else
59 static const int use_armv6_instructions = 0;
60 #endif
61 #undef USE_ARMV6_INSTRUCTIONS
62
63 #ifdef USE_ARMV7_INSTRUCTIONS
64 static const int use_armv7_instructions = 1;
65 #else
66 static const int use_armv7_instructions = 0;
67 #endif
68 #undef USE_ARMV7_INSTRUCTIONS
69
70 #ifndef NDEBUG
71 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
72 "%r0",
73 "%r1",
74 "%r2",
75 "%r3",
76 "%r4",
77 "%r5",
78 "%r6",
79 "%r7",
80 "%r8",
81 "%r9",
82 "%r10",
83 "%r11",
84 "%r12",
85 "%r13",
86 "%r14",
87 "%pc",
88 };
89 #endif
90
91 static const int tcg_target_reg_alloc_order[] = {
92 TCG_REG_R4,
93 TCG_REG_R5,
94 TCG_REG_R6,
95 TCG_REG_R7,
96 TCG_REG_R8,
97 TCG_REG_R9,
98 TCG_REG_R10,
99 TCG_REG_R11,
100 TCG_REG_R13,
101 TCG_REG_R0,
102 TCG_REG_R1,
103 TCG_REG_R2,
104 TCG_REG_R3,
105 TCG_REG_R12,
106 TCG_REG_R14,
107 };
108
109 static const int tcg_target_call_iarg_regs[4] = {
110 TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
111 };
112 static const int tcg_target_call_oarg_regs[2] = {
113 TCG_REG_R0, TCG_REG_R1
114 };
115
116 static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
117 {
118 *(uint32_t *) code_ptr = target;
119 }
120
121 static inline void reloc_pc24(void *code_ptr, tcg_target_long target)
122 {
123 uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2);
124
125 *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
126 | (offset & 0xffffff);
127 }
128
129 static void patch_reloc(uint8_t *code_ptr, int type,
130 tcg_target_long value, tcg_target_long addend)
131 {
132 switch (type) {
133 case R_ARM_ABS32:
134 reloc_abs32(code_ptr, value);
135 break;
136
137 case R_ARM_CALL:
138 case R_ARM_JUMP24:
139 default:
140 tcg_abort();
141
142 case R_ARM_PC24:
143 reloc_pc24(code_ptr, value);
144 break;
145 }
146 }
147
148 #define TCG_CT_CONST_ARM 0x100
149 #define TCG_CT_CONST_INV 0x200
150 #define TCG_CT_CONST_NEG 0x400
151 #define TCG_CT_CONST_ZERO 0x800
152
153 /* parse target specific constraints */
154 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
155 {
156 const char *ct_str;
157
158 ct_str = *pct_str;
159 switch (ct_str[0]) {
160 case 'I':
161 ct->ct |= TCG_CT_CONST_ARM;
162 break;
163 case 'K':
164 ct->ct |= TCG_CT_CONST_INV;
165 break;
166 case 'N': /* The gcc constraint letter is L, already used here. */
167 ct->ct |= TCG_CT_CONST_NEG;
168 break;
169 case 'Z':
170 ct->ct |= TCG_CT_CONST_ZERO;
171 break;
172
173 case 'r':
174 ct->ct |= TCG_CT_REG;
175 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
176 break;
177
178 /* qemu_ld address */
179 case 'l':
180 ct->ct |= TCG_CT_REG;
181 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
182 #ifdef CONFIG_SOFTMMU
183 /* r0 and r1 will be overwritten when reading the tlb entry,
184 so don't use these. */
185 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
186 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
187 #if TARGET_LONG_BITS == 64
188 /* If we're passing env to the helper as r0 and need a regpair
189 * for the address then r2 will be overwritten as we're setting
190 * up the args to the helper.
191 */
192 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
193 #endif
194 #endif
195 break;
196 case 'L':
197 ct->ct |= TCG_CT_REG;
198 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
199 #ifdef CONFIG_SOFTMMU
200 /* r1 is still needed to load data_reg or data_reg2,
201 so don't use it. */
202 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
203 #endif
204 break;
205
206 /* qemu_st address & data_reg */
207 case 's':
208 ct->ct |= TCG_CT_REG;
209 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
210 /* r0 and r1 will be overwritten when reading the tlb entry
211 (softmmu only) and doing the byte swapping, so don't
212 use these. */
213 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
214 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
215 #if defined(CONFIG_SOFTMMU) && (TARGET_LONG_BITS == 64)
216 /* Avoid clashes with registers being used for helper args */
217 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
218 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
219 #endif
220 break;
221 /* qemu_st64 data_reg2 */
222 case 'S':
223 ct->ct |= TCG_CT_REG;
224 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
225 /* r0 and r1 will be overwritten when reading the tlb entry
226 (softmmu only) and doing the byte swapping, so don't
227 use these. */
228 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
229 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
230 #ifdef CONFIG_SOFTMMU
231 /* r2 is still needed to load data_reg, so don't use it. */
232 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
233 #if TARGET_LONG_BITS == 64
234 /* Avoid clashes with registers being used for helper args */
235 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
236 #endif
237 #endif
238 break;
239
240 default:
241 return -1;
242 }
243 ct_str++;
244 *pct_str = ct_str;
245
246 return 0;
247 }
248
249 static inline uint32_t rotl(uint32_t val, int n)
250 {
251 return (val << n) | (val >> (32 - n));
252 }
253
254 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
255 right-rotated by an even amount between 0 and 30. */
256 static inline int encode_imm(uint32_t imm)
257 {
258 int shift;
259
260 /* simple case, only lower bits */
261 if ((imm & ~0xff) == 0)
262 return 0;
263 /* then try a simple even shift */
264 shift = ctz32(imm) & ~1;
265 if (((imm >> shift) & ~0xff) == 0)
266 return 32 - shift;
267 /* now try harder with rotations */
268 if ((rotl(imm, 2) & ~0xff) == 0)
269 return 2;
270 if ((rotl(imm, 4) & ~0xff) == 0)
271 return 4;
272 if ((rotl(imm, 6) & ~0xff) == 0)
273 return 6;
274 /* imm can't be encoded */
275 return -1;
276 }
277
278 static inline int check_fit_imm(uint32_t imm)
279 {
280 return encode_imm(imm) >= 0;
281 }
282
283 /* Test if a constant matches the constraint.
284 * TODO: define constraints for:
285 *
286 * ldr/str offset: between -0xfff and 0xfff
287 * ldrh/strh offset: between -0xff and 0xff
288 * mov operand2: values represented with x << (2 * y), x < 0x100
289 * add, sub, eor...: ditto
290 */
291 static inline int tcg_target_const_match(tcg_target_long val,
292 const TCGArgConstraint *arg_ct)
293 {
294 int ct;
295 ct = arg_ct->ct;
296 if (ct & TCG_CT_CONST) {
297 return 1;
298 } else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
299 return 1;
300 } else if ((ct & TCG_CT_CONST_INV) && check_fit_imm(~val)) {
301 return 1;
302 } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
303 return 1;
304 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
305 return 1;
306 } else {
307 return 0;
308 }
309 }
310
311 #define TO_CPSR (1 << 20)
312
313 enum arm_data_opc_e {
314 ARITH_AND = 0x0 << 21,
315 ARITH_EOR = 0x1 << 21,
316 ARITH_SUB = 0x2 << 21,
317 ARITH_RSB = 0x3 << 21,
318 ARITH_ADD = 0x4 << 21,
319 ARITH_ADC = 0x5 << 21,
320 ARITH_SBC = 0x6 << 21,
321 ARITH_RSC = 0x7 << 21,
322 ARITH_TST = 0x8 << 21 | TO_CPSR,
323 ARITH_CMP = 0xa << 21 | TO_CPSR,
324 ARITH_CMN = 0xb << 21 | TO_CPSR,
325 ARITH_ORR = 0xc << 21,
326 ARITH_MOV = 0xd << 21,
327 ARITH_BIC = 0xe << 21,
328 ARITH_MVN = 0xf << 21,
329 };
330
331 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
332 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
333 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
334 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
335 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
336 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
337 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
338 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
339
340 enum arm_cond_code_e {
341 COND_EQ = 0x0,
342 COND_NE = 0x1,
343 COND_CS = 0x2, /* Unsigned greater or equal */
344 COND_CC = 0x3, /* Unsigned less than */
345 COND_MI = 0x4, /* Negative */
346 COND_PL = 0x5, /* Zero or greater */
347 COND_VS = 0x6, /* Overflow */
348 COND_VC = 0x7, /* No overflow */
349 COND_HI = 0x8, /* Unsigned greater than */
350 COND_LS = 0x9, /* Unsigned less or equal */
351 COND_GE = 0xa,
352 COND_LT = 0xb,
353 COND_GT = 0xc,
354 COND_LE = 0xd,
355 COND_AL = 0xe,
356 };
357
358 static const uint8_t tcg_cond_to_arm_cond[] = {
359 [TCG_COND_EQ] = COND_EQ,
360 [TCG_COND_NE] = COND_NE,
361 [TCG_COND_LT] = COND_LT,
362 [TCG_COND_GE] = COND_GE,
363 [TCG_COND_LE] = COND_LE,
364 [TCG_COND_GT] = COND_GT,
365 /* unsigned */
366 [TCG_COND_LTU] = COND_CC,
367 [TCG_COND_GEU] = COND_CS,
368 [TCG_COND_LEU] = COND_LS,
369 [TCG_COND_GTU] = COND_HI,
370 };
371
372 static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
373 {
374 tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
375 }
376
377 static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
378 {
379 tcg_out32(s, (cond << 28) | 0x0a000000 |
380 (((offset - 8) >> 2) & 0x00ffffff));
381 }
382
383 static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
384 {
385 /* We pay attention here to not modify the branch target by skipping
386 the corresponding bytes. This ensure that caches and memory are
387 kept coherent during retranslation. */
388 #ifdef HOST_WORDS_BIGENDIAN
389 tcg_out8(s, (cond << 4) | 0x0a);
390 s->code_ptr += 3;
391 #else
392 s->code_ptr += 3;
393 tcg_out8(s, (cond << 4) | 0x0a);
394 #endif
395 }
396
397 static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
398 {
399 tcg_out32(s, (cond << 28) | 0x0b000000 |
400 (((offset - 8) >> 2) & 0x00ffffff));
401 }
402
403 static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
404 {
405 tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
406 }
407
408 static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
409 {
410 tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
411 (((offset - 8) >> 2) & 0x00ffffff));
412 }
413
414 static inline void tcg_out_dat_reg(TCGContext *s,
415 int cond, int opc, int rd, int rn, int rm, int shift)
416 {
417 tcg_out32(s, (cond << 28) | (0 << 25) | opc |
418 (rn << 16) | (rd << 12) | shift | rm);
419 }
420
421 static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
422 {
423 /* Simple reg-reg move, optimising out the 'do nothing' case */
424 if (rd != rm) {
425 tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, rm, SHIFT_IMM_LSL(0));
426 }
427 }
428
429 static inline void tcg_out_dat_imm(TCGContext *s,
430 int cond, int opc, int rd, int rn, int im)
431 {
432 tcg_out32(s, (cond << 28) | (1 << 25) | opc |
433 (rn << 16) | (rd << 12) | im);
434 }
435
436 static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
437 {
438 int rot, opc, rn;
439
440 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
441 Speed things up by only checking when movt would be required.
442 Prior to armv7, have one go at fully rotated immediates before
443 doing the decomposition thing below. */
444 if (!use_armv7_instructions || (arg & 0xffff0000)) {
445 rot = encode_imm(arg);
446 if (rot >= 0) {
447 tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
448 rotl(arg, rot) | (rot << 7));
449 return;
450 }
451 rot = encode_imm(~arg);
452 if (rot >= 0) {
453 tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
454 rotl(~arg, rot) | (rot << 7));
455 return;
456 }
457 }
458
459 /* Use movw + movt. */
460 if (use_armv7_instructions) {
461 /* movw */
462 tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
463 | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
464 if (arg & 0xffff0000) {
465 /* movt */
466 tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
467 | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
468 }
469 return;
470 }
471
472 /* TODO: This is very suboptimal, we can easily have a constant
473 pool somewhere after all the instructions. */
474 opc = ARITH_MOV;
475 rn = 0;
476 /* If we have lots of leading 1's, we can shorten the sequence by
477 beginning with mvn and then clearing higher bits with eor. */
478 if (clz32(~arg) > clz32(arg)) {
479 opc = ARITH_MVN, arg = ~arg;
480 }
481 do {
482 int i = ctz32(arg) & ~1;
483 rot = ((32 - i) << 7) & 0xf00;
484 tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
485 arg &= ~(0xff << i);
486
487 opc = ARITH_EOR;
488 rn = rd;
489 } while (arg);
490 }
491
492 static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
493 TCGArg lhs, TCGArg rhs, int rhs_is_const)
494 {
495 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
496 * rhs must satisfy the "rI" constraint.
497 */
498 if (rhs_is_const) {
499 int rot = encode_imm(rhs);
500 assert(rot >= 0);
501 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
502 } else {
503 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
504 }
505 }
506
507 static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
508 TCGReg dst, TCGReg lhs, TCGArg rhs,
509 bool rhs_is_const)
510 {
511 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
512 * rhs must satisfy the "rIK" constraint.
513 */
514 if (rhs_is_const) {
515 int rot = encode_imm(rhs);
516 if (rot < 0) {
517 rhs = ~rhs;
518 rot = encode_imm(rhs);
519 assert(rot >= 0);
520 opc = opinv;
521 }
522 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
523 } else {
524 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
525 }
526 }
527
528 static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
529 TCGArg dst, TCGArg lhs, TCGArg rhs,
530 bool rhs_is_const)
531 {
532 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
533 * rhs must satisfy the "rIN" constraint.
534 */
535 if (rhs_is_const) {
536 int rot = encode_imm(rhs);
537 if (rot < 0) {
538 rhs = -rhs;
539 rot = encode_imm(rhs);
540 assert(rot >= 0);
541 opc = opneg;
542 }
543 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
544 } else {
545 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
546 }
547 }
548
549 static inline void tcg_out_mul32(TCGContext *s,
550 int cond, int rd, int rs, int rm)
551 {
552 if (rd != rm)
553 tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
554 (rs << 8) | 0x90 | rm);
555 else if (rd != rs)
556 tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
557 (rm << 8) | 0x90 | rs);
558 else {
559 tcg_out32(s, (cond << 28) | ( 8 << 16) | (0 << 12) |
560 (rs << 8) | 0x90 | rm);
561 tcg_out_dat_reg(s, cond, ARITH_MOV,
562 rd, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
563 }
564 }
565
566 static inline void tcg_out_umull32(TCGContext *s,
567 int cond, int rd0, int rd1, int rs, int rm)
568 {
569 if (rd0 != rm && rd1 != rm)
570 tcg_out32(s, (cond << 28) | 0x800090 |
571 (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
572 else if (rd0 != rs && rd1 != rs)
573 tcg_out32(s, (cond << 28) | 0x800090 |
574 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
575 else {
576 tcg_out_dat_reg(s, cond, ARITH_MOV,
577 TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
578 tcg_out32(s, (cond << 28) | 0x800098 |
579 (rd1 << 16) | (rd0 << 12) | (rs << 8));
580 }
581 }
582
583 static inline void tcg_out_smull32(TCGContext *s,
584 int cond, int rd0, int rd1, int rs, int rm)
585 {
586 if (rd0 != rm && rd1 != rm)
587 tcg_out32(s, (cond << 28) | 0xc00090 |
588 (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
589 else if (rd0 != rs && rd1 != rs)
590 tcg_out32(s, (cond << 28) | 0xc00090 |
591 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
592 else {
593 tcg_out_dat_reg(s, cond, ARITH_MOV,
594 TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
595 tcg_out32(s, (cond << 28) | 0xc00098 |
596 (rd1 << 16) | (rd0 << 12) | (rs << 8));
597 }
598 }
599
600 static inline void tcg_out_ext8s(TCGContext *s, int cond,
601 int rd, int rn)
602 {
603 if (use_armv6_instructions) {
604 /* sxtb */
605 tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
606 } else {
607 tcg_out_dat_reg(s, cond, ARITH_MOV,
608 rd, 0, rn, SHIFT_IMM_LSL(24));
609 tcg_out_dat_reg(s, cond, ARITH_MOV,
610 rd, 0, rd, SHIFT_IMM_ASR(24));
611 }
612 }
613
614 static inline void tcg_out_ext8u(TCGContext *s, int cond,
615 int rd, int rn)
616 {
617 tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
618 }
619
620 static inline void tcg_out_ext16s(TCGContext *s, int cond,
621 int rd, int rn)
622 {
623 if (use_armv6_instructions) {
624 /* sxth */
625 tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
626 } else {
627 tcg_out_dat_reg(s, cond, ARITH_MOV,
628 rd, 0, rn, SHIFT_IMM_LSL(16));
629 tcg_out_dat_reg(s, cond, ARITH_MOV,
630 rd, 0, rd, SHIFT_IMM_ASR(16));
631 }
632 }
633
634 static inline void tcg_out_ext16u(TCGContext *s, int cond,
635 int rd, int rn)
636 {
637 if (use_armv6_instructions) {
638 /* uxth */
639 tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
640 } else {
641 tcg_out_dat_reg(s, cond, ARITH_MOV,
642 rd, 0, rn, SHIFT_IMM_LSL(16));
643 tcg_out_dat_reg(s, cond, ARITH_MOV,
644 rd, 0, rd, SHIFT_IMM_LSR(16));
645 }
646 }
647
648 static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
649 {
650 if (use_armv6_instructions) {
651 /* revsh */
652 tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
653 } else {
654 tcg_out_dat_reg(s, cond, ARITH_MOV,
655 TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
656 tcg_out_dat_reg(s, cond, ARITH_MOV,
657 TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_ASR(16));
658 tcg_out_dat_reg(s, cond, ARITH_ORR,
659 rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
660 }
661 }
662
663 static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
664 {
665 if (use_armv6_instructions) {
666 /* rev16 */
667 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
668 } else {
669 tcg_out_dat_reg(s, cond, ARITH_MOV,
670 TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
671 tcg_out_dat_reg(s, cond, ARITH_MOV,
672 TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_LSR(16));
673 tcg_out_dat_reg(s, cond, ARITH_ORR,
674 rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
675 }
676 }
677
678 /* swap the two low bytes assuming that the two high input bytes and the
679 two high output bit can hold any value. */
680 static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
681 {
682 if (use_armv6_instructions) {
683 /* rev16 */
684 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
685 } else {
686 tcg_out_dat_reg(s, cond, ARITH_MOV,
687 TCG_REG_R8, 0, rn, SHIFT_IMM_LSR(8));
688 tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_R8, TCG_REG_R8, 0xff);
689 tcg_out_dat_reg(s, cond, ARITH_ORR,
690 rd, TCG_REG_R8, rn, SHIFT_IMM_LSL(8));
691 }
692 }
693
694 static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
695 {
696 if (use_armv6_instructions) {
697 /* rev */
698 tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
699 } else {
700 tcg_out_dat_reg(s, cond, ARITH_EOR,
701 TCG_REG_R8, rn, rn, SHIFT_IMM_ROR(16));
702 tcg_out_dat_imm(s, cond, ARITH_BIC,
703 TCG_REG_R8, TCG_REG_R8, 0xff | 0x800);
704 tcg_out_dat_reg(s, cond, ARITH_MOV,
705 rd, 0, rn, SHIFT_IMM_ROR(8));
706 tcg_out_dat_reg(s, cond, ARITH_EOR,
707 rd, rd, TCG_REG_R8, SHIFT_IMM_LSR(8));
708 }
709 }
710
711 bool tcg_target_deposit_valid(int ofs, int len)
712 {
713 /* ??? Without bfi, we could improve over generic code by combining
714 the right-shift from a non-zero ofs with the orr. We do run into
715 problems when rd == rs, and the mask generated from ofs+len doesn't
716 fit into an immediate. We would have to be careful not to pessimize
717 wrt the optimizations performed on the expanded code. */
718 return use_armv7_instructions;
719 }
720
721 static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd,
722 TCGArg a1, int ofs, int len, bool const_a1)
723 {
724 if (const_a1) {
725 /* bfi becomes bfc with rn == 15. */
726 a1 = 15;
727 }
728 /* bfi/bfc */
729 tcg_out32(s, 0x07c00010 | (cond << 28) | (rd << 12) | a1
730 | (ofs << 7) | ((ofs + len - 1) << 16));
731 }
732
733 static inline void tcg_out_ld32_12(TCGContext *s, int cond,
734 int rd, int rn, tcg_target_long im)
735 {
736 if (im >= 0)
737 tcg_out32(s, (cond << 28) | 0x05900000 |
738 (rn << 16) | (rd << 12) | (im & 0xfff));
739 else
740 tcg_out32(s, (cond << 28) | 0x05100000 |
741 (rn << 16) | (rd << 12) | ((-im) & 0xfff));
742 }
743
744 /* Offset pre-increment with base writeback. */
745 static inline void tcg_out_ld32_12wb(TCGContext *s, int cond,
746 int rd, int rn, tcg_target_long im)
747 {
748 /* ldr with writeback and both register equals is UNPREDICTABLE */
749 assert(rd != rn);
750
751 if (im >= 0) {
752 tcg_out32(s, (cond << 28) | 0x05b00000 |
753 (rn << 16) | (rd << 12) | (im & 0xfff));
754 } else {
755 tcg_out32(s, (cond << 28) | 0x05300000 |
756 (rn << 16) | (rd << 12) | ((-im) & 0xfff));
757 }
758 }
759
760 static inline void tcg_out_st32_12(TCGContext *s, int cond,
761 int rd, int rn, tcg_target_long im)
762 {
763 if (im >= 0)
764 tcg_out32(s, (cond << 28) | 0x05800000 |
765 (rn << 16) | (rd << 12) | (im & 0xfff));
766 else
767 tcg_out32(s, (cond << 28) | 0x05000000 |
768 (rn << 16) | (rd << 12) | ((-im) & 0xfff));
769 }
770
771 static inline void tcg_out_ld32_r(TCGContext *s, int cond,
772 int rd, int rn, int rm)
773 {
774 tcg_out32(s, (cond << 28) | 0x07900000 |
775 (rn << 16) | (rd << 12) | rm);
776 }
777
778 static inline void tcg_out_st32_r(TCGContext *s, int cond,
779 int rd, int rn, int rm)
780 {
781 tcg_out32(s, (cond << 28) | 0x07800000 |
782 (rn << 16) | (rd << 12) | rm);
783 }
784
785 /* Register pre-increment with base writeback. */
786 static inline void tcg_out_ld32_rwb(TCGContext *s, int cond,
787 int rd, int rn, int rm)
788 {
789 tcg_out32(s, (cond << 28) | 0x07b00000 |
790 (rn << 16) | (rd << 12) | rm);
791 }
792
793 static inline void tcg_out_st32_rwb(TCGContext *s, int cond,
794 int rd, int rn, int rm)
795 {
796 tcg_out32(s, (cond << 28) | 0x07a00000 |
797 (rn << 16) | (rd << 12) | rm);
798 }
799
800 static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
801 int rd, int rn, tcg_target_long im)
802 {
803 if (im >= 0)
804 tcg_out32(s, (cond << 28) | 0x01d000b0 |
805 (rn << 16) | (rd << 12) |
806 ((im & 0xf0) << 4) | (im & 0xf));
807 else
808 tcg_out32(s, (cond << 28) | 0x015000b0 |
809 (rn << 16) | (rd << 12) |
810 (((-im) & 0xf0) << 4) | ((-im) & 0xf));
811 }
812
813 static inline void tcg_out_st16_8(TCGContext *s, int cond,
814 int rd, int rn, tcg_target_long im)
815 {
816 if (im >= 0)
817 tcg_out32(s, (cond << 28) | 0x01c000b0 |
818 (rn << 16) | (rd << 12) |
819 ((im & 0xf0) << 4) | (im & 0xf));
820 else
821 tcg_out32(s, (cond << 28) | 0x014000b0 |
822 (rn << 16) | (rd << 12) |
823 (((-im) & 0xf0) << 4) | ((-im) & 0xf));
824 }
825
826 static inline void tcg_out_ld16u_r(TCGContext *s, int cond,
827 int rd, int rn, int rm)
828 {
829 tcg_out32(s, (cond << 28) | 0x019000b0 |
830 (rn << 16) | (rd << 12) | rm);
831 }
832
833 static inline void tcg_out_st16_r(TCGContext *s, int cond,
834 int rd, int rn, int rm)
835 {
836 tcg_out32(s, (cond << 28) | 0x018000b0 |
837 (rn << 16) | (rd << 12) | rm);
838 }
839
840 static inline void tcg_out_ld16s_8(TCGContext *s, int cond,
841 int rd, int rn, tcg_target_long im)
842 {
843 if (im >= 0)
844 tcg_out32(s, (cond << 28) | 0x01d000f0 |
845 (rn << 16) | (rd << 12) |
846 ((im & 0xf0) << 4) | (im & 0xf));
847 else
848 tcg_out32(s, (cond << 28) | 0x015000f0 |
849 (rn << 16) | (rd << 12) |
850 (((-im) & 0xf0) << 4) | ((-im) & 0xf));
851 }
852
853 static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
854 int rd, int rn, int rm)
855 {
856 tcg_out32(s, (cond << 28) | 0x019000f0 |
857 (rn << 16) | (rd << 12) | rm);
858 }
859
860 static inline void tcg_out_ld8_12(TCGContext *s, int cond,
861 int rd, int rn, tcg_target_long im)
862 {
863 if (im >= 0)
864 tcg_out32(s, (cond << 28) | 0x05d00000 |
865 (rn << 16) | (rd << 12) | (im & 0xfff));
866 else
867 tcg_out32(s, (cond << 28) | 0x05500000 |
868 (rn << 16) | (rd << 12) | ((-im) & 0xfff));
869 }
870
871 static inline void tcg_out_st8_12(TCGContext *s, int cond,
872 int rd, int rn, tcg_target_long im)
873 {
874 if (im >= 0)
875 tcg_out32(s, (cond << 28) | 0x05c00000 |
876 (rn << 16) | (rd << 12) | (im & 0xfff));
877 else
878 tcg_out32(s, (cond << 28) | 0x05400000 |
879 (rn << 16) | (rd << 12) | ((-im) & 0xfff));
880 }
881
882 static inline void tcg_out_ld8_r(TCGContext *s, int cond,
883 int rd, int rn, int rm)
884 {
885 tcg_out32(s, (cond << 28) | 0x07d00000 |
886 (rn << 16) | (rd << 12) | rm);
887 }
888
889 static inline void tcg_out_st8_r(TCGContext *s, int cond,
890 int rd, int rn, int rm)
891 {
892 tcg_out32(s, (cond << 28) | 0x07c00000 |
893 (rn << 16) | (rd << 12) | rm);
894 }
895
896 static inline void tcg_out_ld8s_8(TCGContext *s, int cond,
897 int rd, int rn, tcg_target_long im)
898 {
899 if (im >= 0)
900 tcg_out32(s, (cond << 28) | 0x01d000d0 |
901 (rn << 16) | (rd << 12) |
902 ((im & 0xf0) << 4) | (im & 0xf));
903 else
904 tcg_out32(s, (cond << 28) | 0x015000d0 |
905 (rn << 16) | (rd << 12) |
906 (((-im) & 0xf0) << 4) | ((-im) & 0xf));
907 }
908
909 static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
910 int rd, int rn, int rm)
911 {
912 tcg_out32(s, (cond << 28) | 0x019000d0 |
913 (rn << 16) | (rd << 12) | rm);
914 }
915
916 static inline void tcg_out_ld32u(TCGContext *s, int cond,
917 int rd, int rn, int32_t offset)
918 {
919 if (offset > 0xfff || offset < -0xfff) {
920 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
921 tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_R8);
922 } else
923 tcg_out_ld32_12(s, cond, rd, rn, offset);
924 }
925
926 static inline void tcg_out_st32(TCGContext *s, int cond,
927 int rd, int rn, int32_t offset)
928 {
929 if (offset > 0xfff || offset < -0xfff) {
930 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
931 tcg_out_st32_r(s, cond, rd, rn, TCG_REG_R8);
932 } else
933 tcg_out_st32_12(s, cond, rd, rn, offset);
934 }
935
936 static inline void tcg_out_ld16u(TCGContext *s, int cond,
937 int rd, int rn, int32_t offset)
938 {
939 if (offset > 0xff || offset < -0xff) {
940 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
941 tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_R8);
942 } else
943 tcg_out_ld16u_8(s, cond, rd, rn, offset);
944 }
945
946 static inline void tcg_out_ld16s(TCGContext *s, int cond,
947 int rd, int rn, int32_t offset)
948 {
949 if (offset > 0xff || offset < -0xff) {
950 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
951 tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_R8);
952 } else
953 tcg_out_ld16s_8(s, cond, rd, rn, offset);
954 }
955
956 static inline void tcg_out_st16(TCGContext *s, int cond,
957 int rd, int rn, int32_t offset)
958 {
959 if (offset > 0xff || offset < -0xff) {
960 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
961 tcg_out_st16_r(s, cond, rd, rn, TCG_REG_R8);
962 } else
963 tcg_out_st16_8(s, cond, rd, rn, offset);
964 }
965
966 static inline void tcg_out_ld8u(TCGContext *s, int cond,
967 int rd, int rn, int32_t offset)
968 {
969 if (offset > 0xfff || offset < -0xfff) {
970 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
971 tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_R8);
972 } else
973 tcg_out_ld8_12(s, cond, rd, rn, offset);
974 }
975
976 static inline void tcg_out_ld8s(TCGContext *s, int cond,
977 int rd, int rn, int32_t offset)
978 {
979 if (offset > 0xff || offset < -0xff) {
980 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
981 tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_R8);
982 } else
983 tcg_out_ld8s_8(s, cond, rd, rn, offset);
984 }
985
986 static inline void tcg_out_st8(TCGContext *s, int cond,
987 int rd, int rn, int32_t offset)
988 {
989 if (offset > 0xfff || offset < -0xfff) {
990 tcg_out_movi32(s, cond, TCG_REG_R8, offset);
991 tcg_out_st8_r(s, cond, rd, rn, TCG_REG_R8);
992 } else
993 tcg_out_st8_12(s, cond, rd, rn, offset);
994 }
995
996 /* The _goto case is normally between TBs within the same code buffer,
997 * and with the code buffer limited to 16MB we shouldn't need the long
998 * case.
999 *
1000 * .... except to the prologue that is in its own buffer.
1001 */
1002 static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
1003 {
1004 int32_t val;
1005
1006 if (addr & 1) {
1007 /* goto to a Thumb destination isn't supported */
1008 tcg_abort();
1009 }
1010
1011 val = addr - (tcg_target_long) s->code_ptr;
1012 if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
1013 tcg_out_b(s, cond, val);
1014 else {
1015 if (cond == COND_AL) {
1016 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1017 tcg_out32(s, addr);
1018 } else {
1019 tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
1020 tcg_out_dat_reg(s, cond, ARITH_ADD,
1021 TCG_REG_PC, TCG_REG_PC,
1022 TCG_REG_R8, SHIFT_IMM_LSL(0));
1023 }
1024 }
1025 }
1026
1027 /* The call case is mostly used for helpers - so it's not unreasonable
1028 * for them to be beyond branch range */
1029 static inline void tcg_out_call(TCGContext *s, uint32_t addr)
1030 {
1031 int32_t val;
1032
1033 val = addr - (tcg_target_long) s->code_ptr;
1034 if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
1035 if (addr & 1) {
1036 /* Use BLX if the target is in Thumb mode */
1037 if (!use_armv5_instructions) {
1038 tcg_abort();
1039 }
1040 tcg_out_blx_imm(s, val);
1041 } else {
1042 tcg_out_bl(s, COND_AL, val);
1043 }
1044 } else {
1045 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
1046 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1047 tcg_out32(s, addr);
1048 }
1049 }
1050
1051 static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
1052 {
1053 if (use_armv5_instructions) {
1054 tcg_out_blx(s, cond, arg);
1055 } else {
1056 tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
1057 TCG_REG_PC, SHIFT_IMM_LSL(0));
1058 tcg_out_bx(s, cond, arg);
1059 }
1060 }
1061
1062 static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
1063 {
1064 TCGLabel *l = &s->labels[label_index];
1065
1066 if (l->has_value)
1067 tcg_out_goto(s, cond, l->u.value);
1068 else if (cond == COND_AL) {
1069 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1070 tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
1071 s->code_ptr += 4;
1072 } else {
1073 /* Probably this should be preferred even for COND_AL... */
1074 tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
1075 tcg_out_b_noaddr(s, cond);
1076 }
1077 }
1078
1079 #ifdef CONFIG_SOFTMMU
1080
1081 #include "exec/softmmu_defs.h"
1082
1083 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
1084 int mmu_idx) */
1085 static const void * const qemu_ld_helpers[4] = {
1086 helper_ldb_mmu,
1087 helper_ldw_mmu,
1088 helper_ldl_mmu,
1089 helper_ldq_mmu,
1090 };
1091
1092 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
1093 uintxx_t val, int mmu_idx) */
1094 static const void * const qemu_st_helpers[4] = {
1095 helper_stb_mmu,
1096 helper_stw_mmu,
1097 helper_stl_mmu,
1098 helper_stq_mmu,
1099 };
1100
1101 /* Helper routines for marshalling helper function arguments into
1102 * the correct registers and stack.
1103 * argreg is where we want to put this argument, arg is the argument itself.
1104 * Return value is the updated argreg ready for the next call.
1105 * Note that argreg 0..3 is real registers, 4+ on stack.
1106 *
1107 * We provide routines for arguments which are: immediate, 32 bit
1108 * value in register, 16 and 8 bit values in register (which must be zero
1109 * extended before use) and 64 bit value in a lo:hi register pair.
1110 */
1111 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1112 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1113 { \
1114 if (argreg < 4) { \
1115 MOV_ARG(s, COND_AL, argreg, arg); \
1116 } else { \
1117 int ofs = (argreg - 4) * 4; \
1118 EXT_ARG; \
1119 assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1120 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1121 } \
1122 return argreg + 1; \
1123 }
1124
1125 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
1126 (tcg_out_movi32(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
1127 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
1128 (tcg_out_ext8u(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
1129 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
1130 (tcg_out_ext16u(s, COND_AL, TCG_REG_R8, arg), arg = TCG_REG_R8))
1131 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
1132
1133 static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
1134 TCGReg arglo, TCGReg arghi)
1135 {
1136 /* 64 bit arguments must go in even/odd register pairs
1137 * and in 8-aligned stack slots.
1138 */
1139 if (argreg & 1) {
1140 argreg++;
1141 }
1142 argreg = tcg_out_arg_reg32(s, argreg, arglo);
1143 argreg = tcg_out_arg_reg32(s, argreg, arghi);
1144 return argreg;
1145 }
1146 #endif /* SOFTMMU */
1147
1148 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1149
1150 static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
1151 {
1152 int addr_reg, data_reg, data_reg2, bswap;
1153 #ifdef CONFIG_SOFTMMU
1154 int mem_index, s_bits, tlb_offset;
1155 TCGReg argreg;
1156 # if TARGET_LONG_BITS == 64
1157 int addr_reg2;
1158 # endif
1159 uint32_t *label_ptr;
1160 #endif
1161
1162 #ifdef TARGET_WORDS_BIGENDIAN
1163 bswap = 1;
1164 #else
1165 bswap = 0;
1166 #endif
1167 data_reg = *args++;
1168 if (opc == 3)
1169 data_reg2 = *args++;
1170 else
1171 data_reg2 = 0; /* suppress warning */
1172 addr_reg = *args++;
1173 #ifdef CONFIG_SOFTMMU
1174 # if TARGET_LONG_BITS == 64
1175 addr_reg2 = *args++;
1176 # endif
1177 mem_index = *args;
1178 s_bits = opc & 3;
1179
1180 /* Should generate something like the following:
1181 * shr r8, addr_reg, #TARGET_PAGE_BITS
1182 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8
1183 * add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1184 */
1185 # if CPU_TLB_BITS > 8
1186 # error
1187 # endif
1188 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_R8,
1189 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1190 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1191 TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
1192 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
1193 TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1194 /* We assume that the offset is contained within 20 bits. */
1195 tlb_offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_read);
1196 assert((tlb_offset & ~0xfffff) == 0);
1197 if (tlb_offset > 0xfff) {
1198 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1199 0xa00 | (tlb_offset >> 12));
1200 tlb_offset &= 0xfff;
1201 }
1202 tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
1203 tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
1204 TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1205 /* Check alignment. */
1206 if (s_bits)
1207 tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1208 0, addr_reg, (1 << s_bits) - 1);
1209 # if TARGET_LONG_BITS == 64
1210 /* XXX: possibly we could use a block data load in the first access. */
1211 tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
1212 tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1213 TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1214 # endif
1215 tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1216 offsetof(CPUTLBEntry, addend)
1217 - offsetof(CPUTLBEntry, addr_read));
1218
1219 switch (opc) {
1220 case 0:
1221 tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1222 break;
1223 case 0 | 4:
1224 tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1225 break;
1226 case 1:
1227 tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1228 if (bswap) {
1229 tcg_out_bswap16(s, COND_EQ, data_reg, data_reg);
1230 }
1231 break;
1232 case 1 | 4:
1233 if (bswap) {
1234 tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1235 tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg);
1236 } else {
1237 tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1238 }
1239 break;
1240 case 2:
1241 default:
1242 tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1243 if (bswap) {
1244 tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
1245 }
1246 break;
1247 case 3:
1248 if (bswap) {
1249 tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg);
1250 tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
1251 tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2);
1252 tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
1253 } else {
1254 tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
1255 tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
1256 }
1257 break;
1258 }
1259
1260 label_ptr = (void *) s->code_ptr;
1261 tcg_out_b_noaddr(s, COND_EQ);
1262
1263 /* TODO: move this code to where the constants pool will be */
1264 /* Note that this code relies on the constraints we set in arm_op_defs[]
1265 * to ensure that later arguments are not passed to us in registers we
1266 * trash by moving the earlier arguments into them.
1267 */
1268 argreg = TCG_REG_R0;
1269 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
1270 #if TARGET_LONG_BITS == 64
1271 argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
1272 #else
1273 argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
1274 #endif
1275 argreg = tcg_out_arg_imm32(s, argreg, mem_index);
1276 tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
1277
1278 switch (opc) {
1279 case 0 | 4:
1280 tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
1281 break;
1282 case 1 | 4:
1283 tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
1284 break;
1285 case 0:
1286 case 1:
1287 case 2:
1288 default:
1289 tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
1290 break;
1291 case 3:
1292 tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
1293 tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
1294 break;
1295 }
1296
1297 reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1298 #else /* !CONFIG_SOFTMMU */
1299 if (GUEST_BASE) {
1300 uint32_t offset = GUEST_BASE;
1301 int i;
1302 int rot;
1303
1304 while (offset) {
1305 i = ctz32(offset) & ~1;
1306 rot = ((32 - i) << 7) & 0xf00;
1307
1308 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
1309 ((offset >> i) & 0xff) | rot);
1310 addr_reg = TCG_REG_R8;
1311 offset &= ~(0xff << i);
1312 }
1313 }
1314 switch (opc) {
1315 case 0:
1316 tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
1317 break;
1318 case 0 | 4:
1319 tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
1320 break;
1321 case 1:
1322 tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1323 if (bswap) {
1324 tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
1325 }
1326 break;
1327 case 1 | 4:
1328 if (bswap) {
1329 tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1330 tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
1331 } else {
1332 tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
1333 }
1334 break;
1335 case 2:
1336 default:
1337 tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1338 if (bswap) {
1339 tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1340 }
1341 break;
1342 case 3:
1343 /* TODO: use block load -
1344 * check that data_reg2 > data_reg or the other way */
1345 if (data_reg == addr_reg) {
1346 tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1347 tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1348 } else {
1349 tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1350 tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1351 }
1352 if (bswap) {
1353 tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1354 tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
1355 }
1356 break;
1357 }
1358 #endif
1359 }
1360
1361 static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
1362 {
1363 int addr_reg, data_reg, data_reg2, bswap;
1364 #ifdef CONFIG_SOFTMMU
1365 int mem_index, s_bits, tlb_offset;
1366 TCGReg argreg;
1367 # if TARGET_LONG_BITS == 64
1368 int addr_reg2;
1369 # endif
1370 uint32_t *label_ptr;
1371 #endif
1372
1373 #ifdef TARGET_WORDS_BIGENDIAN
1374 bswap = 1;
1375 #else
1376 bswap = 0;
1377 #endif
1378 data_reg = *args++;
1379 if (opc == 3)
1380 data_reg2 = *args++;
1381 else
1382 data_reg2 = 0; /* suppress warning */
1383 addr_reg = *args++;
1384 #ifdef CONFIG_SOFTMMU
1385 # if TARGET_LONG_BITS == 64
1386 addr_reg2 = *args++;
1387 # endif
1388 mem_index = *args;
1389 s_bits = opc & 3;
1390
1391 /* Should generate something like the following:
1392 * shr r8, addr_reg, #TARGET_PAGE_BITS
1393 * and r0, r8, #(CPU_TLB_SIZE - 1) @ Assumption: CPU_TLB_BITS <= 8
1394 * add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1395 */
1396 tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1397 TCG_REG_R8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1398 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1399 TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
1400 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
1401 TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1402 /* We assume that the offset is contained within 20 bits. */
1403 tlb_offset = offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
1404 assert((tlb_offset & ~0xfffff) == 0);
1405 if (tlb_offset > 0xfff) {
1406 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1407 0xa00 | (tlb_offset >> 12));
1408 tlb_offset &= 0xfff;
1409 }
1410 tcg_out_ld32_12wb(s, COND_AL, TCG_REG_R1, TCG_REG_R0, tlb_offset);
1411 tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
1412 TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1413 /* Check alignment. */
1414 if (s_bits)
1415 tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1416 0, addr_reg, (1 << s_bits) - 1);
1417 # if TARGET_LONG_BITS == 64
1418 /* XXX: possibly we could use a block data load in the first access. */
1419 tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0, 4);
1420 tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1421 TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1422 # endif
1423 tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1424 offsetof(CPUTLBEntry, addend)
1425 - offsetof(CPUTLBEntry, addr_write));
1426
1427 switch (opc) {
1428 case 0:
1429 tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1430 break;
1431 case 1:
1432 if (bswap) {
1433 tcg_out_bswap16st(s, COND_EQ, TCG_REG_R0, data_reg);
1434 tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
1435 } else {
1436 tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1437 }
1438 break;
1439 case 2:
1440 default:
1441 if (bswap) {
1442 tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1443 tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
1444 } else {
1445 tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1446 }
1447 break;
1448 case 3:
1449 if (bswap) {
1450 tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
1451 tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
1452 tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1453 tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
1454 } else {
1455 tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
1456 tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
1457 }
1458 break;
1459 }
1460
1461 label_ptr = (void *) s->code_ptr;
1462 tcg_out_b_noaddr(s, COND_EQ);
1463
1464 /* TODO: move this code to where the constants pool will be */
1465 /* Note that this code relies on the constraints we set in arm_op_defs[]
1466 * to ensure that later arguments are not passed to us in registers we
1467 * trash by moving the earlier arguments into them.
1468 */
1469 argreg = TCG_REG_R0;
1470 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
1471 #if TARGET_LONG_BITS == 64
1472 argreg = tcg_out_arg_reg64(s, argreg, addr_reg, addr_reg2);
1473 #else
1474 argreg = tcg_out_arg_reg32(s, argreg, addr_reg);
1475 #endif
1476
1477 switch (opc) {
1478 case 0:
1479 argreg = tcg_out_arg_reg8(s, argreg, data_reg);
1480 break;
1481 case 1:
1482 argreg = tcg_out_arg_reg16(s, argreg, data_reg);
1483 break;
1484 case 2:
1485 argreg = tcg_out_arg_reg32(s, argreg, data_reg);
1486 break;
1487 case 3:
1488 argreg = tcg_out_arg_reg64(s, argreg, data_reg, data_reg2);
1489 break;
1490 }
1491
1492 argreg = tcg_out_arg_imm32(s, argreg, mem_index);
1493 tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
1494
1495 reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1496 #else /* !CONFIG_SOFTMMU */
1497 if (GUEST_BASE) {
1498 uint32_t offset = GUEST_BASE;
1499 int i;
1500 int rot;
1501
1502 while (offset) {
1503 i = ctz32(offset) & ~1;
1504 rot = ((32 - i) << 7) & 0xf00;
1505
1506 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
1507 ((offset >> i) & 0xff) | rot);
1508 addr_reg = TCG_REG_R1;
1509 offset &= ~(0xff << i);
1510 }
1511 }
1512 switch (opc) {
1513 case 0:
1514 tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
1515 break;
1516 case 1:
1517 if (bswap) {
1518 tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, data_reg);
1519 tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1520 } else {
1521 tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
1522 }
1523 break;
1524 case 2:
1525 default:
1526 if (bswap) {
1527 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1528 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1529 } else {
1530 tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1531 }
1532 break;
1533 case 3:
1534 /* TODO: use block store -
1535 * check that data_reg2 > data_reg or the other way */
1536 if (bswap) {
1537 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
1538 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1539 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1540 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
1541 } else {
1542 tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1543 tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
1544 }
1545 break;
1546 }
1547 #endif
1548 }
1549
1550 static uint8_t *tb_ret_addr;
1551
1552 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1553 const TCGArg *args, const int *const_args)
1554 {
1555 TCGArg a0, a1, a2, a3, a4, a5;
1556 int c;
1557
1558 switch (opc) {
1559 case INDEX_op_exit_tb:
1560 {
1561 uint8_t *ld_ptr = s->code_ptr;
1562 if (args[0] >> 8)
1563 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1564 else
1565 tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1566 tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1567 if (args[0] >> 8) {
1568 *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
1569 tcg_out32(s, args[0]);
1570 }
1571 }
1572 break;
1573 case INDEX_op_goto_tb:
1574 if (s->tb_jmp_offset) {
1575 /* Direct jump method */
1576 #if defined(USE_DIRECT_JUMP)
1577 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1578 tcg_out_b_noaddr(s, COND_AL);
1579 #else
1580 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1581 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1582 tcg_out32(s, 0);
1583 #endif
1584 } else {
1585 /* Indirect jump method */
1586 #if 1
1587 c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
1588 if (c > 0xfff || c < -0xfff) {
1589 tcg_out_movi32(s, COND_AL, TCG_REG_R0,
1590 (tcg_target_long) (s->tb_next + args[0]));
1591 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1592 } else
1593 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
1594 #else
1595 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1596 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1597 tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
1598 #endif
1599 }
1600 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1601 break;
1602 case INDEX_op_call:
1603 if (const_args[0])
1604 tcg_out_call(s, args[0]);
1605 else
1606 tcg_out_callr(s, COND_AL, args[0]);
1607 break;
1608 case INDEX_op_br:
1609 tcg_out_goto_label(s, COND_AL, args[0]);
1610 break;
1611
1612 case INDEX_op_ld8u_i32:
1613 tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1614 break;
1615 case INDEX_op_ld8s_i32:
1616 tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1617 break;
1618 case INDEX_op_ld16u_i32:
1619 tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1620 break;
1621 case INDEX_op_ld16s_i32:
1622 tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1623 break;
1624 case INDEX_op_ld_i32:
1625 tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1626 break;
1627 case INDEX_op_st8_i32:
1628 tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1629 break;
1630 case INDEX_op_st16_i32:
1631 tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1632 break;
1633 case INDEX_op_st_i32:
1634 tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1635 break;
1636
1637 case INDEX_op_mov_i32:
1638 tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1639 args[0], 0, args[1], SHIFT_IMM_LSL(0));
1640 break;
1641 case INDEX_op_movi_i32:
1642 tcg_out_movi32(s, COND_AL, args[0], args[1]);
1643 break;
1644 case INDEX_op_movcond_i32:
1645 /* Constraints mean that v2 is always in the same register as dest,
1646 * so we only need to do "if condition passed, move v1 to dest".
1647 */
1648 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1649 args[1], args[2], const_args[2]);
1650 tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
1651 ARITH_MVN, args[0], 0, args[3], const_args[3]);
1652 break;
1653 case INDEX_op_add_i32:
1654 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
1655 args[0], args[1], args[2], const_args[2]);
1656 break;
1657 case INDEX_op_sub_i32:
1658 if (const_args[1]) {
1659 if (const_args[2]) {
1660 tcg_out_movi32(s, COND_AL, args[0], args[1] - args[2]);
1661 } else {
1662 tcg_out_dat_rI(s, COND_AL, ARITH_RSB,
1663 args[0], args[2], args[1], 1);
1664 }
1665 } else {
1666 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
1667 args[0], args[1], args[2], const_args[2]);
1668 }
1669 break;
1670 case INDEX_op_and_i32:
1671 tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
1672 args[0], args[1], args[2], const_args[2]);
1673 break;
1674 case INDEX_op_andc_i32:
1675 tcg_out_dat_rIK(s, COND_AL, ARITH_BIC, ARITH_AND,
1676 args[0], args[1], args[2], const_args[2]);
1677 break;
1678 case INDEX_op_or_i32:
1679 c = ARITH_ORR;
1680 goto gen_arith;
1681 case INDEX_op_xor_i32:
1682 c = ARITH_EOR;
1683 /* Fall through. */
1684 gen_arith:
1685 tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]);
1686 break;
1687 case INDEX_op_add2_i32:
1688 a0 = args[0], a1 = args[1], a2 = args[2];
1689 a3 = args[3], a4 = args[4], a5 = args[5];
1690 if (a0 == a3 || (a0 == a5 && !const_args[5])) {
1691 a0 = TCG_REG_R8;
1692 }
1693 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
1694 a0, a2, a4, const_args[4]);
1695 tcg_out_dat_rIK(s, COND_AL, ARITH_ADC, ARITH_SBC,
1696 a1, a3, a5, const_args[5]);
1697 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1698 break;
1699 case INDEX_op_sub2_i32:
1700 a0 = args[0], a1 = args[1], a2 = args[2];
1701 a3 = args[3], a4 = args[4], a5 = args[5];
1702 if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
1703 a0 = TCG_REG_R8;
1704 }
1705 if (const_args[2]) {
1706 if (const_args[4]) {
1707 tcg_out_movi32(s, COND_AL, a0, a4);
1708 a4 = a0;
1709 }
1710 tcg_out_dat_rI(s, COND_AL, ARITH_RSB | TO_CPSR, a0, a4, a2, 1);
1711 } else {
1712 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB | TO_CPSR,
1713 ARITH_ADD | TO_CPSR, a0, a2, a4, const_args[4]);
1714 }
1715 if (const_args[3]) {
1716 if (const_args[5]) {
1717 tcg_out_movi32(s, COND_AL, a1, a5);
1718 a5 = a1;
1719 }
1720 tcg_out_dat_rI(s, COND_AL, ARITH_RSC, a1, a5, a3, 1);
1721 } else {
1722 tcg_out_dat_rIK(s, COND_AL, ARITH_SBC, ARITH_ADC,
1723 a1, a3, a5, const_args[5]);
1724 }
1725 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1726 break;
1727 case INDEX_op_neg_i32:
1728 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1729 break;
1730 case INDEX_op_not_i32:
1731 tcg_out_dat_reg(s, COND_AL,
1732 ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1733 break;
1734 case INDEX_op_mul_i32:
1735 tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1736 break;
1737 case INDEX_op_mulu2_i32:
1738 tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1739 break;
1740 case INDEX_op_muls2_i32:
1741 tcg_out_smull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1742 break;
1743 /* XXX: Perhaps args[2] & 0x1f is wrong */
1744 case INDEX_op_shl_i32:
1745 c = const_args[2] ?
1746 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1747 goto gen_shift32;
1748 case INDEX_op_shr_i32:
1749 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1750 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1751 goto gen_shift32;
1752 case INDEX_op_sar_i32:
1753 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1754 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1755 goto gen_shift32;
1756 case INDEX_op_rotr_i32:
1757 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1758 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1759 /* Fall through. */
1760 gen_shift32:
1761 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1762 break;
1763
1764 case INDEX_op_rotl_i32:
1765 if (const_args[2]) {
1766 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1767 ((0x20 - args[2]) & 0x1f) ?
1768 SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1769 SHIFT_IMM_LSL(0));
1770 } else {
1771 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_R8, args[1], 0x20);
1772 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1773 SHIFT_REG_ROR(TCG_REG_R8));
1774 }
1775 break;
1776
1777 case INDEX_op_brcond_i32:
1778 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1779 args[0], args[1], const_args[1]);
1780 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
1781 break;
1782 case INDEX_op_brcond2_i32:
1783 /* The resulting conditions are:
1784 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1785 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1786 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1787 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1788 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1789 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1790 */
1791 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1792 args[1], args[3], const_args[3]);
1793 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1794 args[0], args[2], const_args[2]);
1795 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
1796 break;
1797 case INDEX_op_setcond_i32:
1798 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1799 args[1], args[2], const_args[2]);
1800 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1801 ARITH_MOV, args[0], 0, 1);
1802 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1803 ARITH_MOV, args[0], 0, 0);
1804 break;
1805 case INDEX_op_setcond2_i32:
1806 /* See brcond2_i32 comment */
1807 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1808 args[2], args[4], const_args[4]);
1809 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1810 args[1], args[3], const_args[3]);
1811 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1812 ARITH_MOV, args[0], 0, 1);
1813 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1814 ARITH_MOV, args[0], 0, 0);
1815 break;
1816
1817 case INDEX_op_qemu_ld8u:
1818 tcg_out_qemu_ld(s, args, 0);
1819 break;
1820 case INDEX_op_qemu_ld8s:
1821 tcg_out_qemu_ld(s, args, 0 | 4);
1822 break;
1823 case INDEX_op_qemu_ld16u:
1824 tcg_out_qemu_ld(s, args, 1);
1825 break;
1826 case INDEX_op_qemu_ld16s:
1827 tcg_out_qemu_ld(s, args, 1 | 4);
1828 break;
1829 case INDEX_op_qemu_ld32:
1830 tcg_out_qemu_ld(s, args, 2);
1831 break;
1832 case INDEX_op_qemu_ld64:
1833 tcg_out_qemu_ld(s, args, 3);
1834 break;
1835
1836 case INDEX_op_qemu_st8:
1837 tcg_out_qemu_st(s, args, 0);
1838 break;
1839 case INDEX_op_qemu_st16:
1840 tcg_out_qemu_st(s, args, 1);
1841 break;
1842 case INDEX_op_qemu_st32:
1843 tcg_out_qemu_st(s, args, 2);
1844 break;
1845 case INDEX_op_qemu_st64:
1846 tcg_out_qemu_st(s, args, 3);
1847 break;
1848
1849 case INDEX_op_bswap16_i32:
1850 tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1851 break;
1852 case INDEX_op_bswap32_i32:
1853 tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1854 break;
1855
1856 case INDEX_op_ext8s_i32:
1857 tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1858 break;
1859 case INDEX_op_ext16s_i32:
1860 tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1861 break;
1862 case INDEX_op_ext16u_i32:
1863 tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1864 break;
1865
1866 case INDEX_op_deposit_i32:
1867 tcg_out_deposit(s, COND_AL, args[0], args[2],
1868 args[3], args[4], const_args[2]);
1869 break;
1870
1871 default:
1872 tcg_abort();
1873 }
1874 }
1875
1876 static const TCGTargetOpDef arm_op_defs[] = {
1877 { INDEX_op_exit_tb, { } },
1878 { INDEX_op_goto_tb, { } },
1879 { INDEX_op_call, { "ri" } },
1880 { INDEX_op_br, { } },
1881
1882 { INDEX_op_mov_i32, { "r", "r" } },
1883 { INDEX_op_movi_i32, { "r" } },
1884
1885 { INDEX_op_ld8u_i32, { "r", "r" } },
1886 { INDEX_op_ld8s_i32, { "r", "r" } },
1887 { INDEX_op_ld16u_i32, { "r", "r" } },
1888 { INDEX_op_ld16s_i32, { "r", "r" } },
1889 { INDEX_op_ld_i32, { "r", "r" } },
1890 { INDEX_op_st8_i32, { "r", "r" } },
1891 { INDEX_op_st16_i32, { "r", "r" } },
1892 { INDEX_op_st_i32, { "r", "r" } },
1893
1894 /* TODO: "r", "r", "ri" */
1895 { INDEX_op_add_i32, { "r", "r", "rIN" } },
1896 { INDEX_op_sub_i32, { "r", "rI", "rIN" } },
1897 { INDEX_op_mul_i32, { "r", "r", "r" } },
1898 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1899 { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
1900 { INDEX_op_and_i32, { "r", "r", "rIK" } },
1901 { INDEX_op_andc_i32, { "r", "r", "rIK" } },
1902 { INDEX_op_or_i32, { "r", "r", "rI" } },
1903 { INDEX_op_xor_i32, { "r", "r", "rI" } },
1904 { INDEX_op_neg_i32, { "r", "r" } },
1905 { INDEX_op_not_i32, { "r", "r" } },
1906
1907 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1908 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1909 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1910 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1911 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1912
1913 { INDEX_op_brcond_i32, { "r", "rIN" } },
1914 { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
1915 { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
1916
1917 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
1918 { INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1919 { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
1920 { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
1921
1922 #if TARGET_LONG_BITS == 32
1923 { INDEX_op_qemu_ld8u, { "r", "l" } },
1924 { INDEX_op_qemu_ld8s, { "r", "l" } },
1925 { INDEX_op_qemu_ld16u, { "r", "l" } },
1926 { INDEX_op_qemu_ld16s, { "r", "l" } },
1927 { INDEX_op_qemu_ld32, { "r", "l" } },
1928 { INDEX_op_qemu_ld64, { "L", "L", "l" } },
1929
1930 { INDEX_op_qemu_st8, { "s", "s" } },
1931 { INDEX_op_qemu_st16, { "s", "s" } },
1932 { INDEX_op_qemu_st32, { "s", "s" } },
1933 { INDEX_op_qemu_st64, { "S", "S", "s" } },
1934 #else
1935 { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
1936 { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
1937 { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
1938 { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
1939 { INDEX_op_qemu_ld32, { "r", "l", "l" } },
1940 { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
1941
1942 { INDEX_op_qemu_st8, { "s", "s", "s" } },
1943 { INDEX_op_qemu_st16, { "s", "s", "s" } },
1944 { INDEX_op_qemu_st32, { "s", "s", "s" } },
1945 { INDEX_op_qemu_st64, { "S", "S", "s", "s" } },
1946 #endif
1947
1948 { INDEX_op_bswap16_i32, { "r", "r" } },
1949 { INDEX_op_bswap32_i32, { "r", "r" } },
1950
1951 { INDEX_op_ext8s_i32, { "r", "r" } },
1952 { INDEX_op_ext16s_i32, { "r", "r" } },
1953 { INDEX_op_ext16u_i32, { "r", "r" } },
1954
1955 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1956
1957 { -1 },
1958 };
1959
1960 static void tcg_target_init(TCGContext *s)
1961 {
1962 #if !defined(CONFIG_USER_ONLY)
1963 /* fail safe */
1964 if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1965 tcg_abort();
1966 #endif
1967
1968 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1969 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1970 (1 << TCG_REG_R0) |
1971 (1 << TCG_REG_R1) |
1972 (1 << TCG_REG_R2) |
1973 (1 << TCG_REG_R3) |
1974 (1 << TCG_REG_R12) |
1975 (1 << TCG_REG_R14));
1976
1977 tcg_regset_clear(s->reserved_regs);
1978 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
1979 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
1980 tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
1981
1982 tcg_add_target_add_op_defs(arm_op_defs);
1983 }
1984
1985 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
1986 TCGReg arg1, tcg_target_long arg2)
1987 {
1988 tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
1989 }
1990
1991 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
1992 TCGReg arg1, tcg_target_long arg2)
1993 {
1994 tcg_out_st32(s, COND_AL, arg, arg1, arg2);
1995 }
1996
1997 static inline void tcg_out_mov(TCGContext *s, TCGType type,
1998 TCGReg ret, TCGReg arg)
1999 {
2000 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
2001 }
2002
2003 static inline void tcg_out_movi(TCGContext *s, TCGType type,
2004 TCGReg ret, tcg_target_long arg)
2005 {
2006 tcg_out_movi32(s, COND_AL, ret, arg);
2007 }
2008
2009 static void tcg_target_qemu_prologue(TCGContext *s)
2010 {
2011 int frame_size;
2012
2013 /* Calling convention requires us to save r4-r11 and lr. */
2014 /* stmdb sp!, { r4 - r11, lr } */
2015 tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
2016
2017 /* Allocate the local stack frame. */
2018 frame_size = TCG_STATIC_CALL_ARGS_SIZE;
2019 frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long);
2020 /* We saved an odd number of registers above; keep an 8 aligned stack. */
2021 frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1)
2022 & -TCG_TARGET_STACK_ALIGN) + 4;
2023
2024 tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
2025 TCG_REG_CALL_STACK, frame_size, 1);
2026 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
2027 CPU_TEMP_BUF_NLONGS * sizeof(long));
2028
2029 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2030
2031 tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
2032 tb_ret_addr = s->code_ptr;
2033
2034 /* Epilogue. We branch here via tb_ret_addr. */
2035 tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
2036 TCG_REG_CALL_STACK, frame_size, 1);
2037
2038 /* ldmia sp!, { r4 - r11, pc } */
2039 tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
2040 }