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