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