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