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