]> git.proxmox.com Git - mirror_qemu.git/blob - tcg/arm/tcg-target.inc.c
tcg: Pass the opcode width to target_parse_constraint
[mirror_qemu.git] / tcg / arm / tcg-target.inc.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 #include "elf.h"
26 #include "tcg-be-ldst.h"
27
28 int arm_arch = __ARM_ARCH;
29
30 #ifndef use_idiv_instructions
31 bool use_idiv_instructions;
32 #endif
33
34 /* ??? Ought to think about changing CONFIG_SOFTMMU to always defined. */
35 #ifdef CONFIG_SOFTMMU
36 # define USING_SOFTMMU 1
37 #else
38 # define USING_SOFTMMU 0
39 #endif
40
41 #ifdef CONFIG_DEBUG_TCG
42 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
43 "%r0",
44 "%r1",
45 "%r2",
46 "%r3",
47 "%r4",
48 "%r5",
49 "%r6",
50 "%r7",
51 "%r8",
52 "%r9",
53 "%r10",
54 "%r11",
55 "%r12",
56 "%r13",
57 "%r14",
58 "%pc",
59 };
60 #endif
61
62 static const int tcg_target_reg_alloc_order[] = {
63 TCG_REG_R4,
64 TCG_REG_R5,
65 TCG_REG_R6,
66 TCG_REG_R7,
67 TCG_REG_R8,
68 TCG_REG_R9,
69 TCG_REG_R10,
70 TCG_REG_R11,
71 TCG_REG_R13,
72 TCG_REG_R0,
73 TCG_REG_R1,
74 TCG_REG_R2,
75 TCG_REG_R3,
76 TCG_REG_R12,
77 TCG_REG_R14,
78 };
79
80 static const int tcg_target_call_iarg_regs[4] = {
81 TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
82 };
83 static const int tcg_target_call_oarg_regs[2] = {
84 TCG_REG_R0, TCG_REG_R1
85 };
86
87 #define TCG_REG_TMP TCG_REG_R12
88
89 static inline void reloc_pc24(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
90 {
91 ptrdiff_t offset = (tcg_ptr_byte_diff(target, code_ptr) - 8) >> 2;
92 *code_ptr = (*code_ptr & ~0xffffff) | (offset & 0xffffff);
93 }
94
95 static inline void reloc_pc24_atomic(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
96 {
97 ptrdiff_t offset = (tcg_ptr_byte_diff(target, code_ptr) - 8) >> 2;
98 tcg_insn_unit insn = atomic_read(code_ptr);
99 tcg_debug_assert(offset == sextract32(offset, 0, 24));
100 atomic_set(code_ptr, deposit32(insn, 0, 24, offset));
101 }
102
103 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
104 intptr_t value, intptr_t addend)
105 {
106 tcg_debug_assert(type == R_ARM_PC24);
107 tcg_debug_assert(addend == 0);
108 reloc_pc24(code_ptr, (tcg_insn_unit *)value);
109 }
110
111 #define TCG_CT_CONST_ARM 0x100
112 #define TCG_CT_CONST_INV 0x200
113 #define TCG_CT_CONST_NEG 0x400
114 #define TCG_CT_CONST_ZERO 0x800
115
116 /* parse target specific constraints */
117 static const char *target_parse_constraint(TCGArgConstraint *ct,
118 const char *ct_str, TCGType type)
119 {
120 switch (*ct_str++) {
121 case 'I':
122 ct->ct |= TCG_CT_CONST_ARM;
123 break;
124 case 'K':
125 ct->ct |= TCG_CT_CONST_INV;
126 break;
127 case 'N': /* The gcc constraint letter is L, already used here. */
128 ct->ct |= TCG_CT_CONST_NEG;
129 break;
130 case 'Z':
131 ct->ct |= TCG_CT_CONST_ZERO;
132 break;
133
134 case 'r':
135 ct->ct |= TCG_CT_REG;
136 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
137 break;
138
139 /* qemu_ld address */
140 case 'l':
141 ct->ct |= TCG_CT_REG;
142 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
143 #ifdef CONFIG_SOFTMMU
144 /* r0-r2,lr will be overwritten when reading the tlb entry,
145 so don't use these. */
146 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
147 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
148 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
149 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
150 #endif
151 break;
152
153 /* qemu_st address & data */
154 case 's':
155 ct->ct |= TCG_CT_REG;
156 tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
157 /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
158 and r0-r1 doing the byte swapping, so don't use these. */
159 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
160 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
161 #if defined(CONFIG_SOFTMMU)
162 /* Avoid clashes with registers being used for helper args */
163 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
164 #if TARGET_LONG_BITS == 64
165 /* Avoid clashes with registers being used for helper args */
166 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
167 #endif
168 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
169 #endif
170 break;
171
172 default:
173 return NULL;
174 }
175 return ct_str;
176 }
177
178 static inline uint32_t rotl(uint32_t val, int n)
179 {
180 return (val << n) | (val >> (32 - n));
181 }
182
183 /* ARM immediates for ALU instructions are made of an unsigned 8-bit
184 right-rotated by an even amount between 0 and 30. */
185 static inline int encode_imm(uint32_t imm)
186 {
187 int shift;
188
189 /* simple case, only lower bits */
190 if ((imm & ~0xff) == 0)
191 return 0;
192 /* then try a simple even shift */
193 shift = ctz32(imm) & ~1;
194 if (((imm >> shift) & ~0xff) == 0)
195 return 32 - shift;
196 /* now try harder with rotations */
197 if ((rotl(imm, 2) & ~0xff) == 0)
198 return 2;
199 if ((rotl(imm, 4) & ~0xff) == 0)
200 return 4;
201 if ((rotl(imm, 6) & ~0xff) == 0)
202 return 6;
203 /* imm can't be encoded */
204 return -1;
205 }
206
207 static inline int check_fit_imm(uint32_t imm)
208 {
209 return encode_imm(imm) >= 0;
210 }
211
212 /* Test if a constant matches the constraint.
213 * TODO: define constraints for:
214 *
215 * ldr/str offset: between -0xfff and 0xfff
216 * ldrh/strh offset: between -0xff and 0xff
217 * mov operand2: values represented with x << (2 * y), x < 0x100
218 * add, sub, eor...: ditto
219 */
220 static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
221 const TCGArgConstraint *arg_ct)
222 {
223 int ct;
224 ct = arg_ct->ct;
225 if (ct & TCG_CT_CONST) {
226 return 1;
227 } else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
228 return 1;
229 } else if ((ct & TCG_CT_CONST_INV) && check_fit_imm(~val)) {
230 return 1;
231 } else if ((ct & TCG_CT_CONST_NEG) && check_fit_imm(-val)) {
232 return 1;
233 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
234 return 1;
235 } else {
236 return 0;
237 }
238 }
239
240 #define TO_CPSR (1 << 20)
241
242 typedef enum {
243 ARITH_AND = 0x0 << 21,
244 ARITH_EOR = 0x1 << 21,
245 ARITH_SUB = 0x2 << 21,
246 ARITH_RSB = 0x3 << 21,
247 ARITH_ADD = 0x4 << 21,
248 ARITH_ADC = 0x5 << 21,
249 ARITH_SBC = 0x6 << 21,
250 ARITH_RSC = 0x7 << 21,
251 ARITH_TST = 0x8 << 21 | TO_CPSR,
252 ARITH_CMP = 0xa << 21 | TO_CPSR,
253 ARITH_CMN = 0xb << 21 | TO_CPSR,
254 ARITH_ORR = 0xc << 21,
255 ARITH_MOV = 0xd << 21,
256 ARITH_BIC = 0xe << 21,
257 ARITH_MVN = 0xf << 21,
258
259 INSN_LDR_IMM = 0x04100000,
260 INSN_LDR_REG = 0x06100000,
261 INSN_STR_IMM = 0x04000000,
262 INSN_STR_REG = 0x06000000,
263
264 INSN_LDRH_IMM = 0x005000b0,
265 INSN_LDRH_REG = 0x001000b0,
266 INSN_LDRSH_IMM = 0x005000f0,
267 INSN_LDRSH_REG = 0x001000f0,
268 INSN_STRH_IMM = 0x004000b0,
269 INSN_STRH_REG = 0x000000b0,
270
271 INSN_LDRB_IMM = 0x04500000,
272 INSN_LDRB_REG = 0x06500000,
273 INSN_LDRSB_IMM = 0x005000d0,
274 INSN_LDRSB_REG = 0x001000d0,
275 INSN_STRB_IMM = 0x04400000,
276 INSN_STRB_REG = 0x06400000,
277
278 INSN_LDRD_IMM = 0x004000d0,
279 INSN_LDRD_REG = 0x000000d0,
280 INSN_STRD_IMM = 0x004000f0,
281 INSN_STRD_REG = 0x000000f0,
282
283 INSN_DMB_ISH = 0x5bf07ff5,
284 INSN_DMB_MCR = 0xba0f07ee,
285
286 } ARMInsn;
287
288 #define SHIFT_IMM_LSL(im) (((im) << 7) | 0x00)
289 #define SHIFT_IMM_LSR(im) (((im) << 7) | 0x20)
290 #define SHIFT_IMM_ASR(im) (((im) << 7) | 0x40)
291 #define SHIFT_IMM_ROR(im) (((im) << 7) | 0x60)
292 #define SHIFT_REG_LSL(rs) (((rs) << 8) | 0x10)
293 #define SHIFT_REG_LSR(rs) (((rs) << 8) | 0x30)
294 #define SHIFT_REG_ASR(rs) (((rs) << 8) | 0x50)
295 #define SHIFT_REG_ROR(rs) (((rs) << 8) | 0x70)
296
297 enum arm_cond_code_e {
298 COND_EQ = 0x0,
299 COND_NE = 0x1,
300 COND_CS = 0x2, /* Unsigned greater or equal */
301 COND_CC = 0x3, /* Unsigned less than */
302 COND_MI = 0x4, /* Negative */
303 COND_PL = 0x5, /* Zero or greater */
304 COND_VS = 0x6, /* Overflow */
305 COND_VC = 0x7, /* No overflow */
306 COND_HI = 0x8, /* Unsigned greater than */
307 COND_LS = 0x9, /* Unsigned less or equal */
308 COND_GE = 0xa,
309 COND_LT = 0xb,
310 COND_GT = 0xc,
311 COND_LE = 0xd,
312 COND_AL = 0xe,
313 };
314
315 static const uint8_t tcg_cond_to_arm_cond[] = {
316 [TCG_COND_EQ] = COND_EQ,
317 [TCG_COND_NE] = COND_NE,
318 [TCG_COND_LT] = COND_LT,
319 [TCG_COND_GE] = COND_GE,
320 [TCG_COND_LE] = COND_LE,
321 [TCG_COND_GT] = COND_GT,
322 /* unsigned */
323 [TCG_COND_LTU] = COND_CC,
324 [TCG_COND_GEU] = COND_CS,
325 [TCG_COND_LEU] = COND_LS,
326 [TCG_COND_GTU] = COND_HI,
327 };
328
329 static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
330 {
331 tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
332 }
333
334 static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
335 {
336 tcg_out32(s, (cond << 28) | 0x0a000000 |
337 (((offset - 8) >> 2) & 0x00ffffff));
338 }
339
340 static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
341 {
342 /* We pay attention here to not modify the branch target by masking
343 the corresponding bytes. This ensure that caches and memory are
344 kept coherent during retranslation. */
345 tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0a));
346 }
347
348 static inline void tcg_out_bl_noaddr(TCGContext *s, int cond)
349 {
350 /* We pay attention here to not modify the branch target by masking
351 the corresponding bytes. This ensure that caches and memory are
352 kept coherent during retranslation. */
353 tcg_out32(s, deposit32(*s->code_ptr, 24, 8, (cond << 4) | 0x0b));
354 }
355
356 static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
357 {
358 tcg_out32(s, (cond << 28) | 0x0b000000 |
359 (((offset - 8) >> 2) & 0x00ffffff));
360 }
361
362 static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
363 {
364 tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
365 }
366
367 static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
368 {
369 tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
370 (((offset - 8) >> 2) & 0x00ffffff));
371 }
372
373 static inline void tcg_out_dat_reg(TCGContext *s,
374 int cond, int opc, int rd, int rn, int rm, int shift)
375 {
376 tcg_out32(s, (cond << 28) | (0 << 25) | opc |
377 (rn << 16) | (rd << 12) | shift | rm);
378 }
379
380 static inline void tcg_out_nop(TCGContext *s)
381 {
382 if (use_armv7_instructions) {
383 /* Architected nop introduced in v6k. */
384 /* ??? This is an MSR (imm) 0,0,0 insn. Anyone know if this
385 also Just So Happened to do nothing on pre-v6k so that we
386 don't need to conditionalize it? */
387 tcg_out32(s, 0xe320f000);
388 } else {
389 /* Prior to that the assembler uses mov r0, r0. */
390 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 0, 0, 0, SHIFT_IMM_LSL(0));
391 }
392 }
393
394 static inline void tcg_out_mov_reg(TCGContext *s, int cond, int rd, int rm)
395 {
396 /* Simple reg-reg move, optimising out the 'do nothing' case */
397 if (rd != rm) {
398 tcg_out_dat_reg(s, cond, ARITH_MOV, rd, 0, rm, SHIFT_IMM_LSL(0));
399 }
400 }
401
402 static inline void tcg_out_dat_imm(TCGContext *s,
403 int cond, int opc, int rd, int rn, int im)
404 {
405 tcg_out32(s, (cond << 28) | (1 << 25) | opc |
406 (rn << 16) | (rd << 12) | im);
407 }
408
409 static void tcg_out_movi32(TCGContext *s, int cond, int rd, uint32_t arg)
410 {
411 int rot, opc, rn;
412
413 /* For armv7, make sure not to use movw+movt when mov/mvn would do.
414 Speed things up by only checking when movt would be required.
415 Prior to armv7, have one go at fully rotated immediates before
416 doing the decomposition thing below. */
417 if (!use_armv7_instructions || (arg & 0xffff0000)) {
418 rot = encode_imm(arg);
419 if (rot >= 0) {
420 tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0,
421 rotl(arg, rot) | (rot << 7));
422 return;
423 }
424 rot = encode_imm(~arg);
425 if (rot >= 0) {
426 tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0,
427 rotl(~arg, rot) | (rot << 7));
428 return;
429 }
430 }
431
432 /* Use movw + movt. */
433 if (use_armv7_instructions) {
434 /* movw */
435 tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
436 | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
437 if (arg & 0xffff0000) {
438 /* movt */
439 tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
440 | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
441 }
442 return;
443 }
444
445 /* TODO: This is very suboptimal, we can easily have a constant
446 pool somewhere after all the instructions. */
447 opc = ARITH_MOV;
448 rn = 0;
449 /* If we have lots of leading 1's, we can shorten the sequence by
450 beginning with mvn and then clearing higher bits with eor. */
451 if (clz32(~arg) > clz32(arg)) {
452 opc = ARITH_MVN, arg = ~arg;
453 }
454 do {
455 int i = ctz32(arg) & ~1;
456 rot = ((32 - i) << 7) & 0xf00;
457 tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
458 arg &= ~(0xff << i);
459
460 opc = ARITH_EOR;
461 rn = rd;
462 } while (arg);
463 }
464
465 static inline void tcg_out_dat_rI(TCGContext *s, int cond, int opc, TCGArg dst,
466 TCGArg lhs, TCGArg rhs, int rhs_is_const)
467 {
468 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
469 * rhs must satisfy the "rI" constraint.
470 */
471 if (rhs_is_const) {
472 int rot = encode_imm(rhs);
473 tcg_debug_assert(rot >= 0);
474 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
475 } else {
476 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
477 }
478 }
479
480 static void tcg_out_dat_rIK(TCGContext *s, int cond, int opc, int opinv,
481 TCGReg dst, TCGReg lhs, TCGArg rhs,
482 bool rhs_is_const)
483 {
484 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
485 * rhs must satisfy the "rIK" constraint.
486 */
487 if (rhs_is_const) {
488 int rot = encode_imm(rhs);
489 if (rot < 0) {
490 rhs = ~rhs;
491 rot = encode_imm(rhs);
492 tcg_debug_assert(rot >= 0);
493 opc = opinv;
494 }
495 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
496 } else {
497 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
498 }
499 }
500
501 static void tcg_out_dat_rIN(TCGContext *s, int cond, int opc, int opneg,
502 TCGArg dst, TCGArg lhs, TCGArg rhs,
503 bool rhs_is_const)
504 {
505 /* Emit either the reg,imm or reg,reg form of a data-processing insn.
506 * rhs must satisfy the "rIN" constraint.
507 */
508 if (rhs_is_const) {
509 int rot = encode_imm(rhs);
510 if (rot < 0) {
511 rhs = -rhs;
512 rot = encode_imm(rhs);
513 tcg_debug_assert(rot >= 0);
514 opc = opneg;
515 }
516 tcg_out_dat_imm(s, cond, opc, dst, lhs, rotl(rhs, rot) | (rot << 7));
517 } else {
518 tcg_out_dat_reg(s, cond, opc, dst, lhs, rhs, SHIFT_IMM_LSL(0));
519 }
520 }
521
522 static inline void tcg_out_mul32(TCGContext *s, int cond, TCGReg rd,
523 TCGReg rn, TCGReg rm)
524 {
525 /* if ArchVersion() < 6 && d == n then UNPREDICTABLE; */
526 if (!use_armv6_instructions && rd == rn) {
527 if (rd == rm) {
528 /* rd == rn == rm; copy an input to tmp first. */
529 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
530 rm = rn = TCG_REG_TMP;
531 } else {
532 rn = rm;
533 rm = rd;
534 }
535 }
536 /* mul */
537 tcg_out32(s, (cond << 28) | 0x90 | (rd << 16) | (rm << 8) | rn);
538 }
539
540 static inline void tcg_out_umull32(TCGContext *s, int cond, TCGReg rd0,
541 TCGReg rd1, TCGReg rn, TCGReg rm)
542 {
543 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
544 if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
545 if (rd0 == rm || rd1 == rm) {
546 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
547 rn = TCG_REG_TMP;
548 } else {
549 TCGReg t = rn;
550 rn = rm;
551 rm = t;
552 }
553 }
554 /* umull */
555 tcg_out32(s, (cond << 28) | 0x00800090 |
556 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
557 }
558
559 static inline void tcg_out_smull32(TCGContext *s, int cond, TCGReg rd0,
560 TCGReg rd1, TCGReg rn, TCGReg rm)
561 {
562 /* if ArchVersion() < 6 && (dHi == n || dLo == n) then UNPREDICTABLE; */
563 if (!use_armv6_instructions && (rd0 == rn || rd1 == rn)) {
564 if (rd0 == rm || rd1 == rm) {
565 tcg_out_mov_reg(s, cond, TCG_REG_TMP, rn);
566 rn = TCG_REG_TMP;
567 } else {
568 TCGReg t = rn;
569 rn = rm;
570 rm = t;
571 }
572 }
573 /* smull */
574 tcg_out32(s, (cond << 28) | 0x00c00090 |
575 (rd1 << 16) | (rd0 << 12) | (rm << 8) | rn);
576 }
577
578 static inline void tcg_out_sdiv(TCGContext *s, int cond, int rd, int rn, int rm)
579 {
580 tcg_out32(s, 0x0710f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
581 }
582
583 static inline void tcg_out_udiv(TCGContext *s, int cond, int rd, int rn, int rm)
584 {
585 tcg_out32(s, 0x0730f010 | (cond << 28) | (rd << 16) | rn | (rm << 8));
586 }
587
588 static inline void tcg_out_ext8s(TCGContext *s, int cond,
589 int rd, int rn)
590 {
591 if (use_armv6_instructions) {
592 /* sxtb */
593 tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
594 } else {
595 tcg_out_dat_reg(s, cond, ARITH_MOV,
596 rd, 0, rn, SHIFT_IMM_LSL(24));
597 tcg_out_dat_reg(s, cond, ARITH_MOV,
598 rd, 0, rd, SHIFT_IMM_ASR(24));
599 }
600 }
601
602 static inline void tcg_out_ext8u(TCGContext *s, int cond,
603 int rd, int rn)
604 {
605 tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
606 }
607
608 static inline void tcg_out_ext16s(TCGContext *s, int cond,
609 int rd, int rn)
610 {
611 if (use_armv6_instructions) {
612 /* sxth */
613 tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
614 } else {
615 tcg_out_dat_reg(s, cond, ARITH_MOV,
616 rd, 0, rn, SHIFT_IMM_LSL(16));
617 tcg_out_dat_reg(s, cond, ARITH_MOV,
618 rd, 0, rd, SHIFT_IMM_ASR(16));
619 }
620 }
621
622 static inline void tcg_out_ext16u(TCGContext *s, int cond,
623 int rd, int rn)
624 {
625 if (use_armv6_instructions) {
626 /* uxth */
627 tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
628 } else {
629 tcg_out_dat_reg(s, cond, ARITH_MOV,
630 rd, 0, rn, SHIFT_IMM_LSL(16));
631 tcg_out_dat_reg(s, cond, ARITH_MOV,
632 rd, 0, rd, SHIFT_IMM_LSR(16));
633 }
634 }
635
636 static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
637 {
638 if (use_armv6_instructions) {
639 /* revsh */
640 tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
641 } else {
642 tcg_out_dat_reg(s, cond, ARITH_MOV,
643 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
644 tcg_out_dat_reg(s, cond, ARITH_MOV,
645 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_ASR(16));
646 tcg_out_dat_reg(s, cond, ARITH_ORR,
647 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
648 }
649 }
650
651 static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
652 {
653 if (use_armv6_instructions) {
654 /* rev16 */
655 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
656 } else {
657 tcg_out_dat_reg(s, cond, ARITH_MOV,
658 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSL(24));
659 tcg_out_dat_reg(s, cond, ARITH_MOV,
660 TCG_REG_TMP, 0, TCG_REG_TMP, SHIFT_IMM_LSR(16));
661 tcg_out_dat_reg(s, cond, ARITH_ORR,
662 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSR(8));
663 }
664 }
665
666 /* swap the two low bytes assuming that the two high input bytes and the
667 two high output bit can hold any value. */
668 static inline void tcg_out_bswap16st(TCGContext *s, int cond, int rd, int rn)
669 {
670 if (use_armv6_instructions) {
671 /* rev16 */
672 tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
673 } else {
674 tcg_out_dat_reg(s, cond, ARITH_MOV,
675 TCG_REG_TMP, 0, rn, SHIFT_IMM_LSR(8));
676 tcg_out_dat_imm(s, cond, ARITH_AND, TCG_REG_TMP, TCG_REG_TMP, 0xff);
677 tcg_out_dat_reg(s, cond, ARITH_ORR,
678 rd, TCG_REG_TMP, rn, SHIFT_IMM_LSL(8));
679 }
680 }
681
682 static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
683 {
684 if (use_armv6_instructions) {
685 /* rev */
686 tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
687 } else {
688 tcg_out_dat_reg(s, cond, ARITH_EOR,
689 TCG_REG_TMP, rn, rn, SHIFT_IMM_ROR(16));
690 tcg_out_dat_imm(s, cond, ARITH_BIC,
691 TCG_REG_TMP, TCG_REG_TMP, 0xff | 0x800);
692 tcg_out_dat_reg(s, cond, ARITH_MOV,
693 rd, 0, rn, SHIFT_IMM_ROR(8));
694 tcg_out_dat_reg(s, cond, ARITH_EOR,
695 rd, rd, TCG_REG_TMP, SHIFT_IMM_LSR(8));
696 }
697 }
698
699 static inline void tcg_out_deposit(TCGContext *s, int cond, TCGReg rd,
700 TCGArg a1, int ofs, int len, bool const_a1)
701 {
702 if (const_a1) {
703 /* bfi becomes bfc with rn == 15. */
704 a1 = 15;
705 }
706 /* bfi/bfc */
707 tcg_out32(s, 0x07c00010 | (cond << 28) | (rd << 12) | a1
708 | (ofs << 7) | ((ofs + len - 1) << 16));
709 }
710
711 static inline void tcg_out_extract(TCGContext *s, int cond, TCGReg rd,
712 TCGArg a1, int ofs, int len)
713 {
714 /* ubfx */
715 tcg_out32(s, 0x07e00050 | (cond << 28) | (rd << 12) | a1
716 | (ofs << 7) | ((len - 1) << 16));
717 }
718
719 static inline void tcg_out_sextract(TCGContext *s, int cond, TCGReg rd,
720 TCGArg a1, int ofs, int len)
721 {
722 /* sbfx */
723 tcg_out32(s, 0x07a00050 | (cond << 28) | (rd << 12) | a1
724 | (ofs << 7) | ((len - 1) << 16));
725 }
726
727 /* Note that this routine is used for both LDR and LDRH formats, so we do
728 not wish to include an immediate shift at this point. */
729 static void tcg_out_memop_r(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
730 TCGReg rn, TCGReg rm, bool u, bool p, bool w)
731 {
732 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24)
733 | (w << 21) | (rn << 16) | (rt << 12) | rm);
734 }
735
736 static void tcg_out_memop_8(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
737 TCGReg rn, int imm8, bool p, bool w)
738 {
739 bool u = 1;
740 if (imm8 < 0) {
741 imm8 = -imm8;
742 u = 0;
743 }
744 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
745 (rn << 16) | (rt << 12) | ((imm8 & 0xf0) << 4) | (imm8 & 0xf));
746 }
747
748 static void tcg_out_memop_12(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
749 TCGReg rn, int imm12, bool p, bool w)
750 {
751 bool u = 1;
752 if (imm12 < 0) {
753 imm12 = -imm12;
754 u = 0;
755 }
756 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
757 (rn << 16) | (rt << 12) | imm12);
758 }
759
760 static inline void tcg_out_ld32_12(TCGContext *s, int cond, TCGReg rt,
761 TCGReg rn, int imm12)
762 {
763 tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 0);
764 }
765
766 static inline void tcg_out_st32_12(TCGContext *s, int cond, TCGReg rt,
767 TCGReg rn, int imm12)
768 {
769 tcg_out_memop_12(s, cond, INSN_STR_IMM, rt, rn, imm12, 1, 0);
770 }
771
772 static inline void tcg_out_ld32_r(TCGContext *s, int cond, TCGReg rt,
773 TCGReg rn, TCGReg rm)
774 {
775 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 0);
776 }
777
778 static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt,
779 TCGReg rn, TCGReg rm)
780 {
781 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0);
782 }
783
784 static inline void tcg_out_ldrd_8(TCGContext *s, int cond, TCGReg rt,
785 TCGReg rn, int imm8)
786 {
787 tcg_out_memop_8(s, cond, INSN_LDRD_IMM, rt, rn, imm8, 1, 0);
788 }
789
790 static inline void tcg_out_ldrd_r(TCGContext *s, int cond, TCGReg rt,
791 TCGReg rn, TCGReg rm)
792 {
793 tcg_out_memop_r(s, cond, INSN_LDRD_REG, rt, rn, rm, 1, 1, 0);
794 }
795
796 static inline void tcg_out_strd_8(TCGContext *s, int cond, TCGReg rt,
797 TCGReg rn, int imm8)
798 {
799 tcg_out_memop_8(s, cond, INSN_STRD_IMM, rt, rn, imm8, 1, 0);
800 }
801
802 static inline void tcg_out_strd_r(TCGContext *s, int cond, TCGReg rt,
803 TCGReg rn, TCGReg rm)
804 {
805 tcg_out_memop_r(s, cond, INSN_STRD_REG, rt, rn, rm, 1, 1, 0);
806 }
807
808 /* Register pre-increment with base writeback. */
809 static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt,
810 TCGReg rn, TCGReg rm)
811 {
812 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 1);
813 }
814
815 static inline void tcg_out_st32_rwb(TCGContext *s, int cond, TCGReg rt,
816 TCGReg rn, TCGReg rm)
817 {
818 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 1);
819 }
820
821 static inline void tcg_out_ld16u_8(TCGContext *s, int cond, TCGReg rt,
822 TCGReg rn, int imm8)
823 {
824 tcg_out_memop_8(s, cond, INSN_LDRH_IMM, rt, rn, imm8, 1, 0);
825 }
826
827 static inline void tcg_out_st16_8(TCGContext *s, int cond, TCGReg rt,
828 TCGReg rn, int imm8)
829 {
830 tcg_out_memop_8(s, cond, INSN_STRH_IMM, rt, rn, imm8, 1, 0);
831 }
832
833 static inline void tcg_out_ld16u_r(TCGContext *s, int cond, TCGReg rt,
834 TCGReg rn, TCGReg rm)
835 {
836 tcg_out_memop_r(s, cond, INSN_LDRH_REG, rt, rn, rm, 1, 1, 0);
837 }
838
839 static inline void tcg_out_st16_r(TCGContext *s, int cond, TCGReg rt,
840 TCGReg rn, TCGReg rm)
841 {
842 tcg_out_memop_r(s, cond, INSN_STRH_REG, rt, rn, rm, 1, 1, 0);
843 }
844
845 static inline void tcg_out_ld16s_8(TCGContext *s, int cond, TCGReg rt,
846 TCGReg rn, int imm8)
847 {
848 tcg_out_memop_8(s, cond, INSN_LDRSH_IMM, rt, rn, imm8, 1, 0);
849 }
850
851 static inline void tcg_out_ld16s_r(TCGContext *s, int cond, TCGReg rt,
852 TCGReg rn, TCGReg rm)
853 {
854 tcg_out_memop_r(s, cond, INSN_LDRSH_REG, rt, rn, rm, 1, 1, 0);
855 }
856
857 static inline void tcg_out_ld8_12(TCGContext *s, int cond, TCGReg rt,
858 TCGReg rn, int imm12)
859 {
860 tcg_out_memop_12(s, cond, INSN_LDRB_IMM, rt, rn, imm12, 1, 0);
861 }
862
863 static inline void tcg_out_st8_12(TCGContext *s, int cond, TCGReg rt,
864 TCGReg rn, int imm12)
865 {
866 tcg_out_memop_12(s, cond, INSN_STRB_IMM, rt, rn, imm12, 1, 0);
867 }
868
869 static inline void tcg_out_ld8_r(TCGContext *s, int cond, TCGReg rt,
870 TCGReg rn, TCGReg rm)
871 {
872 tcg_out_memop_r(s, cond, INSN_LDRB_REG, rt, rn, rm, 1, 1, 0);
873 }
874
875 static inline void tcg_out_st8_r(TCGContext *s, int cond, TCGReg rt,
876 TCGReg rn, TCGReg rm)
877 {
878 tcg_out_memop_r(s, cond, INSN_STRB_REG, rt, rn, rm, 1, 1, 0);
879 }
880
881 static inline void tcg_out_ld8s_8(TCGContext *s, int cond, TCGReg rt,
882 TCGReg rn, int imm8)
883 {
884 tcg_out_memop_8(s, cond, INSN_LDRSB_IMM, rt, rn, imm8, 1, 0);
885 }
886
887 static inline void tcg_out_ld8s_r(TCGContext *s, int cond, TCGReg rt,
888 TCGReg rn, TCGReg rm)
889 {
890 tcg_out_memop_r(s, cond, INSN_LDRSB_REG, rt, rn, rm, 1, 1, 0);
891 }
892
893 static inline void tcg_out_ld32u(TCGContext *s, int cond,
894 int rd, int rn, int32_t offset)
895 {
896 if (offset > 0xfff || offset < -0xfff) {
897 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
898 tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_TMP);
899 } else
900 tcg_out_ld32_12(s, cond, rd, rn, offset);
901 }
902
903 static inline void tcg_out_st32(TCGContext *s, int cond,
904 int rd, int rn, int32_t offset)
905 {
906 if (offset > 0xfff || offset < -0xfff) {
907 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
908 tcg_out_st32_r(s, cond, rd, rn, TCG_REG_TMP);
909 } else
910 tcg_out_st32_12(s, cond, rd, rn, offset);
911 }
912
913 static inline void tcg_out_ld16u(TCGContext *s, int cond,
914 int rd, int rn, int32_t offset)
915 {
916 if (offset > 0xff || offset < -0xff) {
917 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
918 tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_TMP);
919 } else
920 tcg_out_ld16u_8(s, cond, rd, rn, offset);
921 }
922
923 static inline void tcg_out_ld16s(TCGContext *s, int cond,
924 int rd, int rn, int32_t offset)
925 {
926 if (offset > 0xff || offset < -0xff) {
927 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
928 tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_TMP);
929 } else
930 tcg_out_ld16s_8(s, cond, rd, rn, offset);
931 }
932
933 static inline void tcg_out_st16(TCGContext *s, int cond,
934 int rd, int rn, int32_t offset)
935 {
936 if (offset > 0xff || offset < -0xff) {
937 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
938 tcg_out_st16_r(s, cond, rd, rn, TCG_REG_TMP);
939 } else
940 tcg_out_st16_8(s, cond, rd, rn, offset);
941 }
942
943 static inline void tcg_out_ld8u(TCGContext *s, int cond,
944 int rd, int rn, int32_t offset)
945 {
946 if (offset > 0xfff || offset < -0xfff) {
947 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
948 tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_TMP);
949 } else
950 tcg_out_ld8_12(s, cond, rd, rn, offset);
951 }
952
953 static inline void tcg_out_ld8s(TCGContext *s, int cond,
954 int rd, int rn, int32_t offset)
955 {
956 if (offset > 0xff || offset < -0xff) {
957 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
958 tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_TMP);
959 } else
960 tcg_out_ld8s_8(s, cond, rd, rn, offset);
961 }
962
963 static inline void tcg_out_st8(TCGContext *s, int cond,
964 int rd, int rn, int32_t offset)
965 {
966 if (offset > 0xfff || offset < -0xfff) {
967 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
968 tcg_out_st8_r(s, cond, rd, rn, TCG_REG_TMP);
969 } else
970 tcg_out_st8_12(s, cond, rd, rn, offset);
971 }
972
973 /* The _goto case is normally between TBs within the same code buffer, and
974 * with the code buffer limited to 16MB we wouldn't need the long case.
975 * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
976 */
977 static inline void tcg_out_goto(TCGContext *s, int cond, tcg_insn_unit *addr)
978 {
979 intptr_t addri = (intptr_t)addr;
980 ptrdiff_t disp = tcg_pcrel_diff(s, addr);
981
982 if ((addri & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) {
983 tcg_out_b(s, cond, disp);
984 return;
985 }
986
987 tcg_out_movi32(s, cond, TCG_REG_TMP, addri);
988 if (use_armv5t_instructions) {
989 tcg_out_bx(s, cond, TCG_REG_TMP);
990 } else {
991 if (addri & 1) {
992 tcg_abort();
993 }
994 tcg_out_mov_reg(s, cond, TCG_REG_PC, TCG_REG_TMP);
995 }
996 }
997
998 /* The call case is mostly used for helpers - so it's not unreasonable
999 * for them to be beyond branch range */
1000 static void tcg_out_call(TCGContext *s, tcg_insn_unit *addr)
1001 {
1002 intptr_t addri = (intptr_t)addr;
1003 ptrdiff_t disp = tcg_pcrel_diff(s, addr);
1004
1005 if (disp - 8 < 0x02000000 && disp - 8 >= -0x02000000) {
1006 if (addri & 1) {
1007 /* Use BLX if the target is in Thumb mode */
1008 if (!use_armv5t_instructions) {
1009 tcg_abort();
1010 }
1011 tcg_out_blx_imm(s, disp);
1012 } else {
1013 tcg_out_bl(s, COND_AL, disp);
1014 }
1015 } else if (use_armv7_instructions) {
1016 tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
1017 tcg_out_blx(s, COND_AL, TCG_REG_TMP);
1018 } else {
1019 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
1020 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1021 tcg_out32(s, addri);
1022 }
1023 }
1024
1025 void arm_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
1026 {
1027 tcg_insn_unit *code_ptr = (tcg_insn_unit *)jmp_addr;
1028 tcg_insn_unit *target = (tcg_insn_unit *)addr;
1029
1030 /* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
1031 reloc_pc24_atomic(code_ptr, target);
1032 flush_icache_range(jmp_addr, jmp_addr + 4);
1033 }
1034
1035 static inline void tcg_out_goto_label(TCGContext *s, int cond, TCGLabel *l)
1036 {
1037 if (l->has_value) {
1038 tcg_out_goto(s, cond, l->u.value_ptr);
1039 } else {
1040 tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, l, 0);
1041 tcg_out_b_noaddr(s, cond);
1042 }
1043 }
1044
1045 static inline void tcg_out_mb(TCGContext *s, TCGArg a0)
1046 {
1047 if (use_armv7_instructions) {
1048 tcg_out32(s, INSN_DMB_ISH);
1049 } else if (use_armv6_instructions) {
1050 tcg_out32(s, INSN_DMB_MCR);
1051 }
1052 }
1053
1054 #ifdef CONFIG_SOFTMMU
1055 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1056 * int mmu_idx, uintptr_t ra)
1057 */
1058 static void * const qemu_ld_helpers[16] = {
1059 [MO_UB] = helper_ret_ldub_mmu,
1060 [MO_SB] = helper_ret_ldsb_mmu,
1061
1062 [MO_LEUW] = helper_le_lduw_mmu,
1063 [MO_LEUL] = helper_le_ldul_mmu,
1064 [MO_LEQ] = helper_le_ldq_mmu,
1065 [MO_LESW] = helper_le_ldsw_mmu,
1066 [MO_LESL] = helper_le_ldul_mmu,
1067
1068 [MO_BEUW] = helper_be_lduw_mmu,
1069 [MO_BEUL] = helper_be_ldul_mmu,
1070 [MO_BEQ] = helper_be_ldq_mmu,
1071 [MO_BESW] = helper_be_ldsw_mmu,
1072 [MO_BESL] = helper_be_ldul_mmu,
1073 };
1074
1075 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1076 * uintxx_t val, int mmu_idx, uintptr_t ra)
1077 */
1078 static void * const qemu_st_helpers[16] = {
1079 [MO_UB] = helper_ret_stb_mmu,
1080 [MO_LEUW] = helper_le_stw_mmu,
1081 [MO_LEUL] = helper_le_stl_mmu,
1082 [MO_LEQ] = helper_le_stq_mmu,
1083 [MO_BEUW] = helper_be_stw_mmu,
1084 [MO_BEUL] = helper_be_stl_mmu,
1085 [MO_BEQ] = helper_be_stq_mmu,
1086 };
1087
1088 /* Helper routines for marshalling helper function arguments into
1089 * the correct registers and stack.
1090 * argreg is where we want to put this argument, arg is the argument itself.
1091 * Return value is the updated argreg ready for the next call.
1092 * Note that argreg 0..3 is real registers, 4+ on stack.
1093 *
1094 * We provide routines for arguments which are: immediate, 32 bit
1095 * value in register, 16 and 8 bit values in register (which must be zero
1096 * extended before use) and 64 bit value in a lo:hi register pair.
1097 */
1098 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1099 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1100 { \
1101 if (argreg < 4) { \
1102 MOV_ARG(s, COND_AL, argreg, arg); \
1103 } else { \
1104 int ofs = (argreg - 4) * 4; \
1105 EXT_ARG; \
1106 tcg_debug_assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1107 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1108 } \
1109 return argreg + 1; \
1110 }
1111
1112 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
1113 (tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1114 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
1115 (tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1116 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
1117 (tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1118 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
1119
1120 static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
1121 TCGReg arglo, TCGReg arghi)
1122 {
1123 /* 64 bit arguments must go in even/odd register pairs
1124 * and in 8-aligned stack slots.
1125 */
1126 if (argreg & 1) {
1127 argreg++;
1128 }
1129 if (use_armv6_instructions && argreg >= 4
1130 && (arglo & 1) == 0 && arghi == arglo + 1) {
1131 tcg_out_strd_8(s, COND_AL, arglo,
1132 TCG_REG_CALL_STACK, (argreg - 4) * 4);
1133 return argreg + 2;
1134 } else {
1135 argreg = tcg_out_arg_reg32(s, argreg, arglo);
1136 argreg = tcg_out_arg_reg32(s, argreg, arghi);
1137 return argreg;
1138 }
1139 }
1140
1141 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1142
1143 /* We're expecting to use an 8-bit immediate and to mask. */
1144 QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
1145
1146 /* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset.
1147 Using the offset of the second entry in the last tlb table ensures
1148 that we can index all of the elements of the first entry. */
1149 QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
1150 > 0xffff);
1151
1152 /* Load and compare a TLB entry, leaving the flags set. Returns the register
1153 containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
1154
1155 static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
1156 TCGMemOp opc, int mem_index, bool is_load)
1157 {
1158 TCGReg base = TCG_AREG0;
1159 int cmp_off =
1160 (is_load
1161 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1162 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1163 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1164 unsigned s_bits = opc & MO_SIZE;
1165 unsigned a_bits = get_alignment_bits(opc);
1166
1167 /* Should generate something like the following:
1168 * shr tmp, addrlo, #TARGET_PAGE_BITS (1)
1169 * add r2, env, #high
1170 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1171 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1172 * ldr r0, [r2, #cmp] (4)
1173 * tst addrlo, #s_mask
1174 * ldr r2, [r2, #add] (5)
1175 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS
1176 */
1177 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
1178 0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1179
1180 /* We checked that the offset is contained within 16 bits above. */
1181 if (add_off > 0xfff || (use_armv6_instructions && cmp_off > 0xff)) {
1182 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1183 (24 << 7) | (cmp_off >> 8));
1184 base = TCG_REG_R2;
1185 add_off -= cmp_off & 0xff00;
1186 cmp_off &= 0xff;
1187 }
1188
1189 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1190 TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
1191 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1192 TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1193
1194 /* Load the tlb comparator. Use ldrd if needed and available,
1195 but due to how the pointer needs setting up, ldm isn't useful.
1196 Base arm5 doesn't have ldrd, but armv5te does. */
1197 if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
1198 tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1199 } else {
1200 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1201 if (TARGET_LONG_BITS == 64) {
1202 tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, cmp_off + 4);
1203 }
1204 }
1205
1206 /* Check alignment. We don't support inline unaligned acceses,
1207 but we can easily support overalignment checks. */
1208 if (a_bits < s_bits) {
1209 a_bits = s_bits;
1210 }
1211 if (a_bits) {
1212 tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo, (1 << a_bits) - 1);
1213 }
1214
1215 /* Load the tlb addend. */
1216 tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R2, add_off);
1217
1218 tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
1219 TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1220
1221 if (TARGET_LONG_BITS == 64) {
1222 tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1223 TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
1224 }
1225
1226 return TCG_REG_R2;
1227 }
1228
1229 /* Record the context of a call to the out of line helper code for the slow
1230 path for a load or store, so that we can later generate the correct
1231 helper code. */
1232 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
1233 TCGReg datalo, TCGReg datahi, TCGReg addrlo,
1234 TCGReg addrhi, tcg_insn_unit *raddr,
1235 tcg_insn_unit *label_ptr)
1236 {
1237 TCGLabelQemuLdst *label = new_ldst_label(s);
1238
1239 label->is_ld = is_ld;
1240 label->oi = oi;
1241 label->datalo_reg = datalo;
1242 label->datahi_reg = datahi;
1243 label->addrlo_reg = addrlo;
1244 label->addrhi_reg = addrhi;
1245 label->raddr = raddr;
1246 label->label_ptr[0] = label_ptr;
1247 }
1248
1249 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1250 {
1251 TCGReg argreg, datalo, datahi;
1252 TCGMemOpIdx oi = lb->oi;
1253 TCGMemOp opc = get_memop(oi);
1254 void *func;
1255
1256 reloc_pc24(lb->label_ptr[0], s->code_ptr);
1257
1258 argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
1259 if (TARGET_LONG_BITS == 64) {
1260 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1261 } else {
1262 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1263 }
1264 argreg = tcg_out_arg_imm32(s, argreg, oi);
1265 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1266
1267 /* For armv6 we can use the canonical unsigned helpers and minimize
1268 icache usage. For pre-armv6, use the signed helpers since we do
1269 not have a single insn sign-extend. */
1270 if (use_armv6_instructions) {
1271 func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)];
1272 } else {
1273 func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)];
1274 if (opc & MO_SIGN) {
1275 opc = MO_UL;
1276 }
1277 }
1278 tcg_out_call(s, func);
1279
1280 datalo = lb->datalo_reg;
1281 datahi = lb->datahi_reg;
1282 switch (opc & MO_SSIZE) {
1283 case MO_SB:
1284 tcg_out_ext8s(s, COND_AL, datalo, TCG_REG_R0);
1285 break;
1286 case MO_SW:
1287 tcg_out_ext16s(s, COND_AL, datalo, TCG_REG_R0);
1288 break;
1289 default:
1290 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1291 break;
1292 case MO_Q:
1293 if (datalo != TCG_REG_R1) {
1294 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1295 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1296 } else if (datahi != TCG_REG_R0) {
1297 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1298 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1299 } else {
1300 tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0);
1301 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1302 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_TMP);
1303 }
1304 break;
1305 }
1306
1307 tcg_out_goto(s, COND_AL, lb->raddr);
1308 }
1309
1310 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1311 {
1312 TCGReg argreg, datalo, datahi;
1313 TCGMemOpIdx oi = lb->oi;
1314 TCGMemOp opc = get_memop(oi);
1315
1316 reloc_pc24(lb->label_ptr[0], s->code_ptr);
1317
1318 argreg = TCG_REG_R0;
1319 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
1320 if (TARGET_LONG_BITS == 64) {
1321 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1322 } else {
1323 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1324 }
1325
1326 datalo = lb->datalo_reg;
1327 datahi = lb->datahi_reg;
1328 switch (opc & MO_SIZE) {
1329 case MO_8:
1330 argreg = tcg_out_arg_reg8(s, argreg, datalo);
1331 break;
1332 case MO_16:
1333 argreg = tcg_out_arg_reg16(s, argreg, datalo);
1334 break;
1335 case MO_32:
1336 default:
1337 argreg = tcg_out_arg_reg32(s, argreg, datalo);
1338 break;
1339 case MO_64:
1340 argreg = tcg_out_arg_reg64(s, argreg, datalo, datahi);
1341 break;
1342 }
1343
1344 argreg = tcg_out_arg_imm32(s, argreg, oi);
1345 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1346
1347 /* Tail-call to the helper, which will return to the fast path. */
1348 tcg_out_goto(s, COND_AL, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1349 }
1350 #endif /* SOFTMMU */
1351
1352 static inline void tcg_out_qemu_ld_index(TCGContext *s, TCGMemOp opc,
1353 TCGReg datalo, TCGReg datahi,
1354 TCGReg addrlo, TCGReg addend)
1355 {
1356 TCGMemOp bswap = opc & MO_BSWAP;
1357
1358 switch (opc & MO_SSIZE) {
1359 case MO_UB:
1360 tcg_out_ld8_r(s, COND_AL, datalo, addrlo, addend);
1361 break;
1362 case MO_SB:
1363 tcg_out_ld8s_r(s, COND_AL, datalo, addrlo, addend);
1364 break;
1365 case MO_UW:
1366 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1367 if (bswap) {
1368 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1369 }
1370 break;
1371 case MO_SW:
1372 if (bswap) {
1373 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1374 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1375 } else {
1376 tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
1377 }
1378 break;
1379 case MO_UL:
1380 default:
1381 tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
1382 if (bswap) {
1383 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1384 }
1385 break;
1386 case MO_Q:
1387 {
1388 TCGReg dl = (bswap ? datahi : datalo);
1389 TCGReg dh = (bswap ? datalo : datahi);
1390
1391 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1392 if (USING_SOFTMMU && use_armv6_instructions
1393 && (dl & 1) == 0 && dh == dl + 1) {
1394 tcg_out_ldrd_r(s, COND_AL, dl, addrlo, addend);
1395 } else if (dl != addend) {
1396 tcg_out_ld32_rwb(s, COND_AL, dl, addend, addrlo);
1397 tcg_out_ld32_12(s, COND_AL, dh, addend, 4);
1398 } else {
1399 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
1400 addend, addrlo, SHIFT_IMM_LSL(0));
1401 tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0);
1402 tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
1403 }
1404 if (bswap) {
1405 tcg_out_bswap32(s, COND_AL, dl, dl);
1406 tcg_out_bswap32(s, COND_AL, dh, dh);
1407 }
1408 }
1409 break;
1410 }
1411 }
1412
1413 static inline void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp opc,
1414 TCGReg datalo, TCGReg datahi,
1415 TCGReg addrlo)
1416 {
1417 TCGMemOp bswap = opc & MO_BSWAP;
1418
1419 switch (opc & MO_SSIZE) {
1420 case MO_UB:
1421 tcg_out_ld8_12(s, COND_AL, datalo, addrlo, 0);
1422 break;
1423 case MO_SB:
1424 tcg_out_ld8s_8(s, COND_AL, datalo, addrlo, 0);
1425 break;
1426 case MO_UW:
1427 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1428 if (bswap) {
1429 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1430 }
1431 break;
1432 case MO_SW:
1433 if (bswap) {
1434 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1435 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1436 } else {
1437 tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
1438 }
1439 break;
1440 case MO_UL:
1441 default:
1442 tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
1443 if (bswap) {
1444 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1445 }
1446 break;
1447 case MO_Q:
1448 {
1449 TCGReg dl = (bswap ? datahi : datalo);
1450 TCGReg dh = (bswap ? datalo : datahi);
1451
1452 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1453 if (USING_SOFTMMU && use_armv6_instructions
1454 && (dl & 1) == 0 && dh == dl + 1) {
1455 tcg_out_ldrd_8(s, COND_AL, dl, addrlo, 0);
1456 } else if (dl == addrlo) {
1457 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1458 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1459 } else {
1460 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1461 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1462 }
1463 if (bswap) {
1464 tcg_out_bswap32(s, COND_AL, dl, dl);
1465 tcg_out_bswap32(s, COND_AL, dh, dh);
1466 }
1467 }
1468 break;
1469 }
1470 }
1471
1472 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
1473 {
1474 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1475 TCGMemOpIdx oi;
1476 TCGMemOp opc;
1477 #ifdef CONFIG_SOFTMMU
1478 int mem_index;
1479 TCGReg addend;
1480 tcg_insn_unit *label_ptr;
1481 #endif
1482
1483 datalo = *args++;
1484 datahi = (is64 ? *args++ : 0);
1485 addrlo = *args++;
1486 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1487 oi = *args++;
1488 opc = get_memop(oi);
1489
1490 #ifdef CONFIG_SOFTMMU
1491 mem_index = get_mmuidx(oi);
1492 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 1);
1493
1494 /* This a conditional BL only to load a pointer within this opcode into LR
1495 for the slow path. We will not be using the value for a tail call. */
1496 label_ptr = s->code_ptr;
1497 tcg_out_bl_noaddr(s, COND_NE);
1498
1499 tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
1500
1501 add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
1502 s->code_ptr, label_ptr);
1503 #else /* !CONFIG_SOFTMMU */
1504 if (guest_base) {
1505 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
1506 tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, TCG_REG_TMP);
1507 } else {
1508 tcg_out_qemu_ld_direct(s, opc, datalo, datahi, addrlo);
1509 }
1510 #endif
1511 }
1512
1513 static inline void tcg_out_qemu_st_index(TCGContext *s, int cond, TCGMemOp opc,
1514 TCGReg datalo, TCGReg datahi,
1515 TCGReg addrlo, TCGReg addend)
1516 {
1517 TCGMemOp bswap = opc & MO_BSWAP;
1518
1519 switch (opc & MO_SIZE) {
1520 case MO_8:
1521 tcg_out_st8_r(s, cond, datalo, addrlo, addend);
1522 break;
1523 case MO_16:
1524 if (bswap) {
1525 tcg_out_bswap16st(s, cond, TCG_REG_R0, datalo);
1526 tcg_out_st16_r(s, cond, TCG_REG_R0, addrlo, addend);
1527 } else {
1528 tcg_out_st16_r(s, cond, datalo, addrlo, addend);
1529 }
1530 break;
1531 case MO_32:
1532 default:
1533 if (bswap) {
1534 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1535 tcg_out_st32_r(s, cond, TCG_REG_R0, addrlo, addend);
1536 } else {
1537 tcg_out_st32_r(s, cond, datalo, addrlo, addend);
1538 }
1539 break;
1540 case MO_64:
1541 /* Avoid strd for user-only emulation, to handle unaligned. */
1542 if (bswap) {
1543 tcg_out_bswap32(s, cond, TCG_REG_R0, datahi);
1544 tcg_out_st32_rwb(s, cond, TCG_REG_R0, addend, addrlo);
1545 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1546 tcg_out_st32_12(s, cond, TCG_REG_R0, addend, 4);
1547 } else if (USING_SOFTMMU && use_armv6_instructions
1548 && (datalo & 1) == 0 && datahi == datalo + 1) {
1549 tcg_out_strd_r(s, cond, datalo, addrlo, addend);
1550 } else {
1551 tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
1552 tcg_out_st32_12(s, cond, datahi, addend, 4);
1553 }
1554 break;
1555 }
1556 }
1557
1558 static inline void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp opc,
1559 TCGReg datalo, TCGReg datahi,
1560 TCGReg addrlo)
1561 {
1562 TCGMemOp bswap = opc & MO_BSWAP;
1563
1564 switch (opc & MO_SIZE) {
1565 case MO_8:
1566 tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0);
1567 break;
1568 case MO_16:
1569 if (bswap) {
1570 tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, datalo);
1571 tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
1572 } else {
1573 tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
1574 }
1575 break;
1576 case MO_32:
1577 default:
1578 if (bswap) {
1579 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1580 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1581 } else {
1582 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1583 }
1584 break;
1585 case MO_64:
1586 /* Avoid strd for user-only emulation, to handle unaligned. */
1587 if (bswap) {
1588 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datahi);
1589 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1590 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1591 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 4);
1592 } else if (USING_SOFTMMU && use_armv6_instructions
1593 && (datalo & 1) == 0 && datahi == datalo + 1) {
1594 tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
1595 } else {
1596 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1597 tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4);
1598 }
1599 break;
1600 }
1601 }
1602
1603 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
1604 {
1605 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1606 TCGMemOpIdx oi;
1607 TCGMemOp opc;
1608 #ifdef CONFIG_SOFTMMU
1609 int mem_index;
1610 TCGReg addend;
1611 tcg_insn_unit *label_ptr;
1612 #endif
1613
1614 datalo = *args++;
1615 datahi = (is64 ? *args++ : 0);
1616 addrlo = *args++;
1617 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1618 oi = *args++;
1619 opc = get_memop(oi);
1620
1621 #ifdef CONFIG_SOFTMMU
1622 mem_index = get_mmuidx(oi);
1623 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 0);
1624
1625 tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, addrlo, addend);
1626
1627 /* The conditional call must come last, as we're going to return here. */
1628 label_ptr = s->code_ptr;
1629 tcg_out_bl_noaddr(s, COND_NE);
1630
1631 add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi,
1632 s->code_ptr, label_ptr);
1633 #else /* !CONFIG_SOFTMMU */
1634 if (guest_base) {
1635 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
1636 tcg_out_qemu_st_index(s, COND_AL, opc, datalo,
1637 datahi, addrlo, TCG_REG_TMP);
1638 } else {
1639 tcg_out_qemu_st_direct(s, opc, datalo, datahi, addrlo);
1640 }
1641 #endif
1642 }
1643
1644 static tcg_insn_unit *tb_ret_addr;
1645
1646 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1647 const TCGArg *args, const int *const_args)
1648 {
1649 TCGArg a0, a1, a2, a3, a4, a5;
1650 int c;
1651
1652 switch (opc) {
1653 case INDEX_op_exit_tb:
1654 tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]);
1655 tcg_out_goto(s, COND_AL, tb_ret_addr);
1656 break;
1657 case INDEX_op_goto_tb:
1658 if (s->tb_jmp_insn_offset) {
1659 /* Direct jump method */
1660 s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
1661 tcg_out_b_noaddr(s, COND_AL);
1662 } else {
1663 /* Indirect jump method */
1664 intptr_t ptr = (intptr_t)(s->tb_jmp_target_addr + args[0]);
1665 tcg_out_movi32(s, COND_AL, TCG_REG_R0, ptr & ~0xfff);
1666 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, ptr & 0xfff);
1667 }
1668 s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s);
1669 break;
1670 case INDEX_op_br:
1671 tcg_out_goto_label(s, COND_AL, arg_label(args[0]));
1672 break;
1673
1674 case INDEX_op_ld8u_i32:
1675 tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1676 break;
1677 case INDEX_op_ld8s_i32:
1678 tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1679 break;
1680 case INDEX_op_ld16u_i32:
1681 tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1682 break;
1683 case INDEX_op_ld16s_i32:
1684 tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1685 break;
1686 case INDEX_op_ld_i32:
1687 tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1688 break;
1689 case INDEX_op_st8_i32:
1690 tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1691 break;
1692 case INDEX_op_st16_i32:
1693 tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1694 break;
1695 case INDEX_op_st_i32:
1696 tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1697 break;
1698
1699 case INDEX_op_movcond_i32:
1700 /* Constraints mean that v2 is always in the same register as dest,
1701 * so we only need to do "if condition passed, move v1 to dest".
1702 */
1703 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1704 args[1], args[2], const_args[2]);
1705 tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
1706 ARITH_MVN, args[0], 0, args[3], const_args[3]);
1707 break;
1708 case INDEX_op_add_i32:
1709 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
1710 args[0], args[1], args[2], const_args[2]);
1711 break;
1712 case INDEX_op_sub_i32:
1713 if (const_args[1]) {
1714 if (const_args[2]) {
1715 tcg_out_movi32(s, COND_AL, args[0], args[1] - args[2]);
1716 } else {
1717 tcg_out_dat_rI(s, COND_AL, ARITH_RSB,
1718 args[0], args[2], args[1], 1);
1719 }
1720 } else {
1721 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
1722 args[0], args[1], args[2], const_args[2]);
1723 }
1724 break;
1725 case INDEX_op_and_i32:
1726 tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
1727 args[0], args[1], args[2], const_args[2]);
1728 break;
1729 case INDEX_op_andc_i32:
1730 tcg_out_dat_rIK(s, COND_AL, ARITH_BIC, ARITH_AND,
1731 args[0], args[1], args[2], const_args[2]);
1732 break;
1733 case INDEX_op_or_i32:
1734 c = ARITH_ORR;
1735 goto gen_arith;
1736 case INDEX_op_xor_i32:
1737 c = ARITH_EOR;
1738 /* Fall through. */
1739 gen_arith:
1740 tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]);
1741 break;
1742 case INDEX_op_add2_i32:
1743 a0 = args[0], a1 = args[1], a2 = args[2];
1744 a3 = args[3], a4 = args[4], a5 = args[5];
1745 if (a0 == a3 || (a0 == a5 && !const_args[5])) {
1746 a0 = TCG_REG_TMP;
1747 }
1748 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
1749 a0, a2, a4, const_args[4]);
1750 tcg_out_dat_rIK(s, COND_AL, ARITH_ADC, ARITH_SBC,
1751 a1, a3, a5, const_args[5]);
1752 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1753 break;
1754 case INDEX_op_sub2_i32:
1755 a0 = args[0], a1 = args[1], a2 = args[2];
1756 a3 = args[3], a4 = args[4], a5 = args[5];
1757 if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
1758 a0 = TCG_REG_TMP;
1759 }
1760 if (const_args[2]) {
1761 if (const_args[4]) {
1762 tcg_out_movi32(s, COND_AL, a0, a4);
1763 a4 = a0;
1764 }
1765 tcg_out_dat_rI(s, COND_AL, ARITH_RSB | TO_CPSR, a0, a4, a2, 1);
1766 } else {
1767 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB | TO_CPSR,
1768 ARITH_ADD | TO_CPSR, a0, a2, a4, const_args[4]);
1769 }
1770 if (const_args[3]) {
1771 if (const_args[5]) {
1772 tcg_out_movi32(s, COND_AL, a1, a5);
1773 a5 = a1;
1774 }
1775 tcg_out_dat_rI(s, COND_AL, ARITH_RSC, a1, a5, a3, 1);
1776 } else {
1777 tcg_out_dat_rIK(s, COND_AL, ARITH_SBC, ARITH_ADC,
1778 a1, a3, a5, const_args[5]);
1779 }
1780 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1781 break;
1782 case INDEX_op_neg_i32:
1783 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1784 break;
1785 case INDEX_op_not_i32:
1786 tcg_out_dat_reg(s, COND_AL,
1787 ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1788 break;
1789 case INDEX_op_mul_i32:
1790 tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1791 break;
1792 case INDEX_op_mulu2_i32:
1793 tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1794 break;
1795 case INDEX_op_muls2_i32:
1796 tcg_out_smull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1797 break;
1798 /* XXX: Perhaps args[2] & 0x1f is wrong */
1799 case INDEX_op_shl_i32:
1800 c = const_args[2] ?
1801 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1802 goto gen_shift32;
1803 case INDEX_op_shr_i32:
1804 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1805 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1806 goto gen_shift32;
1807 case INDEX_op_sar_i32:
1808 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1809 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1810 goto gen_shift32;
1811 case INDEX_op_rotr_i32:
1812 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1813 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1814 /* Fall through. */
1815 gen_shift32:
1816 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1817 break;
1818
1819 case INDEX_op_rotl_i32:
1820 if (const_args[2]) {
1821 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1822 ((0x20 - args[2]) & 0x1f) ?
1823 SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1824 SHIFT_IMM_LSL(0));
1825 } else {
1826 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[2], 0x20);
1827 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1828 SHIFT_REG_ROR(TCG_REG_TMP));
1829 }
1830 break;
1831
1832 case INDEX_op_brcond_i32:
1833 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1834 args[0], args[1], const_args[1]);
1835 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]],
1836 arg_label(args[3]));
1837 break;
1838 case INDEX_op_brcond2_i32:
1839 /* The resulting conditions are:
1840 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1841 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1842 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1843 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1844 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1845 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1846 */
1847 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1848 args[1], args[3], const_args[3]);
1849 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1850 args[0], args[2], const_args[2]);
1851 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]],
1852 arg_label(args[5]));
1853 break;
1854 case INDEX_op_setcond_i32:
1855 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1856 args[1], args[2], const_args[2]);
1857 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1858 ARITH_MOV, args[0], 0, 1);
1859 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1860 ARITH_MOV, args[0], 0, 0);
1861 break;
1862 case INDEX_op_setcond2_i32:
1863 /* See brcond2_i32 comment */
1864 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1865 args[2], args[4], const_args[4]);
1866 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1867 args[1], args[3], const_args[3]);
1868 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1869 ARITH_MOV, args[0], 0, 1);
1870 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1871 ARITH_MOV, args[0], 0, 0);
1872 break;
1873
1874 case INDEX_op_qemu_ld_i32:
1875 tcg_out_qemu_ld(s, args, 0);
1876 break;
1877 case INDEX_op_qemu_ld_i64:
1878 tcg_out_qemu_ld(s, args, 1);
1879 break;
1880 case INDEX_op_qemu_st_i32:
1881 tcg_out_qemu_st(s, args, 0);
1882 break;
1883 case INDEX_op_qemu_st_i64:
1884 tcg_out_qemu_st(s, args, 1);
1885 break;
1886
1887 case INDEX_op_bswap16_i32:
1888 tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1889 break;
1890 case INDEX_op_bswap32_i32:
1891 tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1892 break;
1893
1894 case INDEX_op_ext8s_i32:
1895 tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1896 break;
1897 case INDEX_op_ext16s_i32:
1898 tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1899 break;
1900 case INDEX_op_ext16u_i32:
1901 tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1902 break;
1903
1904 case INDEX_op_deposit_i32:
1905 tcg_out_deposit(s, COND_AL, args[0], args[2],
1906 args[3], args[4], const_args[2]);
1907 break;
1908 case INDEX_op_extract_i32:
1909 tcg_out_extract(s, COND_AL, args[0], args[1], args[2], args[3]);
1910 break;
1911 case INDEX_op_sextract_i32:
1912 tcg_out_sextract(s, COND_AL, args[0], args[1], args[2], args[3]);
1913 break;
1914
1915 case INDEX_op_div_i32:
1916 tcg_out_sdiv(s, COND_AL, args[0], args[1], args[2]);
1917 break;
1918 case INDEX_op_divu_i32:
1919 tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
1920 break;
1921
1922 case INDEX_op_mb:
1923 tcg_out_mb(s, args[0]);
1924 break;
1925
1926 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1927 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1928 case INDEX_op_call: /* Always emitted via tcg_out_call. */
1929 default:
1930 tcg_abort();
1931 }
1932 }
1933
1934 static const TCGTargetOpDef arm_op_defs[] = {
1935 { INDEX_op_exit_tb, { } },
1936 { INDEX_op_goto_tb, { } },
1937 { INDEX_op_br, { } },
1938
1939 { INDEX_op_ld8u_i32, { "r", "r" } },
1940 { INDEX_op_ld8s_i32, { "r", "r" } },
1941 { INDEX_op_ld16u_i32, { "r", "r" } },
1942 { INDEX_op_ld16s_i32, { "r", "r" } },
1943 { INDEX_op_ld_i32, { "r", "r" } },
1944 { INDEX_op_st8_i32, { "r", "r" } },
1945 { INDEX_op_st16_i32, { "r", "r" } },
1946 { INDEX_op_st_i32, { "r", "r" } },
1947
1948 /* TODO: "r", "r", "ri" */
1949 { INDEX_op_add_i32, { "r", "r", "rIN" } },
1950 { INDEX_op_sub_i32, { "r", "rI", "rIN" } },
1951 { INDEX_op_mul_i32, { "r", "r", "r" } },
1952 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1953 { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
1954 { INDEX_op_and_i32, { "r", "r", "rIK" } },
1955 { INDEX_op_andc_i32, { "r", "r", "rIK" } },
1956 { INDEX_op_or_i32, { "r", "r", "rI" } },
1957 { INDEX_op_xor_i32, { "r", "r", "rI" } },
1958 { INDEX_op_neg_i32, { "r", "r" } },
1959 { INDEX_op_not_i32, { "r", "r" } },
1960
1961 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1962 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1963 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1964 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1965 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1966
1967 { INDEX_op_brcond_i32, { "r", "rIN" } },
1968 { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
1969 { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
1970
1971 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
1972 { INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1973 { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
1974 { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
1975
1976 #if TARGET_LONG_BITS == 32
1977 { INDEX_op_qemu_ld_i32, { "r", "l" } },
1978 { INDEX_op_qemu_ld_i64, { "r", "r", "l" } },
1979 { INDEX_op_qemu_st_i32, { "s", "s" } },
1980 { INDEX_op_qemu_st_i64, { "s", "s", "s" } },
1981 #else
1982 { INDEX_op_qemu_ld_i32, { "r", "l", "l" } },
1983 { INDEX_op_qemu_ld_i64, { "r", "r", "l", "l" } },
1984 { INDEX_op_qemu_st_i32, { "s", "s", "s" } },
1985 { INDEX_op_qemu_st_i64, { "s", "s", "s", "s" } },
1986 #endif
1987
1988 { INDEX_op_bswap16_i32, { "r", "r" } },
1989 { INDEX_op_bswap32_i32, { "r", "r" } },
1990
1991 { INDEX_op_ext8s_i32, { "r", "r" } },
1992 { INDEX_op_ext16s_i32, { "r", "r" } },
1993 { INDEX_op_ext16u_i32, { "r", "r" } },
1994
1995 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1996 { INDEX_op_extract_i32, { "r", "r" } },
1997 { INDEX_op_sextract_i32, { "r", "r" } },
1998
1999 { INDEX_op_div_i32, { "r", "r", "r" } },
2000 { INDEX_op_divu_i32, { "r", "r", "r" } },
2001
2002 { INDEX_op_mb, { } },
2003 { -1 },
2004 };
2005
2006 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
2007 {
2008 int i, n = ARRAY_SIZE(arm_op_defs);
2009
2010 for (i = 0; i < n; ++i) {
2011 if (arm_op_defs[i].op == op) {
2012 return &arm_op_defs[i];
2013 }
2014 }
2015 return NULL;
2016 }
2017
2018 static void tcg_target_init(TCGContext *s)
2019 {
2020 /* Only probe for the platform and capabilities if we havn't already
2021 determined maximum values at compile time. */
2022 #ifndef use_idiv_instructions
2023 {
2024 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
2025 use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
2026 }
2027 #endif
2028 if (__ARM_ARCH < 7) {
2029 const char *pl = (const char *)qemu_getauxval(AT_PLATFORM);
2030 if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
2031 arm_arch = pl[1] - '0';
2032 }
2033 }
2034
2035 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
2036 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
2037 (1 << TCG_REG_R0) |
2038 (1 << TCG_REG_R1) |
2039 (1 << TCG_REG_R2) |
2040 (1 << TCG_REG_R3) |
2041 (1 << TCG_REG_R12) |
2042 (1 << TCG_REG_R14));
2043
2044 tcg_regset_clear(s->reserved_regs);
2045 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
2046 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
2047 tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
2048 }
2049
2050 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
2051 TCGReg arg1, intptr_t arg2)
2052 {
2053 tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
2054 }
2055
2056 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
2057 TCGReg arg1, intptr_t arg2)
2058 {
2059 tcg_out_st32(s, COND_AL, arg, arg1, arg2);
2060 }
2061
2062 static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
2063 TCGReg base, intptr_t ofs)
2064 {
2065 return false;
2066 }
2067
2068 static inline void tcg_out_mov(TCGContext *s, TCGType type,
2069 TCGReg ret, TCGReg arg)
2070 {
2071 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
2072 }
2073
2074 static inline void tcg_out_movi(TCGContext *s, TCGType type,
2075 TCGReg ret, tcg_target_long arg)
2076 {
2077 tcg_out_movi32(s, COND_AL, ret, arg);
2078 }
2079
2080 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2081 and tcg_register_jit. */
2082
2083 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2084
2085 #define FRAME_SIZE \
2086 ((PUSH_SIZE \
2087 + TCG_STATIC_CALL_ARGS_SIZE \
2088 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2089 + TCG_TARGET_STACK_ALIGN - 1) \
2090 & -TCG_TARGET_STACK_ALIGN)
2091
2092 static void tcg_target_qemu_prologue(TCGContext *s)
2093 {
2094 int stack_addend;
2095
2096 /* Calling convention requires us to save r4-r11 and lr. */
2097 /* stmdb sp!, { r4 - r11, lr } */
2098 tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
2099
2100 /* Reserve callee argument and tcg temp space. */
2101 stack_addend = FRAME_SIZE - PUSH_SIZE;
2102
2103 tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
2104 TCG_REG_CALL_STACK, stack_addend, 1);
2105 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
2106 CPU_TEMP_BUF_NLONGS * sizeof(long));
2107
2108 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2109
2110 tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
2111 tb_ret_addr = s->code_ptr;
2112
2113 /* Epilogue. We branch here via tb_ret_addr. */
2114 tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
2115 TCG_REG_CALL_STACK, stack_addend, 1);
2116
2117 /* ldmia sp!, { r4 - r11, pc } */
2118 tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
2119 }
2120
2121 typedef struct {
2122 DebugFrameHeader h;
2123 uint8_t fde_def_cfa[4];
2124 uint8_t fde_reg_ofs[18];
2125 } DebugFrame;
2126
2127 #define ELF_HOST_MACHINE EM_ARM
2128
2129 /* We're expecting a 2 byte uleb128 encoded value. */
2130 QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
2131
2132 static const DebugFrame debug_frame = {
2133 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
2134 .h.cie.id = -1,
2135 .h.cie.version = 1,
2136 .h.cie.code_align = 1,
2137 .h.cie.data_align = 0x7c, /* sleb128 -4 */
2138 .h.cie.return_column = 14,
2139
2140 /* Total FDE size does not include the "len" member. */
2141 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2142
2143 .fde_def_cfa = {
2144 12, 13, /* DW_CFA_def_cfa sp, ... */
2145 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2146 (FRAME_SIZE >> 7)
2147 },
2148 .fde_reg_ofs = {
2149 /* The following must match the stmdb in the prologue. */
2150 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2151 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2152 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2153 0x89, 4, /* DW_CFA_offset, r9, -16 */
2154 0x88, 5, /* DW_CFA_offset, r8, -20 */
2155 0x87, 6, /* DW_CFA_offset, r7, -24 */
2156 0x86, 7, /* DW_CFA_offset, r6, -28 */
2157 0x85, 8, /* DW_CFA_offset, r5, -32 */
2158 0x84, 9, /* DW_CFA_offset, r4, -36 */
2159 }
2160 };
2161
2162 void tcg_register_jit(void *buf, size_t buf_size)
2163 {
2164 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2165 }