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