]> git.proxmox.com Git - mirror_qemu.git/blob - tcg/arm/tcg-target.inc.c
1415c271723cf9d3eba83fb777fe102aec1b7a24
[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 /* Note that this routine is used for both LDR and LDRH formats, so we do
717 not wish to include an immediate shift at this point. */
718 static void tcg_out_memop_r(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
719 TCGReg rn, TCGReg rm, bool u, bool p, bool w)
720 {
721 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24)
722 | (w << 21) | (rn << 16) | (rt << 12) | rm);
723 }
724
725 static void tcg_out_memop_8(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
726 TCGReg rn, int imm8, bool p, bool w)
727 {
728 bool u = 1;
729 if (imm8 < 0) {
730 imm8 = -imm8;
731 u = 0;
732 }
733 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
734 (rn << 16) | (rt << 12) | ((imm8 & 0xf0) << 4) | (imm8 & 0xf));
735 }
736
737 static void tcg_out_memop_12(TCGContext *s, int cond, ARMInsn opc, TCGReg rt,
738 TCGReg rn, int imm12, bool p, bool w)
739 {
740 bool u = 1;
741 if (imm12 < 0) {
742 imm12 = -imm12;
743 u = 0;
744 }
745 tcg_out32(s, (cond << 28) | opc | (u << 23) | (p << 24) | (w << 21) |
746 (rn << 16) | (rt << 12) | imm12);
747 }
748
749 static inline void tcg_out_ld32_12(TCGContext *s, int cond, TCGReg rt,
750 TCGReg rn, int imm12)
751 {
752 tcg_out_memop_12(s, cond, INSN_LDR_IMM, rt, rn, imm12, 1, 0);
753 }
754
755 static inline void tcg_out_st32_12(TCGContext *s, int cond, TCGReg rt,
756 TCGReg rn, int imm12)
757 {
758 tcg_out_memop_12(s, cond, INSN_STR_IMM, rt, rn, imm12, 1, 0);
759 }
760
761 static inline void tcg_out_ld32_r(TCGContext *s, int cond, TCGReg rt,
762 TCGReg rn, TCGReg rm)
763 {
764 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 0);
765 }
766
767 static inline void tcg_out_st32_r(TCGContext *s, int cond, TCGReg rt,
768 TCGReg rn, TCGReg rm)
769 {
770 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 0);
771 }
772
773 static inline void tcg_out_ldrd_8(TCGContext *s, int cond, TCGReg rt,
774 TCGReg rn, int imm8)
775 {
776 tcg_out_memop_8(s, cond, INSN_LDRD_IMM, rt, rn, imm8, 1, 0);
777 }
778
779 static inline void tcg_out_ldrd_r(TCGContext *s, int cond, TCGReg rt,
780 TCGReg rn, TCGReg rm)
781 {
782 tcg_out_memop_r(s, cond, INSN_LDRD_REG, rt, rn, rm, 1, 1, 0);
783 }
784
785 static inline void tcg_out_strd_8(TCGContext *s, int cond, TCGReg rt,
786 TCGReg rn, int imm8)
787 {
788 tcg_out_memop_8(s, cond, INSN_STRD_IMM, rt, rn, imm8, 1, 0);
789 }
790
791 static inline void tcg_out_strd_r(TCGContext *s, int cond, TCGReg rt,
792 TCGReg rn, TCGReg rm)
793 {
794 tcg_out_memop_r(s, cond, INSN_STRD_REG, rt, rn, rm, 1, 1, 0);
795 }
796
797 /* Register pre-increment with base writeback. */
798 static inline void tcg_out_ld32_rwb(TCGContext *s, int cond, TCGReg rt,
799 TCGReg rn, TCGReg rm)
800 {
801 tcg_out_memop_r(s, cond, INSN_LDR_REG, rt, rn, rm, 1, 1, 1);
802 }
803
804 static inline void tcg_out_st32_rwb(TCGContext *s, int cond, TCGReg rt,
805 TCGReg rn, TCGReg rm)
806 {
807 tcg_out_memop_r(s, cond, INSN_STR_REG, rt, rn, rm, 1, 1, 1);
808 }
809
810 static inline void tcg_out_ld16u_8(TCGContext *s, int cond, TCGReg rt,
811 TCGReg rn, int imm8)
812 {
813 tcg_out_memop_8(s, cond, INSN_LDRH_IMM, rt, rn, imm8, 1, 0);
814 }
815
816 static inline void tcg_out_st16_8(TCGContext *s, int cond, TCGReg rt,
817 TCGReg rn, int imm8)
818 {
819 tcg_out_memop_8(s, cond, INSN_STRH_IMM, rt, rn, imm8, 1, 0);
820 }
821
822 static inline void tcg_out_ld16u_r(TCGContext *s, int cond, TCGReg rt,
823 TCGReg rn, TCGReg rm)
824 {
825 tcg_out_memop_r(s, cond, INSN_LDRH_REG, rt, rn, rm, 1, 1, 0);
826 }
827
828 static inline void tcg_out_st16_r(TCGContext *s, int cond, TCGReg rt,
829 TCGReg rn, TCGReg rm)
830 {
831 tcg_out_memop_r(s, cond, INSN_STRH_REG, rt, rn, rm, 1, 1, 0);
832 }
833
834 static inline void tcg_out_ld16s_8(TCGContext *s, int cond, TCGReg rt,
835 TCGReg rn, int imm8)
836 {
837 tcg_out_memop_8(s, cond, INSN_LDRSH_IMM, rt, rn, imm8, 1, 0);
838 }
839
840 static inline void tcg_out_ld16s_r(TCGContext *s, int cond, TCGReg rt,
841 TCGReg rn, TCGReg rm)
842 {
843 tcg_out_memop_r(s, cond, INSN_LDRSH_REG, rt, rn, rm, 1, 1, 0);
844 }
845
846 static inline void tcg_out_ld8_12(TCGContext *s, int cond, TCGReg rt,
847 TCGReg rn, int imm12)
848 {
849 tcg_out_memop_12(s, cond, INSN_LDRB_IMM, rt, rn, imm12, 1, 0);
850 }
851
852 static inline void tcg_out_st8_12(TCGContext *s, int cond, TCGReg rt,
853 TCGReg rn, int imm12)
854 {
855 tcg_out_memop_12(s, cond, INSN_STRB_IMM, rt, rn, imm12, 1, 0);
856 }
857
858 static inline void tcg_out_ld8_r(TCGContext *s, int cond, TCGReg rt,
859 TCGReg rn, TCGReg rm)
860 {
861 tcg_out_memop_r(s, cond, INSN_LDRB_REG, rt, rn, rm, 1, 1, 0);
862 }
863
864 static inline void tcg_out_st8_r(TCGContext *s, int cond, TCGReg rt,
865 TCGReg rn, TCGReg rm)
866 {
867 tcg_out_memop_r(s, cond, INSN_STRB_REG, rt, rn, rm, 1, 1, 0);
868 }
869
870 static inline void tcg_out_ld8s_8(TCGContext *s, int cond, TCGReg rt,
871 TCGReg rn, int imm8)
872 {
873 tcg_out_memop_8(s, cond, INSN_LDRSB_IMM, rt, rn, imm8, 1, 0);
874 }
875
876 static inline void tcg_out_ld8s_r(TCGContext *s, int cond, TCGReg rt,
877 TCGReg rn, TCGReg rm)
878 {
879 tcg_out_memop_r(s, cond, INSN_LDRSB_REG, rt, rn, rm, 1, 1, 0);
880 }
881
882 static inline void tcg_out_ld32u(TCGContext *s, int cond,
883 int rd, int rn, int32_t offset)
884 {
885 if (offset > 0xfff || offset < -0xfff) {
886 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
887 tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_TMP);
888 } else
889 tcg_out_ld32_12(s, cond, rd, rn, offset);
890 }
891
892 static inline void tcg_out_st32(TCGContext *s, int cond,
893 int rd, int rn, int32_t offset)
894 {
895 if (offset > 0xfff || offset < -0xfff) {
896 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
897 tcg_out_st32_r(s, cond, rd, rn, TCG_REG_TMP);
898 } else
899 tcg_out_st32_12(s, cond, rd, rn, offset);
900 }
901
902 static inline void tcg_out_ld16u(TCGContext *s, int cond,
903 int rd, int rn, int32_t offset)
904 {
905 if (offset > 0xff || offset < -0xff) {
906 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
907 tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_TMP);
908 } else
909 tcg_out_ld16u_8(s, cond, rd, rn, offset);
910 }
911
912 static inline void tcg_out_ld16s(TCGContext *s, int cond,
913 int rd, int rn, int32_t offset)
914 {
915 if (offset > 0xff || offset < -0xff) {
916 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
917 tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_TMP);
918 } else
919 tcg_out_ld16s_8(s, cond, rd, rn, offset);
920 }
921
922 static inline void tcg_out_st16(TCGContext *s, int cond,
923 int rd, int rn, int32_t offset)
924 {
925 if (offset > 0xff || offset < -0xff) {
926 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
927 tcg_out_st16_r(s, cond, rd, rn, TCG_REG_TMP);
928 } else
929 tcg_out_st16_8(s, cond, rd, rn, offset);
930 }
931
932 static inline void tcg_out_ld8u(TCGContext *s, int cond,
933 int rd, int rn, int32_t offset)
934 {
935 if (offset > 0xfff || offset < -0xfff) {
936 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
937 tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_TMP);
938 } else
939 tcg_out_ld8_12(s, cond, rd, rn, offset);
940 }
941
942 static inline void tcg_out_ld8s(TCGContext *s, int cond,
943 int rd, int rn, int32_t offset)
944 {
945 if (offset > 0xff || offset < -0xff) {
946 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
947 tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_TMP);
948 } else
949 tcg_out_ld8s_8(s, cond, rd, rn, offset);
950 }
951
952 static inline void tcg_out_st8(TCGContext *s, int cond,
953 int rd, int rn, int32_t offset)
954 {
955 if (offset > 0xfff || offset < -0xfff) {
956 tcg_out_movi32(s, cond, TCG_REG_TMP, offset);
957 tcg_out_st8_r(s, cond, rd, rn, TCG_REG_TMP);
958 } else
959 tcg_out_st8_12(s, cond, rd, rn, offset);
960 }
961
962 /* The _goto case is normally between TBs within the same code buffer, and
963 * with the code buffer limited to 16MB we wouldn't need the long case.
964 * But we also use it for the tail-call to the qemu_ld/st helpers, which does.
965 */
966 static inline void tcg_out_goto(TCGContext *s, int cond, tcg_insn_unit *addr)
967 {
968 intptr_t addri = (intptr_t)addr;
969 ptrdiff_t disp = tcg_pcrel_diff(s, addr);
970
971 if ((addri & 1) == 0 && disp - 8 < 0x01fffffd && disp - 8 > -0x01fffffd) {
972 tcg_out_b(s, cond, disp);
973 return;
974 }
975
976 tcg_out_movi32(s, cond, TCG_REG_TMP, addri);
977 if (use_armv5t_instructions) {
978 tcg_out_bx(s, cond, TCG_REG_TMP);
979 } else {
980 if (addri & 1) {
981 tcg_abort();
982 }
983 tcg_out_mov_reg(s, cond, TCG_REG_PC, TCG_REG_TMP);
984 }
985 }
986
987 /* The call case is mostly used for helpers - so it's not unreasonable
988 * for them to be beyond branch range */
989 static void tcg_out_call(TCGContext *s, tcg_insn_unit *addr)
990 {
991 intptr_t addri = (intptr_t)addr;
992 ptrdiff_t disp = tcg_pcrel_diff(s, addr);
993
994 if (disp - 8 < 0x02000000 && disp - 8 >= -0x02000000) {
995 if (addri & 1) {
996 /* Use BLX if the target is in Thumb mode */
997 if (!use_armv5t_instructions) {
998 tcg_abort();
999 }
1000 tcg_out_blx_imm(s, disp);
1001 } else {
1002 tcg_out_bl(s, COND_AL, disp);
1003 }
1004 } else if (use_armv7_instructions) {
1005 tcg_out_movi32(s, COND_AL, TCG_REG_TMP, addri);
1006 tcg_out_blx(s, COND_AL, TCG_REG_TMP);
1007 } else {
1008 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
1009 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1010 tcg_out32(s, addri);
1011 }
1012 }
1013
1014 void arm_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
1015 {
1016 tcg_insn_unit *code_ptr = (tcg_insn_unit *)jmp_addr;
1017 tcg_insn_unit *target = (tcg_insn_unit *)addr;
1018
1019 /* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
1020 reloc_pc24_atomic(code_ptr, target);
1021 flush_icache_range(jmp_addr, jmp_addr + 4);
1022 }
1023
1024 static inline void tcg_out_goto_label(TCGContext *s, int cond, TCGLabel *l)
1025 {
1026 if (l->has_value) {
1027 tcg_out_goto(s, cond, l->u.value_ptr);
1028 } else {
1029 tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, l, 0);
1030 tcg_out_b_noaddr(s, cond);
1031 }
1032 }
1033
1034 static inline void tcg_out_mb(TCGContext *s, TCGArg a0)
1035 {
1036 if (use_armv7_instructions) {
1037 tcg_out32(s, INSN_DMB_ISH);
1038 } else if (use_armv6_instructions) {
1039 tcg_out32(s, INSN_DMB_MCR);
1040 }
1041 }
1042
1043 #ifdef CONFIG_SOFTMMU
1044 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1045 * int mmu_idx, uintptr_t ra)
1046 */
1047 static void * const qemu_ld_helpers[16] = {
1048 [MO_UB] = helper_ret_ldub_mmu,
1049 [MO_SB] = helper_ret_ldsb_mmu,
1050
1051 [MO_LEUW] = helper_le_lduw_mmu,
1052 [MO_LEUL] = helper_le_ldul_mmu,
1053 [MO_LEQ] = helper_le_ldq_mmu,
1054 [MO_LESW] = helper_le_ldsw_mmu,
1055 [MO_LESL] = helper_le_ldul_mmu,
1056
1057 [MO_BEUW] = helper_be_lduw_mmu,
1058 [MO_BEUL] = helper_be_ldul_mmu,
1059 [MO_BEQ] = helper_be_ldq_mmu,
1060 [MO_BESW] = helper_be_ldsw_mmu,
1061 [MO_BESL] = helper_be_ldul_mmu,
1062 };
1063
1064 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1065 * uintxx_t val, int mmu_idx, uintptr_t ra)
1066 */
1067 static void * const qemu_st_helpers[16] = {
1068 [MO_UB] = helper_ret_stb_mmu,
1069 [MO_LEUW] = helper_le_stw_mmu,
1070 [MO_LEUL] = helper_le_stl_mmu,
1071 [MO_LEQ] = helper_le_stq_mmu,
1072 [MO_BEUW] = helper_be_stw_mmu,
1073 [MO_BEUL] = helper_be_stl_mmu,
1074 [MO_BEQ] = helper_be_stq_mmu,
1075 };
1076
1077 /* Helper routines for marshalling helper function arguments into
1078 * the correct registers and stack.
1079 * argreg is where we want to put this argument, arg is the argument itself.
1080 * Return value is the updated argreg ready for the next call.
1081 * Note that argreg 0..3 is real registers, 4+ on stack.
1082 *
1083 * We provide routines for arguments which are: immediate, 32 bit
1084 * value in register, 16 and 8 bit values in register (which must be zero
1085 * extended before use) and 64 bit value in a lo:hi register pair.
1086 */
1087 #define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \
1088 static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \
1089 { \
1090 if (argreg < 4) { \
1091 MOV_ARG(s, COND_AL, argreg, arg); \
1092 } else { \
1093 int ofs = (argreg - 4) * 4; \
1094 EXT_ARG; \
1095 tcg_debug_assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \
1096 tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \
1097 } \
1098 return argreg + 1; \
1099 }
1100
1101 DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32,
1102 (tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1103 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u,
1104 (tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1105 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u,
1106 (tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP))
1107 DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, )
1108
1109 static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg,
1110 TCGReg arglo, TCGReg arghi)
1111 {
1112 /* 64 bit arguments must go in even/odd register pairs
1113 * and in 8-aligned stack slots.
1114 */
1115 if (argreg & 1) {
1116 argreg++;
1117 }
1118 if (use_armv6_instructions && argreg >= 4
1119 && (arglo & 1) == 0 && arghi == arglo + 1) {
1120 tcg_out_strd_8(s, COND_AL, arglo,
1121 TCG_REG_CALL_STACK, (argreg - 4) * 4);
1122 return argreg + 2;
1123 } else {
1124 argreg = tcg_out_arg_reg32(s, argreg, arglo);
1125 argreg = tcg_out_arg_reg32(s, argreg, arghi);
1126 return argreg;
1127 }
1128 }
1129
1130 #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
1131
1132 /* We're expecting to use an 8-bit immediate and to mask. */
1133 QEMU_BUILD_BUG_ON(CPU_TLB_BITS > 8);
1134
1135 /* We're expecting to use an 8-bit immediate add + 8-bit ldrd offset.
1136 Using the offset of the second entry in the last tlb table ensures
1137 that we can index all of the elements of the first entry. */
1138 QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
1139 > 0xffff);
1140
1141 /* Load and compare a TLB entry, leaving the flags set. Returns the register
1142 containing the addend of the tlb entry. Clobbers R0, R1, R2, TMP. */
1143
1144 static TCGReg tcg_out_tlb_read(TCGContext *s, TCGReg addrlo, TCGReg addrhi,
1145 TCGMemOp opc, int mem_index, bool is_load)
1146 {
1147 TCGReg base = TCG_AREG0;
1148 int cmp_off =
1149 (is_load
1150 ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1151 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1152 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1153 unsigned s_bits = opc & MO_SIZE;
1154 unsigned a_bits = get_alignment_bits(opc);
1155
1156 /* Should generate something like the following:
1157 * shr tmp, addrlo, #TARGET_PAGE_BITS (1)
1158 * add r2, env, #high
1159 * and r0, tmp, #(CPU_TLB_SIZE - 1) (2)
1160 * add r2, r2, r0, lsl #CPU_TLB_ENTRY_BITS (3)
1161 * ldr r0, [r2, #cmp] (4)
1162 * tst addrlo, #s_mask
1163 * ldr r2, [r2, #add] (5)
1164 * cmpeq r0, tmp, lsl #TARGET_PAGE_BITS
1165 */
1166 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_TMP,
1167 0, addrlo, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1168
1169 /* We checked that the offset is contained within 16 bits above. */
1170 if (add_off > 0xfff || (use_armv6_instructions && cmp_off > 0xff)) {
1171 tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1172 (24 << 7) | (cmp_off >> 8));
1173 base = TCG_REG_R2;
1174 add_off -= cmp_off & 0xff00;
1175 cmp_off &= 0xff;
1176 }
1177
1178 tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1179 TCG_REG_R0, TCG_REG_TMP, CPU_TLB_SIZE - 1);
1180 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R2, base,
1181 TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1182
1183 /* Load the tlb comparator. Use ldrd if needed and available,
1184 but due to how the pointer needs setting up, ldm isn't useful.
1185 Base arm5 doesn't have ldrd, but armv5te does. */
1186 if (use_armv6_instructions && TARGET_LONG_BITS == 64) {
1187 tcg_out_ldrd_8(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1188 } else {
1189 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_R2, cmp_off);
1190 if (TARGET_LONG_BITS == 64) {
1191 tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R2, cmp_off + 4);
1192 }
1193 }
1194
1195 /* Check alignment. We don't support inline unaligned acceses,
1196 but we can easily support overalignment checks. */
1197 if (a_bits < s_bits) {
1198 a_bits = s_bits;
1199 }
1200 if (a_bits) {
1201 tcg_out_dat_imm(s, COND_AL, ARITH_TST, 0, addrlo, (1 << a_bits) - 1);
1202 }
1203
1204 /* Load the tlb addend. */
1205 tcg_out_ld32_12(s, COND_AL, TCG_REG_R2, TCG_REG_R2, add_off);
1206
1207 tcg_out_dat_reg(s, (s_bits ? COND_EQ : COND_AL), ARITH_CMP, 0,
1208 TCG_REG_R0, TCG_REG_TMP, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1209
1210 if (TARGET_LONG_BITS == 64) {
1211 tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1212 TCG_REG_R1, addrhi, SHIFT_IMM_LSL(0));
1213 }
1214
1215 return TCG_REG_R2;
1216 }
1217
1218 /* Record the context of a call to the out of line helper code for the slow
1219 path for a load or store, so that we can later generate the correct
1220 helper code. */
1221 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
1222 TCGReg datalo, TCGReg datahi, TCGReg addrlo,
1223 TCGReg addrhi, tcg_insn_unit *raddr,
1224 tcg_insn_unit *label_ptr)
1225 {
1226 TCGLabelQemuLdst *label = new_ldst_label(s);
1227
1228 label->is_ld = is_ld;
1229 label->oi = oi;
1230 label->datalo_reg = datalo;
1231 label->datahi_reg = datahi;
1232 label->addrlo_reg = addrlo;
1233 label->addrhi_reg = addrhi;
1234 label->raddr = raddr;
1235 label->label_ptr[0] = label_ptr;
1236 }
1237
1238 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1239 {
1240 TCGReg argreg, datalo, datahi;
1241 TCGMemOpIdx oi = lb->oi;
1242 TCGMemOp opc = get_memop(oi);
1243 void *func;
1244
1245 reloc_pc24(lb->label_ptr[0], s->code_ptr);
1246
1247 argreg = tcg_out_arg_reg32(s, TCG_REG_R0, TCG_AREG0);
1248 if (TARGET_LONG_BITS == 64) {
1249 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1250 } else {
1251 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1252 }
1253 argreg = tcg_out_arg_imm32(s, argreg, oi);
1254 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1255
1256 /* For armv6 we can use the canonical unsigned helpers and minimize
1257 icache usage. For pre-armv6, use the signed helpers since we do
1258 not have a single insn sign-extend. */
1259 if (use_armv6_instructions) {
1260 func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)];
1261 } else {
1262 func = qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)];
1263 if (opc & MO_SIGN) {
1264 opc = MO_UL;
1265 }
1266 }
1267 tcg_out_call(s, func);
1268
1269 datalo = lb->datalo_reg;
1270 datahi = lb->datahi_reg;
1271 switch (opc & MO_SSIZE) {
1272 case MO_SB:
1273 tcg_out_ext8s(s, COND_AL, datalo, TCG_REG_R0);
1274 break;
1275 case MO_SW:
1276 tcg_out_ext16s(s, COND_AL, datalo, TCG_REG_R0);
1277 break;
1278 default:
1279 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1280 break;
1281 case MO_Q:
1282 if (datalo != TCG_REG_R1) {
1283 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1284 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1285 } else if (datahi != TCG_REG_R0) {
1286 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1287 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0);
1288 } else {
1289 tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0);
1290 tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1);
1291 tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_TMP);
1292 }
1293 break;
1294 }
1295
1296 tcg_out_goto(s, COND_AL, lb->raddr);
1297 }
1298
1299 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1300 {
1301 TCGReg argreg, datalo, datahi;
1302 TCGMemOpIdx oi = lb->oi;
1303 TCGMemOp opc = get_memop(oi);
1304
1305 reloc_pc24(lb->label_ptr[0], s->code_ptr);
1306
1307 argreg = TCG_REG_R0;
1308 argreg = tcg_out_arg_reg32(s, argreg, TCG_AREG0);
1309 if (TARGET_LONG_BITS == 64) {
1310 argreg = tcg_out_arg_reg64(s, argreg, lb->addrlo_reg, lb->addrhi_reg);
1311 } else {
1312 argreg = tcg_out_arg_reg32(s, argreg, lb->addrlo_reg);
1313 }
1314
1315 datalo = lb->datalo_reg;
1316 datahi = lb->datahi_reg;
1317 switch (opc & MO_SIZE) {
1318 case MO_8:
1319 argreg = tcg_out_arg_reg8(s, argreg, datalo);
1320 break;
1321 case MO_16:
1322 argreg = tcg_out_arg_reg16(s, argreg, datalo);
1323 break;
1324 case MO_32:
1325 default:
1326 argreg = tcg_out_arg_reg32(s, argreg, datalo);
1327 break;
1328 case MO_64:
1329 argreg = tcg_out_arg_reg64(s, argreg, datalo, datahi);
1330 break;
1331 }
1332
1333 argreg = tcg_out_arg_imm32(s, argreg, oi);
1334 argreg = tcg_out_arg_reg32(s, argreg, TCG_REG_R14);
1335
1336 /* Tail-call to the helper, which will return to the fast path. */
1337 tcg_out_goto(s, COND_AL, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1338 }
1339 #endif /* SOFTMMU */
1340
1341 static inline void tcg_out_qemu_ld_index(TCGContext *s, TCGMemOp opc,
1342 TCGReg datalo, TCGReg datahi,
1343 TCGReg addrlo, TCGReg addend)
1344 {
1345 TCGMemOp bswap = opc & MO_BSWAP;
1346
1347 switch (opc & MO_SSIZE) {
1348 case MO_UB:
1349 tcg_out_ld8_r(s, COND_AL, datalo, addrlo, addend);
1350 break;
1351 case MO_SB:
1352 tcg_out_ld8s_r(s, COND_AL, datalo, addrlo, addend);
1353 break;
1354 case MO_UW:
1355 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1356 if (bswap) {
1357 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1358 }
1359 break;
1360 case MO_SW:
1361 if (bswap) {
1362 tcg_out_ld16u_r(s, COND_AL, datalo, addrlo, addend);
1363 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1364 } else {
1365 tcg_out_ld16s_r(s, COND_AL, datalo, addrlo, addend);
1366 }
1367 break;
1368 case MO_UL:
1369 default:
1370 tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
1371 if (bswap) {
1372 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1373 }
1374 break;
1375 case MO_Q:
1376 {
1377 TCGReg dl = (bswap ? datahi : datalo);
1378 TCGReg dh = (bswap ? datalo : datahi);
1379
1380 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1381 if (USING_SOFTMMU && use_armv6_instructions
1382 && (dl & 1) == 0 && dh == dl + 1) {
1383 tcg_out_ldrd_r(s, COND_AL, dl, addrlo, addend);
1384 } else if (dl != addend) {
1385 tcg_out_ld32_rwb(s, COND_AL, dl, addend, addrlo);
1386 tcg_out_ld32_12(s, COND_AL, dh, addend, 4);
1387 } else {
1388 tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
1389 addend, addrlo, SHIFT_IMM_LSL(0));
1390 tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0);
1391 tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
1392 }
1393 if (bswap) {
1394 tcg_out_bswap32(s, COND_AL, dl, dl);
1395 tcg_out_bswap32(s, COND_AL, dh, dh);
1396 }
1397 }
1398 break;
1399 }
1400 }
1401
1402 static inline void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp opc,
1403 TCGReg datalo, TCGReg datahi,
1404 TCGReg addrlo)
1405 {
1406 TCGMemOp bswap = opc & MO_BSWAP;
1407
1408 switch (opc & MO_SSIZE) {
1409 case MO_UB:
1410 tcg_out_ld8_12(s, COND_AL, datalo, addrlo, 0);
1411 break;
1412 case MO_SB:
1413 tcg_out_ld8s_8(s, COND_AL, datalo, addrlo, 0);
1414 break;
1415 case MO_UW:
1416 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1417 if (bswap) {
1418 tcg_out_bswap16(s, COND_AL, datalo, datalo);
1419 }
1420 break;
1421 case MO_SW:
1422 if (bswap) {
1423 tcg_out_ld16u_8(s, COND_AL, datalo, addrlo, 0);
1424 tcg_out_bswap16s(s, COND_AL, datalo, datalo);
1425 } else {
1426 tcg_out_ld16s_8(s, COND_AL, datalo, addrlo, 0);
1427 }
1428 break;
1429 case MO_UL:
1430 default:
1431 tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
1432 if (bswap) {
1433 tcg_out_bswap32(s, COND_AL, datalo, datalo);
1434 }
1435 break;
1436 case MO_Q:
1437 {
1438 TCGReg dl = (bswap ? datahi : datalo);
1439 TCGReg dh = (bswap ? datalo : datahi);
1440
1441 /* Avoid ldrd for user-only emulation, to handle unaligned. */
1442 if (USING_SOFTMMU && use_armv6_instructions
1443 && (dl & 1) == 0 && dh == dl + 1) {
1444 tcg_out_ldrd_8(s, COND_AL, dl, addrlo, 0);
1445 } else if (dl == addrlo) {
1446 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1447 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1448 } else {
1449 tcg_out_ld32_12(s, COND_AL, dl, addrlo, bswap ? 4 : 0);
1450 tcg_out_ld32_12(s, COND_AL, dh, addrlo, bswap ? 0 : 4);
1451 }
1452 if (bswap) {
1453 tcg_out_bswap32(s, COND_AL, dl, dl);
1454 tcg_out_bswap32(s, COND_AL, dh, dh);
1455 }
1456 }
1457 break;
1458 }
1459 }
1460
1461 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is64)
1462 {
1463 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1464 TCGMemOpIdx oi;
1465 TCGMemOp opc;
1466 #ifdef CONFIG_SOFTMMU
1467 int mem_index;
1468 TCGReg addend;
1469 tcg_insn_unit *label_ptr;
1470 #endif
1471
1472 datalo = *args++;
1473 datahi = (is64 ? *args++ : 0);
1474 addrlo = *args++;
1475 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1476 oi = *args++;
1477 opc = get_memop(oi);
1478
1479 #ifdef CONFIG_SOFTMMU
1480 mem_index = get_mmuidx(oi);
1481 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 1);
1482
1483 /* This a conditional BL only to load a pointer within this opcode into LR
1484 for the slow path. We will not be using the value for a tail call. */
1485 label_ptr = s->code_ptr;
1486 tcg_out_bl_noaddr(s, COND_NE);
1487
1488 tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, addend);
1489
1490 add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
1491 s->code_ptr, label_ptr);
1492 #else /* !CONFIG_SOFTMMU */
1493 if (guest_base) {
1494 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
1495 tcg_out_qemu_ld_index(s, opc, datalo, datahi, addrlo, TCG_REG_TMP);
1496 } else {
1497 tcg_out_qemu_ld_direct(s, opc, datalo, datahi, addrlo);
1498 }
1499 #endif
1500 }
1501
1502 static inline void tcg_out_qemu_st_index(TCGContext *s, int cond, TCGMemOp opc,
1503 TCGReg datalo, TCGReg datahi,
1504 TCGReg addrlo, TCGReg addend)
1505 {
1506 TCGMemOp bswap = opc & MO_BSWAP;
1507
1508 switch (opc & MO_SIZE) {
1509 case MO_8:
1510 tcg_out_st8_r(s, cond, datalo, addrlo, addend);
1511 break;
1512 case MO_16:
1513 if (bswap) {
1514 tcg_out_bswap16st(s, cond, TCG_REG_R0, datalo);
1515 tcg_out_st16_r(s, cond, TCG_REG_R0, addrlo, addend);
1516 } else {
1517 tcg_out_st16_r(s, cond, datalo, addrlo, addend);
1518 }
1519 break;
1520 case MO_32:
1521 default:
1522 if (bswap) {
1523 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1524 tcg_out_st32_r(s, cond, TCG_REG_R0, addrlo, addend);
1525 } else {
1526 tcg_out_st32_r(s, cond, datalo, addrlo, addend);
1527 }
1528 break;
1529 case MO_64:
1530 /* Avoid strd for user-only emulation, to handle unaligned. */
1531 if (bswap) {
1532 tcg_out_bswap32(s, cond, TCG_REG_R0, datahi);
1533 tcg_out_st32_rwb(s, cond, TCG_REG_R0, addend, addrlo);
1534 tcg_out_bswap32(s, cond, TCG_REG_R0, datalo);
1535 tcg_out_st32_12(s, cond, TCG_REG_R0, addend, 4);
1536 } else if (USING_SOFTMMU && use_armv6_instructions
1537 && (datalo & 1) == 0 && datahi == datalo + 1) {
1538 tcg_out_strd_r(s, cond, datalo, addrlo, addend);
1539 } else {
1540 tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
1541 tcg_out_st32_12(s, cond, datahi, addend, 4);
1542 }
1543 break;
1544 }
1545 }
1546
1547 static inline void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp opc,
1548 TCGReg datalo, TCGReg datahi,
1549 TCGReg addrlo)
1550 {
1551 TCGMemOp bswap = opc & MO_BSWAP;
1552
1553 switch (opc & MO_SIZE) {
1554 case MO_8:
1555 tcg_out_st8_12(s, COND_AL, datalo, addrlo, 0);
1556 break;
1557 case MO_16:
1558 if (bswap) {
1559 tcg_out_bswap16st(s, COND_AL, TCG_REG_R0, datalo);
1560 tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addrlo, 0);
1561 } else {
1562 tcg_out_st16_8(s, COND_AL, datalo, addrlo, 0);
1563 }
1564 break;
1565 case MO_32:
1566 default:
1567 if (bswap) {
1568 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1569 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1570 } else {
1571 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1572 }
1573 break;
1574 case MO_64:
1575 /* Avoid strd for user-only emulation, to handle unaligned. */
1576 if (bswap) {
1577 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datahi);
1578 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 0);
1579 tcg_out_bswap32(s, COND_AL, TCG_REG_R0, datalo);
1580 tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addrlo, 4);
1581 } else if (USING_SOFTMMU && use_armv6_instructions
1582 && (datalo & 1) == 0 && datahi == datalo + 1) {
1583 tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
1584 } else {
1585 tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
1586 tcg_out_st32_12(s, COND_AL, datahi, addrlo, 4);
1587 }
1588 break;
1589 }
1590 }
1591
1592 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64)
1593 {
1594 TCGReg addrlo, datalo, datahi, addrhi __attribute__((unused));
1595 TCGMemOpIdx oi;
1596 TCGMemOp opc;
1597 #ifdef CONFIG_SOFTMMU
1598 int mem_index;
1599 TCGReg addend;
1600 tcg_insn_unit *label_ptr;
1601 #endif
1602
1603 datalo = *args++;
1604 datahi = (is64 ? *args++ : 0);
1605 addrlo = *args++;
1606 addrhi = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1607 oi = *args++;
1608 opc = get_memop(oi);
1609
1610 #ifdef CONFIG_SOFTMMU
1611 mem_index = get_mmuidx(oi);
1612 addend = tcg_out_tlb_read(s, addrlo, addrhi, opc, mem_index, 0);
1613
1614 tcg_out_qemu_st_index(s, COND_EQ, opc, datalo, datahi, addrlo, addend);
1615
1616 /* The conditional call must come last, as we're going to return here. */
1617 label_ptr = s->code_ptr;
1618 tcg_out_bl_noaddr(s, COND_NE);
1619
1620 add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi,
1621 s->code_ptr, label_ptr);
1622 #else /* !CONFIG_SOFTMMU */
1623 if (guest_base) {
1624 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, guest_base);
1625 tcg_out_qemu_st_index(s, COND_AL, opc, datalo,
1626 datahi, addrlo, TCG_REG_TMP);
1627 } else {
1628 tcg_out_qemu_st_direct(s, opc, datalo, datahi, addrlo);
1629 }
1630 #endif
1631 }
1632
1633 static tcg_insn_unit *tb_ret_addr;
1634
1635 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1636 const TCGArg *args, const int *const_args)
1637 {
1638 TCGArg a0, a1, a2, a3, a4, a5;
1639 int c;
1640
1641 switch (opc) {
1642 case INDEX_op_exit_tb:
1643 tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]);
1644 tcg_out_goto(s, COND_AL, tb_ret_addr);
1645 break;
1646 case INDEX_op_goto_tb:
1647 if (s->tb_jmp_insn_offset) {
1648 /* Direct jump method */
1649 s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s);
1650 tcg_out_b_noaddr(s, COND_AL);
1651 } else {
1652 /* Indirect jump method */
1653 intptr_t ptr = (intptr_t)(s->tb_jmp_target_addr + args[0]);
1654 tcg_out_movi32(s, COND_AL, TCG_REG_R0, ptr & ~0xfff);
1655 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, ptr & 0xfff);
1656 }
1657 s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s);
1658 break;
1659 case INDEX_op_br:
1660 tcg_out_goto_label(s, COND_AL, arg_label(args[0]));
1661 break;
1662
1663 case INDEX_op_ld8u_i32:
1664 tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1665 break;
1666 case INDEX_op_ld8s_i32:
1667 tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1668 break;
1669 case INDEX_op_ld16u_i32:
1670 tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1671 break;
1672 case INDEX_op_ld16s_i32:
1673 tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1674 break;
1675 case INDEX_op_ld_i32:
1676 tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1677 break;
1678 case INDEX_op_st8_i32:
1679 tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1680 break;
1681 case INDEX_op_st16_i32:
1682 tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1683 break;
1684 case INDEX_op_st_i32:
1685 tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1686 break;
1687
1688 case INDEX_op_movcond_i32:
1689 /* Constraints mean that v2 is always in the same register as dest,
1690 * so we only need to do "if condition passed, move v1 to dest".
1691 */
1692 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1693 args[1], args[2], const_args[2]);
1694 tcg_out_dat_rIK(s, tcg_cond_to_arm_cond[args[5]], ARITH_MOV,
1695 ARITH_MVN, args[0], 0, args[3], const_args[3]);
1696 break;
1697 case INDEX_op_add_i32:
1698 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
1699 args[0], args[1], args[2], const_args[2]);
1700 break;
1701 case INDEX_op_sub_i32:
1702 if (const_args[1]) {
1703 if (const_args[2]) {
1704 tcg_out_movi32(s, COND_AL, args[0], args[1] - args[2]);
1705 } else {
1706 tcg_out_dat_rI(s, COND_AL, ARITH_RSB,
1707 args[0], args[2], args[1], 1);
1708 }
1709 } else {
1710 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB, ARITH_ADD,
1711 args[0], args[1], args[2], const_args[2]);
1712 }
1713 break;
1714 case INDEX_op_and_i32:
1715 tcg_out_dat_rIK(s, COND_AL, ARITH_AND, ARITH_BIC,
1716 args[0], args[1], args[2], const_args[2]);
1717 break;
1718 case INDEX_op_andc_i32:
1719 tcg_out_dat_rIK(s, COND_AL, ARITH_BIC, ARITH_AND,
1720 args[0], args[1], args[2], const_args[2]);
1721 break;
1722 case INDEX_op_or_i32:
1723 c = ARITH_ORR;
1724 goto gen_arith;
1725 case INDEX_op_xor_i32:
1726 c = ARITH_EOR;
1727 /* Fall through. */
1728 gen_arith:
1729 tcg_out_dat_rI(s, COND_AL, c, args[0], args[1], args[2], const_args[2]);
1730 break;
1731 case INDEX_op_add2_i32:
1732 a0 = args[0], a1 = args[1], a2 = args[2];
1733 a3 = args[3], a4 = args[4], a5 = args[5];
1734 if (a0 == a3 || (a0 == a5 && !const_args[5])) {
1735 a0 = TCG_REG_TMP;
1736 }
1737 tcg_out_dat_rIN(s, COND_AL, ARITH_ADD | TO_CPSR, ARITH_SUB | TO_CPSR,
1738 a0, a2, a4, const_args[4]);
1739 tcg_out_dat_rIK(s, COND_AL, ARITH_ADC, ARITH_SBC,
1740 a1, a3, a5, const_args[5]);
1741 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1742 break;
1743 case INDEX_op_sub2_i32:
1744 a0 = args[0], a1 = args[1], a2 = args[2];
1745 a3 = args[3], a4 = args[4], a5 = args[5];
1746 if ((a0 == a3 && !const_args[3]) || (a0 == a5 && !const_args[5])) {
1747 a0 = TCG_REG_TMP;
1748 }
1749 if (const_args[2]) {
1750 if (const_args[4]) {
1751 tcg_out_movi32(s, COND_AL, a0, a4);
1752 a4 = a0;
1753 }
1754 tcg_out_dat_rI(s, COND_AL, ARITH_RSB | TO_CPSR, a0, a4, a2, 1);
1755 } else {
1756 tcg_out_dat_rIN(s, COND_AL, ARITH_SUB | TO_CPSR,
1757 ARITH_ADD | TO_CPSR, a0, a2, a4, const_args[4]);
1758 }
1759 if (const_args[3]) {
1760 if (const_args[5]) {
1761 tcg_out_movi32(s, COND_AL, a1, a5);
1762 a5 = a1;
1763 }
1764 tcg_out_dat_rI(s, COND_AL, ARITH_RSC, a1, a5, a3, 1);
1765 } else {
1766 tcg_out_dat_rIK(s, COND_AL, ARITH_SBC, ARITH_ADC,
1767 a1, a3, a5, const_args[5]);
1768 }
1769 tcg_out_mov_reg(s, COND_AL, args[0], a0);
1770 break;
1771 case INDEX_op_neg_i32:
1772 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1773 break;
1774 case INDEX_op_not_i32:
1775 tcg_out_dat_reg(s, COND_AL,
1776 ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1777 break;
1778 case INDEX_op_mul_i32:
1779 tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1780 break;
1781 case INDEX_op_mulu2_i32:
1782 tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1783 break;
1784 case INDEX_op_muls2_i32:
1785 tcg_out_smull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1786 break;
1787 /* XXX: Perhaps args[2] & 0x1f is wrong */
1788 case INDEX_op_shl_i32:
1789 c = const_args[2] ?
1790 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1791 goto gen_shift32;
1792 case INDEX_op_shr_i32:
1793 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1794 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1795 goto gen_shift32;
1796 case INDEX_op_sar_i32:
1797 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1798 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1799 goto gen_shift32;
1800 case INDEX_op_rotr_i32:
1801 c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1802 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1803 /* Fall through. */
1804 gen_shift32:
1805 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1806 break;
1807
1808 case INDEX_op_rotl_i32:
1809 if (const_args[2]) {
1810 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1811 ((0x20 - args[2]) & 0x1f) ?
1812 SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1813 SHIFT_IMM_LSL(0));
1814 } else {
1815 tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_TMP, args[2], 0x20);
1816 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1817 SHIFT_REG_ROR(TCG_REG_TMP));
1818 }
1819 break;
1820
1821 case INDEX_op_brcond_i32:
1822 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1823 args[0], args[1], const_args[1]);
1824 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]],
1825 arg_label(args[3]));
1826 break;
1827 case INDEX_op_brcond2_i32:
1828 /* The resulting conditions are:
1829 * TCG_COND_EQ --> a0 == a2 && a1 == a3,
1830 * TCG_COND_NE --> (a0 != a2 && a1 == a3) || a1 != a3,
1831 * TCG_COND_LT(U) --> (a0 < a2 && a1 == a3) || a1 < a3,
1832 * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1833 * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1834 * TCG_COND_GT(U) --> (a0 > a2 && a1 == a3) || a1 > a3,
1835 */
1836 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1837 args[1], args[3], const_args[3]);
1838 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1839 args[0], args[2], const_args[2]);
1840 tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]],
1841 arg_label(args[5]));
1842 break;
1843 case INDEX_op_setcond_i32:
1844 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1845 args[1], args[2], const_args[2]);
1846 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1847 ARITH_MOV, args[0], 0, 1);
1848 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1849 ARITH_MOV, args[0], 0, 0);
1850 break;
1851 case INDEX_op_setcond2_i32:
1852 /* See brcond2_i32 comment */
1853 tcg_out_dat_rIN(s, COND_AL, ARITH_CMP, ARITH_CMN, 0,
1854 args[2], args[4], const_args[4]);
1855 tcg_out_dat_rIN(s, COND_EQ, ARITH_CMP, ARITH_CMN, 0,
1856 args[1], args[3], const_args[3]);
1857 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1858 ARITH_MOV, args[0], 0, 1);
1859 tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1860 ARITH_MOV, args[0], 0, 0);
1861 break;
1862
1863 case INDEX_op_qemu_ld_i32:
1864 tcg_out_qemu_ld(s, args, 0);
1865 break;
1866 case INDEX_op_qemu_ld_i64:
1867 tcg_out_qemu_ld(s, args, 1);
1868 break;
1869 case INDEX_op_qemu_st_i32:
1870 tcg_out_qemu_st(s, args, 0);
1871 break;
1872 case INDEX_op_qemu_st_i64:
1873 tcg_out_qemu_st(s, args, 1);
1874 break;
1875
1876 case INDEX_op_bswap16_i32:
1877 tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1878 break;
1879 case INDEX_op_bswap32_i32:
1880 tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1881 break;
1882
1883 case INDEX_op_ext8s_i32:
1884 tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1885 break;
1886 case INDEX_op_ext16s_i32:
1887 tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1888 break;
1889 case INDEX_op_ext16u_i32:
1890 tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1891 break;
1892
1893 case INDEX_op_deposit_i32:
1894 tcg_out_deposit(s, COND_AL, args[0], args[2],
1895 args[3], args[4], const_args[2]);
1896 break;
1897
1898 case INDEX_op_div_i32:
1899 tcg_out_sdiv(s, COND_AL, args[0], args[1], args[2]);
1900 break;
1901 case INDEX_op_divu_i32:
1902 tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]);
1903 break;
1904
1905 case INDEX_op_mb:
1906 tcg_out_mb(s, args[0]);
1907 break;
1908
1909 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1910 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1911 case INDEX_op_call: /* Always emitted via tcg_out_call. */
1912 default:
1913 tcg_abort();
1914 }
1915 }
1916
1917 static const TCGTargetOpDef arm_op_defs[] = {
1918 { INDEX_op_exit_tb, { } },
1919 { INDEX_op_goto_tb, { } },
1920 { INDEX_op_br, { } },
1921
1922 { INDEX_op_ld8u_i32, { "r", "r" } },
1923 { INDEX_op_ld8s_i32, { "r", "r" } },
1924 { INDEX_op_ld16u_i32, { "r", "r" } },
1925 { INDEX_op_ld16s_i32, { "r", "r" } },
1926 { INDEX_op_ld_i32, { "r", "r" } },
1927 { INDEX_op_st8_i32, { "r", "r" } },
1928 { INDEX_op_st16_i32, { "r", "r" } },
1929 { INDEX_op_st_i32, { "r", "r" } },
1930
1931 /* TODO: "r", "r", "ri" */
1932 { INDEX_op_add_i32, { "r", "r", "rIN" } },
1933 { INDEX_op_sub_i32, { "r", "rI", "rIN" } },
1934 { INDEX_op_mul_i32, { "r", "r", "r" } },
1935 { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1936 { INDEX_op_muls2_i32, { "r", "r", "r", "r" } },
1937 { INDEX_op_and_i32, { "r", "r", "rIK" } },
1938 { INDEX_op_andc_i32, { "r", "r", "rIK" } },
1939 { INDEX_op_or_i32, { "r", "r", "rI" } },
1940 { INDEX_op_xor_i32, { "r", "r", "rI" } },
1941 { INDEX_op_neg_i32, { "r", "r" } },
1942 { INDEX_op_not_i32, { "r", "r" } },
1943
1944 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1945 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1946 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1947 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1948 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1949
1950 { INDEX_op_brcond_i32, { "r", "rIN" } },
1951 { INDEX_op_setcond_i32, { "r", "r", "rIN" } },
1952 { INDEX_op_movcond_i32, { "r", "r", "rIN", "rIK", "0" } },
1953
1954 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rIN", "rIK" } },
1955 { INDEX_op_sub2_i32, { "r", "r", "rI", "rI", "rIN", "rIK" } },
1956 { INDEX_op_brcond2_i32, { "r", "r", "rIN", "rIN" } },
1957 { INDEX_op_setcond2_i32, { "r", "r", "r", "rIN", "rIN" } },
1958
1959 #if TARGET_LONG_BITS == 32
1960 { INDEX_op_qemu_ld_i32, { "r", "l" } },
1961 { INDEX_op_qemu_ld_i64, { "r", "r", "l" } },
1962 { INDEX_op_qemu_st_i32, { "s", "s" } },
1963 { INDEX_op_qemu_st_i64, { "s", "s", "s" } },
1964 #else
1965 { INDEX_op_qemu_ld_i32, { "r", "l", "l" } },
1966 { INDEX_op_qemu_ld_i64, { "r", "r", "l", "l" } },
1967 { INDEX_op_qemu_st_i32, { "s", "s", "s" } },
1968 { INDEX_op_qemu_st_i64, { "s", "s", "s", "s" } },
1969 #endif
1970
1971 { INDEX_op_bswap16_i32, { "r", "r" } },
1972 { INDEX_op_bswap32_i32, { "r", "r" } },
1973
1974 { INDEX_op_ext8s_i32, { "r", "r" } },
1975 { INDEX_op_ext16s_i32, { "r", "r" } },
1976 { INDEX_op_ext16u_i32, { "r", "r" } },
1977
1978 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1979
1980 { INDEX_op_div_i32, { "r", "r", "r" } },
1981 { INDEX_op_divu_i32, { "r", "r", "r" } },
1982
1983 { INDEX_op_mb, { } },
1984 { -1 },
1985 };
1986
1987 static void tcg_target_init(TCGContext *s)
1988 {
1989 /* Only probe for the platform and capabilities if we havn't already
1990 determined maximum values at compile time. */
1991 #ifndef use_idiv_instructions
1992 {
1993 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
1994 use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
1995 }
1996 #endif
1997 if (__ARM_ARCH < 7) {
1998 const char *pl = (const char *)qemu_getauxval(AT_PLATFORM);
1999 if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
2000 arm_arch = pl[1] - '0';
2001 }
2002 }
2003
2004 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
2005 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
2006 (1 << TCG_REG_R0) |
2007 (1 << TCG_REG_R1) |
2008 (1 << TCG_REG_R2) |
2009 (1 << TCG_REG_R3) |
2010 (1 << TCG_REG_R12) |
2011 (1 << TCG_REG_R14));
2012
2013 tcg_regset_clear(s->reserved_regs);
2014 tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
2015 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
2016 tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
2017
2018 tcg_add_target_add_op_defs(arm_op_defs);
2019 }
2020
2021 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
2022 TCGReg arg1, intptr_t arg2)
2023 {
2024 tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
2025 }
2026
2027 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
2028 TCGReg arg1, intptr_t arg2)
2029 {
2030 tcg_out_st32(s, COND_AL, arg, arg1, arg2);
2031 }
2032
2033 static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
2034 TCGReg base, intptr_t ofs)
2035 {
2036 return false;
2037 }
2038
2039 static inline void tcg_out_mov(TCGContext *s, TCGType type,
2040 TCGReg ret, TCGReg arg)
2041 {
2042 tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
2043 }
2044
2045 static inline void tcg_out_movi(TCGContext *s, TCGType type,
2046 TCGReg ret, tcg_target_long arg)
2047 {
2048 tcg_out_movi32(s, COND_AL, ret, arg);
2049 }
2050
2051 /* Compute frame size via macros, to share between tcg_target_qemu_prologue
2052 and tcg_register_jit. */
2053
2054 #define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long))
2055
2056 #define FRAME_SIZE \
2057 ((PUSH_SIZE \
2058 + TCG_STATIC_CALL_ARGS_SIZE \
2059 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2060 + TCG_TARGET_STACK_ALIGN - 1) \
2061 & -TCG_TARGET_STACK_ALIGN)
2062
2063 static void tcg_target_qemu_prologue(TCGContext *s)
2064 {
2065 int stack_addend;
2066
2067 /* Calling convention requires us to save r4-r11 and lr. */
2068 /* stmdb sp!, { r4 - r11, lr } */
2069 tcg_out32(s, (COND_AL << 28) | 0x092d4ff0);
2070
2071 /* Reserve callee argument and tcg temp space. */
2072 stack_addend = FRAME_SIZE - PUSH_SIZE;
2073
2074 tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK,
2075 TCG_REG_CALL_STACK, stack_addend, 1);
2076 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
2077 CPU_TEMP_BUF_NLONGS * sizeof(long));
2078
2079 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2080
2081 tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
2082 tb_ret_addr = s->code_ptr;
2083
2084 /* Epilogue. We branch here via tb_ret_addr. */
2085 tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK,
2086 TCG_REG_CALL_STACK, stack_addend, 1);
2087
2088 /* ldmia sp!, { r4 - r11, pc } */
2089 tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0);
2090 }
2091
2092 typedef struct {
2093 DebugFrameHeader h;
2094 uint8_t fde_def_cfa[4];
2095 uint8_t fde_reg_ofs[18];
2096 } DebugFrame;
2097
2098 #define ELF_HOST_MACHINE EM_ARM
2099
2100 /* We're expecting a 2 byte uleb128 encoded value. */
2101 QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
2102
2103 static const DebugFrame debug_frame = {
2104 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
2105 .h.cie.id = -1,
2106 .h.cie.version = 1,
2107 .h.cie.code_align = 1,
2108 .h.cie.data_align = 0x7c, /* sleb128 -4 */
2109 .h.cie.return_column = 14,
2110
2111 /* Total FDE size does not include the "len" member. */
2112 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2113
2114 .fde_def_cfa = {
2115 12, 13, /* DW_CFA_def_cfa sp, ... */
2116 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2117 (FRAME_SIZE >> 7)
2118 },
2119 .fde_reg_ofs = {
2120 /* The following must match the stmdb in the prologue. */
2121 0x8e, 1, /* DW_CFA_offset, lr, -4 */
2122 0x8b, 2, /* DW_CFA_offset, r11, -8 */
2123 0x8a, 3, /* DW_CFA_offset, r10, -12 */
2124 0x89, 4, /* DW_CFA_offset, r9, -16 */
2125 0x88, 5, /* DW_CFA_offset, r8, -20 */
2126 0x87, 6, /* DW_CFA_offset, r7, -24 */
2127 0x86, 7, /* DW_CFA_offset, r6, -28 */
2128 0x85, 8, /* DW_CFA_offset, r5, -32 */
2129 0x84, 9, /* DW_CFA_offset, r4, -36 */
2130 }
2131 };
2132
2133 void tcg_register_jit(void *buf, size_t buf_size)
2134 {
2135 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2136 }