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