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