tcg-sparc: Tidy check_fit_* tests
[qemu.git] / tcg / sparc / tcg-target.c
blobaf9673f99685abe483de037060340e688764b7a4
1 /*
2 * Tiny Code Generator for QEMU
4 * Copyright (c) 2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
25 #include "tcg-be-null.h"
27 #ifndef NDEBUG
28 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
29 "%g0",
30 "%g1",
31 "%g2",
32 "%g3",
33 "%g4",
34 "%g5",
35 "%g6",
36 "%g7",
37 "%o0",
38 "%o1",
39 "%o2",
40 "%o3",
41 "%o4",
42 "%o5",
43 "%o6",
44 "%o7",
45 "%l0",
46 "%l1",
47 "%l2",
48 "%l3",
49 "%l4",
50 "%l5",
51 "%l6",
52 "%l7",
53 "%i0",
54 "%i1",
55 "%i2",
56 "%i3",
57 "%i4",
58 "%i5",
59 "%i6",
60 "%i7",
62 #endif
64 #ifdef __arch64__
65 # define SPARC64 1
66 #else
67 # define SPARC64 0
68 #endif
70 /* Note that sparcv8plus can only hold 64 bit quantities in %g and %o
71 registers. These are saved manually by the kernel in full 64-bit
72 slots. The %i and %l registers are saved by the register window
73 mechanism, which only allocates space for 32 bits. Given that this
74 window spill/fill can happen on any signal, we must consider the
75 high bits of the %i and %l registers garbage at all times. */
76 #if SPARC64
77 # define ALL_64 0xffffffffu
78 #else
79 # define ALL_64 0xffffu
80 #endif
82 /* Define some temporary registers. T2 is used for constant generation. */
83 #define TCG_REG_T1 TCG_REG_G1
84 #define TCG_REG_T2 TCG_REG_O7
86 #ifdef CONFIG_USE_GUEST_BASE
87 # define TCG_GUEST_BASE_REG TCG_REG_I5
88 #else
89 # define TCG_GUEST_BASE_REG TCG_REG_G0
90 #endif
92 static const int tcg_target_reg_alloc_order[] = {
93 TCG_REG_L0,
94 TCG_REG_L1,
95 TCG_REG_L2,
96 TCG_REG_L3,
97 TCG_REG_L4,
98 TCG_REG_L5,
99 TCG_REG_L6,
100 TCG_REG_L7,
102 TCG_REG_I0,
103 TCG_REG_I1,
104 TCG_REG_I2,
105 TCG_REG_I3,
106 TCG_REG_I4,
107 TCG_REG_I5,
109 TCG_REG_G2,
110 TCG_REG_G3,
111 TCG_REG_G4,
112 TCG_REG_G5,
114 TCG_REG_O0,
115 TCG_REG_O1,
116 TCG_REG_O2,
117 TCG_REG_O3,
118 TCG_REG_O4,
119 TCG_REG_O5,
122 static const int tcg_target_call_iarg_regs[6] = {
123 TCG_REG_O0,
124 TCG_REG_O1,
125 TCG_REG_O2,
126 TCG_REG_O3,
127 TCG_REG_O4,
128 TCG_REG_O5,
131 static const int tcg_target_call_oarg_regs[] = {
132 TCG_REG_O0,
133 TCG_REG_O1,
134 TCG_REG_O2,
135 TCG_REG_O3,
138 #define INSN_OP(x) ((x) << 30)
139 #define INSN_OP2(x) ((x) << 22)
140 #define INSN_OP3(x) ((x) << 19)
141 #define INSN_OPF(x) ((x) << 5)
142 #define INSN_RD(x) ((x) << 25)
143 #define INSN_RS1(x) ((x) << 14)
144 #define INSN_RS2(x) (x)
145 #define INSN_ASI(x) ((x) << 5)
147 #define INSN_IMM10(x) ((1 << 13) | ((x) & 0x3ff))
148 #define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff))
149 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
150 #define INSN_OFF16(x) ((((x) >> 2) & 0x3fff) | ((((x) >> 16) & 3) << 20))
151 #define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
152 #define INSN_COND(x) ((x) << 25)
154 #define COND_N 0x0
155 #define COND_E 0x1
156 #define COND_LE 0x2
157 #define COND_L 0x3
158 #define COND_LEU 0x4
159 #define COND_CS 0x5
160 #define COND_NEG 0x6
161 #define COND_VS 0x7
162 #define COND_A 0x8
163 #define COND_NE 0x9
164 #define COND_G 0xa
165 #define COND_GE 0xb
166 #define COND_GU 0xc
167 #define COND_CC 0xd
168 #define COND_POS 0xe
169 #define COND_VC 0xf
170 #define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2))
172 #define RCOND_Z 1
173 #define RCOND_LEZ 2
174 #define RCOND_LZ 3
175 #define RCOND_NZ 5
176 #define RCOND_GZ 6
177 #define RCOND_GEZ 7
179 #define MOVCC_ICC (1 << 18)
180 #define MOVCC_XCC (1 << 18 | 1 << 12)
182 #define BPCC_ICC 0
183 #define BPCC_XCC (2 << 20)
184 #define BPCC_PT (1 << 19)
185 #define BPCC_PN 0
186 #define BPCC_A (1 << 29)
188 #define BPR_PT BPCC_PT
190 #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
191 #define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
192 #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
193 #define ARITH_ANDN (INSN_OP(2) | INSN_OP3(0x05))
194 #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02))
195 #define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12))
196 #define ARITH_ORN (INSN_OP(2) | INSN_OP3(0x06))
197 #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03))
198 #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04))
199 #define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
200 #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x08))
201 #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
202 #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
203 #define ARITH_SMUL (INSN_OP(2) | INSN_OP3(0x0b))
204 #define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
205 #define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))
206 #define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
207 #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
208 #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))
209 #define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c))
210 #define ARITH_MOVR (INSN_OP(2) | INSN_OP3(0x2f))
212 #define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25))
213 #define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26))
214 #define SHIFT_SRA (INSN_OP(2) | INSN_OP3(0x27))
216 #define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))
217 #define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
218 #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
220 #define RDY (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0))
221 #define WRY (INSN_OP(2) | INSN_OP3(0x30) | INSN_RD(0))
222 #define JMPL (INSN_OP(2) | INSN_OP3(0x38))
223 #define RETURN (INSN_OP(2) | INSN_OP3(0x39))
224 #define SAVE (INSN_OP(2) | INSN_OP3(0x3c))
225 #define RESTORE (INSN_OP(2) | INSN_OP3(0x3d))
226 #define SETHI (INSN_OP(0) | INSN_OP2(0x4))
227 #define CALL INSN_OP(1)
228 #define LDUB (INSN_OP(3) | INSN_OP3(0x01))
229 #define LDSB (INSN_OP(3) | INSN_OP3(0x09))
230 #define LDUH (INSN_OP(3) | INSN_OP3(0x02))
231 #define LDSH (INSN_OP(3) | INSN_OP3(0x0a))
232 #define LDUW (INSN_OP(3) | INSN_OP3(0x00))
233 #define LDSW (INSN_OP(3) | INSN_OP3(0x08))
234 #define LDX (INSN_OP(3) | INSN_OP3(0x0b))
235 #define STB (INSN_OP(3) | INSN_OP3(0x05))
236 #define STH (INSN_OP(3) | INSN_OP3(0x06))
237 #define STW (INSN_OP(3) | INSN_OP3(0x04))
238 #define STX (INSN_OP(3) | INSN_OP3(0x0e))
239 #define LDUBA (INSN_OP(3) | INSN_OP3(0x11))
240 #define LDSBA (INSN_OP(3) | INSN_OP3(0x19))
241 #define LDUHA (INSN_OP(3) | INSN_OP3(0x12))
242 #define LDSHA (INSN_OP(3) | INSN_OP3(0x1a))
243 #define LDUWA (INSN_OP(3) | INSN_OP3(0x10))
244 #define LDSWA (INSN_OP(3) | INSN_OP3(0x18))
245 #define LDXA (INSN_OP(3) | INSN_OP3(0x1b))
246 #define STBA (INSN_OP(3) | INSN_OP3(0x15))
247 #define STHA (INSN_OP(3) | INSN_OP3(0x16))
248 #define STWA (INSN_OP(3) | INSN_OP3(0x14))
249 #define STXA (INSN_OP(3) | INSN_OP3(0x1e))
251 #ifndef ASI_PRIMARY_LITTLE
252 #define ASI_PRIMARY_LITTLE 0x88
253 #endif
255 #define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
256 #define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
257 #define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
258 #define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
259 #define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE))
261 #define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE))
262 #define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
263 #define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
265 static inline int check_fit_i64(int64_t val, unsigned int bits)
267 return val == sextract64(val, 0, bits);
270 static inline int check_fit_i32(int32_t val, unsigned int bits)
272 return val == sextract32(val, 0, bits);
275 #define check_fit_tl check_fit_i64
276 #if SPARC64
277 # define check_fit_ptr check_fit_i64
278 #else
279 # define check_fit_ptr check_fit_i32
280 #endif
282 static void patch_reloc(uint8_t *code_ptr, int type,
283 intptr_t value, intptr_t addend)
285 uint32_t insn;
286 value += addend;
287 switch (type) {
288 case R_SPARC_32:
289 if (value != (uint32_t)value) {
290 tcg_abort();
292 *(uint32_t *)code_ptr = value;
293 break;
294 case R_SPARC_WDISP16:
295 value -= (intptr_t)code_ptr;
296 if (!check_fit_ptr(value >> 2, 16)) {
297 tcg_abort();
299 insn = *(uint32_t *)code_ptr;
300 insn &= ~INSN_OFF16(-1);
301 insn |= INSN_OFF16(value);
302 *(uint32_t *)code_ptr = insn;
303 break;
304 case R_SPARC_WDISP19:
305 value -= (intptr_t)code_ptr;
306 if (!check_fit_ptr(value >> 2, 19)) {
307 tcg_abort();
309 insn = *(uint32_t *)code_ptr;
310 insn &= ~INSN_OFF19(-1);
311 insn |= INSN_OFF19(value);
312 *(uint32_t *)code_ptr = insn;
313 break;
314 default:
315 tcg_abort();
319 /* parse target specific constraints */
320 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
322 const char *ct_str;
324 ct_str = *pct_str;
325 switch (ct_str[0]) {
326 case 'r':
327 ct->ct |= TCG_CT_REG;
328 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
329 break;
330 case 'R':
331 ct->ct |= TCG_CT_REG;
332 tcg_regset_set32(ct->u.regs, 0, ALL_64);
333 break;
334 case 'A': /* qemu_ld/st address constraint */
335 ct->ct |= TCG_CT_REG;
336 tcg_regset_set32(ct->u.regs, 0,
337 TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff);
338 reserve_helpers:
339 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
340 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
341 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
342 break;
343 case 's': /* qemu_st data 32-bit constraint */
344 ct->ct |= TCG_CT_REG;
345 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
346 goto reserve_helpers;
347 case 'S': /* qemu_st data 64-bit constraint */
348 ct->ct |= TCG_CT_REG;
349 tcg_regset_set32(ct->u.regs, 0, ALL_64);
350 goto reserve_helpers;
351 case 'I':
352 ct->ct |= TCG_CT_CONST_S11;
353 break;
354 case 'J':
355 ct->ct |= TCG_CT_CONST_S13;
356 break;
357 case 'Z':
358 ct->ct |= TCG_CT_CONST_ZERO;
359 break;
360 default:
361 return -1;
363 ct_str++;
364 *pct_str = ct_str;
365 return 0;
368 /* test if a constant matches the constraint */
369 static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
370 const TCGArgConstraint *arg_ct)
372 int ct = arg_ct->ct;
374 if (ct & TCG_CT_CONST) {
375 return 1;
378 if (type == TCG_TYPE_I32) {
379 val = (int32_t)val;
382 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
383 return 1;
384 } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) {
385 return 1;
386 } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) {
387 return 1;
388 } else {
389 return 0;
393 static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
394 int op)
396 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
397 INSN_RS2(rs2));
400 static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1,
401 uint32_t offset, int op)
403 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
404 INSN_IMM13(offset));
407 static void tcg_out_arithc(TCGContext *s, int rd, int rs1,
408 int val2, int val2const, int op)
410 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1)
411 | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
414 static inline void tcg_out_mov(TCGContext *s, TCGType type,
415 TCGReg ret, TCGReg arg)
417 if (ret != arg) {
418 tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
422 static inline void tcg_out_sethi(TCGContext *s, int ret, uint32_t arg)
424 tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10));
427 static inline void tcg_out_movi_imm13(TCGContext *s, int ret, uint32_t arg)
429 tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR);
432 static void tcg_out_movi(TCGContext *s, TCGType type,
433 TCGReg ret, tcg_target_long arg)
435 tcg_target_long hi, lo = (int32_t)arg;
437 /* A 13-bit constant sign-extended to 64-bits. */
438 if (check_fit_tl(arg, 13)) {
439 tcg_out_movi_imm13(s, ret, arg);
440 return;
443 /* A 32-bit constant, or 32-bit zero-extended to 64-bits. */
444 if (type == TCG_TYPE_I32 || arg == (uint32_t)arg) {
445 tcg_out_sethi(s, ret, arg);
446 if (arg & 0x3ff) {
447 tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
449 return;
452 /* A 32-bit constant sign-extended to 64-bits. */
453 if (arg == lo) {
454 tcg_out_sethi(s, ret, ~arg);
455 tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
456 return;
459 /* A 64-bit constant decomposed into 2 32-bit pieces. */
460 if (check_fit_i32(lo, 13)) {
461 hi = (arg - lo) >> 32;
462 tcg_out_movi(s, TCG_TYPE_I32, ret, hi);
463 tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
464 tcg_out_arithi(s, ret, ret, lo, ARITH_ADD);
465 } else {
466 hi = arg >> 32;
467 tcg_out_movi(s, TCG_TYPE_I32, ret, hi);
468 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T2, lo);
469 tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
470 tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR);
474 static inline void tcg_out_ldst_rr(TCGContext *s, int data, int a1,
475 int a2, int op)
477 tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2));
480 static inline void tcg_out_ldst(TCGContext *s, int ret, int addr,
481 int offset, int op)
483 if (check_fit_ptr(offset, 13)) {
484 tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
485 INSN_IMM13(offset));
486 } else {
487 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, offset);
488 tcg_out_ldst_rr(s, ret, addr, TCG_REG_T1, op);
492 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
493 TCGReg arg1, intptr_t arg2)
495 tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX));
498 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
499 TCGReg arg1, intptr_t arg2)
501 tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
504 static inline void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, uintptr_t arg)
506 TCGReg base = TCG_REG_G0;
507 if (!check_fit_ptr(arg, 10)) {
508 tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
509 base = ret;
511 tcg_out_ld(s, TCG_TYPE_PTR, ret, base, arg & 0x3ff);
514 static inline void tcg_out_sety(TCGContext *s, int rs)
516 tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
519 static inline void tcg_out_rdy(TCGContext *s, int rd)
521 tcg_out32(s, RDY | INSN_RD(rd));
524 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
526 if (val != 0) {
527 if (check_fit_tl(val, 13))
528 tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
529 else {
530 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, val);
531 tcg_out_arith(s, reg, reg, TCG_REG_T1, ARITH_ADD);
536 static void tcg_out_div32(TCGContext *s, int rd, int rs1,
537 int val2, int val2const, int uns)
539 /* Load Y with the sign/zero extension of RS1 to 64-bits. */
540 if (uns) {
541 tcg_out_sety(s, TCG_REG_G0);
542 } else {
543 tcg_out_arithi(s, TCG_REG_T1, rs1, 31, SHIFT_SRA);
544 tcg_out_sety(s, TCG_REG_T1);
547 tcg_out_arithc(s, rd, rs1, val2, val2const,
548 uns ? ARITH_UDIV : ARITH_SDIV);
551 static inline void tcg_out_nop(TCGContext *s)
553 tcg_out_sethi(s, TCG_REG_G0, 0);
556 static const uint8_t tcg_cond_to_bcond[] = {
557 [TCG_COND_EQ] = COND_E,
558 [TCG_COND_NE] = COND_NE,
559 [TCG_COND_LT] = COND_L,
560 [TCG_COND_GE] = COND_GE,
561 [TCG_COND_LE] = COND_LE,
562 [TCG_COND_GT] = COND_G,
563 [TCG_COND_LTU] = COND_CS,
564 [TCG_COND_GEU] = COND_CC,
565 [TCG_COND_LEU] = COND_LEU,
566 [TCG_COND_GTU] = COND_GU,
569 static const uint8_t tcg_cond_to_rcond[] = {
570 [TCG_COND_EQ] = RCOND_Z,
571 [TCG_COND_NE] = RCOND_NZ,
572 [TCG_COND_LT] = RCOND_LZ,
573 [TCG_COND_GT] = RCOND_GZ,
574 [TCG_COND_LE] = RCOND_LEZ,
575 [TCG_COND_GE] = RCOND_GEZ
578 static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19)
580 tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19);
583 static void tcg_out_bpcc(TCGContext *s, int scond, int flags, int label)
585 TCGLabel *l = &s->labels[label];
586 int off19;
588 if (l->has_value) {
589 off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
590 } else {
591 /* Make sure to preserve destinations during retranslation. */
592 off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
593 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label, 0);
595 tcg_out_bpcc0(s, scond, flags, off19);
598 static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const)
600 tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
603 static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGArg arg1,
604 TCGArg arg2, int const_arg2, int label)
606 tcg_out_cmp(s, arg1, arg2, const_arg2);
607 tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, label);
608 tcg_out_nop(s);
611 static void tcg_out_movcc(TCGContext *s, TCGCond cond, int cc, TCGArg ret,
612 TCGArg v1, int v1const)
614 tcg_out32(s, ARITH_MOVCC | cc | INSN_RD(ret)
615 | INSN_RS1(tcg_cond_to_bcond[cond])
616 | (v1const ? INSN_IMM11(v1) : INSN_RS2(v1)));
619 static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
620 TCGArg c1, TCGArg c2, int c2const,
621 TCGArg v1, int v1const)
623 tcg_out_cmp(s, c1, c2, c2const);
624 tcg_out_movcc(s, cond, MOVCC_ICC, ret, v1, v1const);
627 static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGArg arg1,
628 TCGArg arg2, int const_arg2, int label)
630 /* For 64-bit signed comparisons vs zero, we can avoid the compare. */
631 if (arg2 == 0 && !is_unsigned_cond(cond)) {
632 TCGLabel *l = &s->labels[label];
633 int off16;
635 if (l->has_value) {
636 off16 = INSN_OFF16(l->u.value - (unsigned long)s->code_ptr);
637 } else {
638 /* Make sure to preserve destinations during retranslation. */
639 off16 = *(uint32_t *)s->code_ptr & INSN_OFF16(-1);
640 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, label, 0);
642 tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
643 | INSN_COND(tcg_cond_to_rcond[cond]) | off16);
644 } else {
645 tcg_out_cmp(s, arg1, arg2, const_arg2);
646 tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label);
648 tcg_out_nop(s);
651 static void tcg_out_movr(TCGContext *s, TCGCond cond, TCGArg ret, TCGArg c1,
652 TCGArg v1, int v1const)
654 tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1)
655 | (tcg_cond_to_rcond[cond] << 10)
656 | (v1const ? INSN_IMM10(v1) : INSN_RS2(v1)));
659 static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGArg ret,
660 TCGArg c1, TCGArg c2, int c2const,
661 TCGArg v1, int v1const)
663 /* For 64-bit signed comparisons vs zero, we can avoid the compare.
664 Note that the immediate range is one bit smaller, so we must check
665 for that as well. */
666 if (c2 == 0 && !is_unsigned_cond(cond)
667 && (!v1const || check_fit_tl(v1, 10))) {
668 tcg_out_movr(s, cond, ret, c1, v1, v1const);
669 } else {
670 tcg_out_cmp(s, c1, c2, c2const);
671 tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const);
675 static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
676 TCGArg c1, TCGArg c2, int c2const)
678 /* For 32-bit comparisons, we can play games with ADDX/SUBX. */
679 switch (cond) {
680 case TCG_COND_LTU:
681 case TCG_COND_GEU:
682 /* The result of the comparison is in the carry bit. */
683 break;
685 case TCG_COND_EQ:
686 case TCG_COND_NE:
687 /* For equality, we can transform to inequality vs zero. */
688 if (c2 != 0) {
689 tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR);
691 c1 = TCG_REG_G0, c2 = ret, c2const = 0;
692 cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU);
693 break;
695 case TCG_COND_GTU:
696 case TCG_COND_LEU:
697 /* If we don't need to load a constant into a register, we can
698 swap the operands on GTU/LEU. There's no benefit to loading
699 the constant into a temporary register. */
700 if (!c2const || c2 == 0) {
701 TCGArg t = c1;
702 c1 = c2;
703 c2 = t;
704 c2const = 0;
705 cond = tcg_swap_cond(cond);
706 break;
708 /* FALLTHRU */
710 default:
711 tcg_out_cmp(s, c1, c2, c2const);
712 tcg_out_movi_imm13(s, ret, 0);
713 tcg_out_movcc(s, cond, MOVCC_ICC, ret, 1, 1);
714 return;
717 tcg_out_cmp(s, c1, c2, c2const);
718 if (cond == TCG_COND_LTU) {
719 tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDX);
720 } else {
721 tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBX);
725 static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGArg ret,
726 TCGArg c1, TCGArg c2, int c2const)
728 /* For 64-bit signed comparisons vs zero, we can avoid the compare
729 if the input does not overlap the output. */
730 if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) {
731 tcg_out_movi_imm13(s, ret, 0);
732 tcg_out_movr(s, cond, ret, c1, 1, 1);
733 } else {
734 tcg_out_cmp(s, c1, c2, c2const);
735 tcg_out_movi_imm13(s, ret, 0);
736 tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1);
740 static void tcg_out_addsub2(TCGContext *s, TCGArg rl, TCGArg rh,
741 TCGArg al, TCGArg ah, TCGArg bl, int blconst,
742 TCGArg bh, int bhconst, int opl, int oph)
744 TCGArg tmp = TCG_REG_T1;
746 /* Note that the low parts are fully consumed before tmp is set. */
747 if (rl != ah && (bhconst || rl != bh)) {
748 tmp = rl;
751 tcg_out_arithc(s, tmp, al, bl, blconst, opl);
752 tcg_out_arithc(s, rh, ah, bh, bhconst, oph);
753 tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
756 static inline void tcg_out_calli(TCGContext *s, uintptr_t dest)
758 intptr_t disp = dest - (uintptr_t)s->code_ptr;
760 if (disp == (int32_t)disp) {
761 tcg_out32(s, CALL | (uint32_t)disp >> 2);
762 } else {
763 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, dest & ~0xfff);
764 tcg_out_arithi(s, TCG_REG_O7, TCG_REG_T1, dest & 0xfff, JMPL);
768 #ifdef CONFIG_SOFTMMU
769 static uintptr_t qemu_ld_trampoline[16];
770 static uintptr_t qemu_st_trampoline[16];
772 static void build_trampolines(TCGContext *s)
774 static uintptr_t const qemu_ld_helpers[16] = {
775 [MO_UB] = (uintptr_t)helper_ret_ldub_mmu,
776 [MO_SB] = (uintptr_t)helper_ret_ldsb_mmu,
777 [MO_LEUW] = (uintptr_t)helper_le_lduw_mmu,
778 [MO_LESW] = (uintptr_t)helper_le_ldsw_mmu,
779 [MO_LEUL] = (uintptr_t)helper_le_ldul_mmu,
780 [MO_LEQ] = (uintptr_t)helper_le_ldq_mmu,
781 [MO_BEUW] = (uintptr_t)helper_be_lduw_mmu,
782 [MO_BESW] = (uintptr_t)helper_be_ldsw_mmu,
783 [MO_BEUL] = (uintptr_t)helper_be_ldul_mmu,
784 [MO_BEQ] = (uintptr_t)helper_be_ldq_mmu,
786 static uintptr_t const qemu_st_helpers[16] = {
787 [MO_UB] = (uintptr_t)helper_ret_stb_mmu,
788 [MO_LEUW] = (uintptr_t)helper_le_stw_mmu,
789 [MO_LEUL] = (uintptr_t)helper_le_stl_mmu,
790 [MO_LEQ] = (uintptr_t)helper_le_stq_mmu,
791 [MO_BEUW] = (uintptr_t)helper_be_stw_mmu,
792 [MO_BEUL] = (uintptr_t)helper_be_stl_mmu,
793 [MO_BEQ] = (uintptr_t)helper_be_stq_mmu,
796 int i;
797 TCGReg ra;
798 uintptr_t tramp;
800 for (i = 0; i < 16; ++i) {
801 if (qemu_ld_helpers[i] == 0) {
802 continue;
805 /* May as well align the trampoline. */
806 tramp = (uintptr_t)s->code_ptr;
807 while (tramp & 15) {
808 tcg_out_nop(s);
809 tramp += 4;
811 qemu_ld_trampoline[i] = tramp;
813 if (SPARC64 || TARGET_LONG_BITS == 32) {
814 ra = TCG_REG_O3;
815 } else {
816 /* Install the high part of the address. */
817 tcg_out_arithi(s, TCG_REG_O1, TCG_REG_O2, 32, SHIFT_SRLX);
818 ra = TCG_REG_O4;
821 /* Set the retaddr operand. */
822 tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
823 /* Set the env operand. */
824 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
825 /* Tail call. */
826 tcg_out_calli(s, qemu_ld_helpers[i]);
827 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
830 for (i = 0; i < 16; ++i) {
831 if (qemu_st_helpers[i] == 0) {
832 continue;
835 /* May as well align the trampoline. */
836 tramp = (uintptr_t)s->code_ptr;
837 while (tramp & 15) {
838 tcg_out_nop(s);
839 tramp += 4;
841 qemu_st_trampoline[i] = tramp;
843 if (SPARC64) {
844 ra = TCG_REG_O4;
845 } else {
846 ra = TCG_REG_O1;
847 if (TARGET_LONG_BITS == 64) {
848 /* Install the high part of the address. */
849 tcg_out_arithi(s, ra, ra + 1, 32, SHIFT_SRLX);
850 ra += 2;
851 } else {
852 ra += 1;
854 if ((i & MO_SIZE) == MO_64) {
855 /* Install the high part of the data. */
856 tcg_out_arithi(s, ra, ra + 1, 32, SHIFT_SRLX);
857 ra += 2;
858 } else {
859 ra += 1;
861 /* Skip the mem_index argument. */
862 ra += 1;
865 /* Set the retaddr operand. */
866 if (ra >= TCG_REG_O6) {
867 tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_O7, TCG_REG_CALL_STACK,
868 TCG_TARGET_CALL_STACK_OFFSET);
869 ra = TCG_REG_G1;
871 tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
872 /* Set the env operand. */
873 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
874 /* Tail call. */
875 tcg_out_calli(s, qemu_st_helpers[i]);
876 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
879 #endif
881 /* Generate global QEMU prologue and epilogue code */
882 static void tcg_target_qemu_prologue(TCGContext *s)
884 int tmp_buf_size, frame_size;
886 /* The TCG temp buffer is at the top of the frame, immediately
887 below the frame pointer. */
888 tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long);
889 tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_STACK_BIAS - tmp_buf_size,
890 tmp_buf_size);
892 /* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
893 otherwise the minimal frame usable by callees. */
894 frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS;
895 frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size;
896 frame_size += TCG_TARGET_STACK_ALIGN - 1;
897 frame_size &= -TCG_TARGET_STACK_ALIGN;
898 tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
899 INSN_IMM13(-frame_size));
901 #ifdef CONFIG_USE_GUEST_BASE
902 if (GUEST_BASE != 0) {
903 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
904 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
906 #endif
908 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL);
909 /* delay slot */
910 tcg_out_nop(s);
912 /* No epilogue required. We issue ret + restore directly in the TB. */
914 #ifdef CONFIG_SOFTMMU
915 build_trampolines(s);
916 #endif
919 #if defined(CONFIG_SOFTMMU)
920 /* Perform the TLB load and compare.
922 Inputs:
923 ADDRLO and ADDRHI contain the possible two parts of the address.
925 MEM_INDEX and S_BITS are the memory context and log2 size of the load.
927 WHICH is the offset into the CPUTLBEntry structure of the slot to read.
928 This should be offsetof addr_read or addr_write.
930 The result of the TLB comparison is in %[ix]cc. The sanitized address
931 is in the returned register, maybe %o0. The TLB addend is in %o1. */
933 static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, int mem_index,
934 TCGMemOp s_bits, int which)
936 const TCGReg r0 = TCG_REG_O0;
937 const TCGReg r1 = TCG_REG_O1;
938 const TCGReg r2 = TCG_REG_O2;
939 int tlb_ofs;
941 /* Shift the page number down. */
942 tcg_out_arithi(s, r1, addr, TARGET_PAGE_BITS, SHIFT_SRL);
944 /* Mask out the page offset, except for the required alignment. */
945 tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_T1,
946 TARGET_PAGE_MASK | ((1 << s_bits) - 1));
948 /* Mask the tlb index. */
949 tcg_out_arithi(s, r1, r1, CPU_TLB_SIZE - 1, ARITH_AND);
951 /* Mask page, part 2. */
952 tcg_out_arith(s, r0, addr, TCG_REG_T1, ARITH_AND);
954 /* Shift the tlb index into place. */
955 tcg_out_arithi(s, r1, r1, CPU_TLB_ENTRY_BITS, SHIFT_SLL);
957 /* Relative to the current ENV. */
958 tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD);
960 /* Find a base address that can load both tlb comparator and addend. */
961 tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
962 if (!check_fit_ptr(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
963 tcg_out_addi(s, r1, tlb_ofs & ~0x3ff);
964 tlb_ofs &= 0x3ff;
967 /* Load the tlb comparator and the addend. */
968 tcg_out_ld(s, TCG_TYPE_TL, r2, r1, tlb_ofs + which);
969 tcg_out_ld(s, TCG_TYPE_PTR, r1, r1, tlb_ofs+offsetof(CPUTLBEntry, addend));
971 /* subcc arg0, arg2, %g0 */
972 tcg_out_cmp(s, r0, r2, 0);
974 /* If the guest address must be zero-extended, do so now. */
975 if (SPARC64 && TARGET_LONG_BITS == 32) {
976 tcg_out_arithi(s, r0, addr, 0, SHIFT_SRL);
977 return r0;
979 return addr;
981 #endif /* CONFIG_SOFTMMU */
983 static const int qemu_ld_opc[16] = {
984 [MO_UB] = LDUB,
985 [MO_SB] = LDSB,
987 [MO_BEUW] = LDUH,
988 [MO_BESW] = LDSH,
989 [MO_BEUL] = LDUW,
990 [MO_BESL] = LDSW,
991 [MO_BEQ] = LDX,
993 [MO_LEUW] = LDUH_LE,
994 [MO_LESW] = LDSH_LE,
995 [MO_LEUL] = LDUW_LE,
996 [MO_LESL] = LDSW_LE,
997 [MO_LEQ] = LDX_LE,
1000 static const int qemu_st_opc[16] = {
1001 [MO_UB] = STB,
1003 [MO_BEUW] = STH,
1004 [MO_BEUL] = STW,
1005 [MO_BEQ] = STX,
1007 [MO_LEUW] = STH_LE,
1008 [MO_LEUL] = STW_LE,
1009 [MO_LEQ] = STX_LE,
1012 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
1013 TCGMemOp memop, int memi, bool is_64)
1015 #ifdef CONFIG_SOFTMMU
1016 TCGMemOp s_bits = memop & MO_SIZE;
1017 TCGReg addrz, param;
1018 uintptr_t func;
1019 uint32_t *label_ptr;
1021 addrz = tcg_out_tlb_load(s, addr, memi, s_bits,
1022 offsetof(CPUTLBEntry, addr_read));
1024 /* The fast path is exactly one insn. Thus we can perform the
1025 entire TLB Hit in the (annulled) delay slot of the branch
1026 over the TLB Miss case. */
1028 /* beq,a,pt %[xi]cc, label0 */
1029 label_ptr = (uint32_t *)s->code_ptr;
1030 tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
1031 | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
1032 /* delay slot */
1033 tcg_out_ldst_rr(s, data, addrz, TCG_REG_O1, qemu_ld_opc[memop]);
1035 /* TLB Miss. */
1037 param = TCG_REG_O1;
1038 if (!SPARC64 && TARGET_LONG_BITS == 64) {
1039 /* Skip the high-part; we'll perform the extract in the trampoline. */
1040 param++;
1042 tcg_out_mov(s, TCG_TYPE_REG, param++, addr);
1044 /* We use the helpers to extend SB and SW data, leaving the case
1045 of SL needing explicit extending below. */
1046 if ((memop & ~MO_BSWAP) == MO_SL) {
1047 func = qemu_ld_trampoline[memop & ~MO_SIGN];
1048 } else {
1049 func = qemu_ld_trampoline[memop];
1051 assert(func != 0);
1052 tcg_out_calli(s, func);
1053 /* delay slot */
1054 tcg_out_movi(s, TCG_TYPE_I32, param, memi);
1056 /* Recall that all of the helpers return 64-bit results.
1057 Which complicates things for sparcv8plus. */
1058 if (SPARC64) {
1059 /* We let the helper sign-extend SB and SW, but leave SL for here. */
1060 if (is_64 && (memop & ~MO_BSWAP) == MO_SL) {
1061 tcg_out_arithi(s, data, TCG_REG_O0, 0, SHIFT_SRA);
1062 } else {
1063 tcg_out_mov(s, TCG_TYPE_REG, data, TCG_REG_O0);
1065 } else {
1066 if (s_bits == MO_64) {
1067 tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, 32, SHIFT_SLLX);
1068 tcg_out_arithi(s, TCG_REG_O1, TCG_REG_O1, 0, SHIFT_SRL);
1069 tcg_out_arith(s, data, TCG_REG_O0, TCG_REG_O1, ARITH_OR);
1070 } else if (is_64) {
1071 /* Re-extend from 32-bit rather than reassembling when we
1072 know the high register must be an extension. */
1073 tcg_out_arithi(s, data, TCG_REG_O1, 0,
1074 memop & MO_SIGN ? SHIFT_SRA : SHIFT_SRL);
1075 } else {
1076 tcg_out_mov(s, TCG_TYPE_I32, data, TCG_REG_O1);
1080 *label_ptr |= INSN_OFF19((uintptr_t)s->code_ptr - (uintptr_t)label_ptr);
1081 #else
1082 if (SPARC64 && TARGET_LONG_BITS == 32) {
1083 tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
1084 addr = TCG_REG_T1;
1086 tcg_out_ldst_rr(s, data, addr,
1087 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1088 qemu_ld_opc[memop]);
1089 #endif /* CONFIG_SOFTMMU */
1092 static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
1093 TCGMemOp memop, int memi)
1095 #ifdef CONFIG_SOFTMMU
1096 TCGMemOp s_bits = memop & MO_SIZE;
1097 TCGReg addrz, param;
1098 uintptr_t func;
1099 uint32_t *label_ptr;
1101 addrz = tcg_out_tlb_load(s, addr, memi, s_bits,
1102 offsetof(CPUTLBEntry, addr_write));
1104 /* The fast path is exactly one insn. Thus we can perform the entire
1105 TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
1106 /* beq,a,pt %[xi]cc, label0 */
1107 label_ptr = (uint32_t *)s->code_ptr;
1108 tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
1109 | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
1110 /* delay slot */
1111 tcg_out_ldst_rr(s, data, addrz, TCG_REG_O1, qemu_st_opc[memop]);
1113 /* TLB Miss. */
1115 param = TCG_REG_O1;
1116 if (!SPARC64 && TARGET_LONG_BITS == 64) {
1117 /* Skip the high-part; we'll perform the extract in the trampoline. */
1118 param++;
1120 tcg_out_mov(s, TCG_TYPE_REG, param++, addr);
1121 if (!SPARC64 && s_bits == MO_64) {
1122 /* Skip the high-part; we'll perform the extract in the trampoline. */
1123 param++;
1125 tcg_out_mov(s, TCG_TYPE_REG, param++, data);
1127 func = qemu_st_trampoline[memop];
1128 assert(func != 0);
1129 tcg_out_calli(s, func);
1130 /* delay slot */
1131 tcg_out_movi(s, TCG_TYPE_REG, param, memi);
1133 *label_ptr |= INSN_OFF19((uintptr_t)s->code_ptr - (uintptr_t)label_ptr);
1134 #else
1135 if (SPARC64 && TARGET_LONG_BITS == 32) {
1136 tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
1137 addr = TCG_REG_T1;
1139 tcg_out_ldst_rr(s, data, addr,
1140 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1141 qemu_st_opc[memop]);
1142 #endif /* CONFIG_SOFTMMU */
1145 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
1146 const int *const_args)
1148 int c;
1150 switch (opc) {
1151 case INDEX_op_exit_tb:
1152 if (check_fit_ptr(args[0], 13)) {
1153 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
1154 tcg_out_movi_imm13(s, TCG_REG_O0, args[0]);
1155 } else {
1156 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0] & ~0x3ff);
1157 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
1158 tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0,
1159 args[0] & 0x3ff, ARITH_OR);
1161 break;
1162 case INDEX_op_goto_tb:
1163 if (s->tb_jmp_offset) {
1164 /* direct jump method */
1165 uint32_t old_insn = *(uint32_t *)s->code_ptr;
1166 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1167 /* Make sure to preserve links during retranslation. */
1168 tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1)));
1169 } else {
1170 /* indirect jump method */
1171 tcg_out_ld_ptr(s, TCG_REG_T1, (uintptr_t)(s->tb_next + args[0]));
1172 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_T1, 0, JMPL);
1174 tcg_out_nop(s);
1175 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1176 break;
1177 case INDEX_op_call:
1178 if (const_args[0]) {
1179 tcg_out_calli(s, args[0]);
1180 } else {
1181 tcg_out_arithi(s, TCG_REG_O7, args[0], 0, JMPL);
1183 /* delay slot */
1184 tcg_out_nop(s);
1185 break;
1186 case INDEX_op_br:
1187 tcg_out_bpcc(s, COND_A, BPCC_PT, args[0]);
1188 tcg_out_nop(s);
1189 break;
1190 case INDEX_op_movi_i32:
1191 tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
1192 break;
1194 #define OP_32_64(x) \
1195 glue(glue(case INDEX_op_, x), _i32): \
1196 glue(glue(case INDEX_op_, x), _i64)
1198 OP_32_64(ld8u):
1199 tcg_out_ldst(s, args[0], args[1], args[2], LDUB);
1200 break;
1201 OP_32_64(ld8s):
1202 tcg_out_ldst(s, args[0], args[1], args[2], LDSB);
1203 break;
1204 OP_32_64(ld16u):
1205 tcg_out_ldst(s, args[0], args[1], args[2], LDUH);
1206 break;
1207 OP_32_64(ld16s):
1208 tcg_out_ldst(s, args[0], args[1], args[2], LDSH);
1209 break;
1210 case INDEX_op_ld_i32:
1211 case INDEX_op_ld32u_i64:
1212 tcg_out_ldst(s, args[0], args[1], args[2], LDUW);
1213 break;
1214 OP_32_64(st8):
1215 tcg_out_ldst(s, args[0], args[1], args[2], STB);
1216 break;
1217 OP_32_64(st16):
1218 tcg_out_ldst(s, args[0], args[1], args[2], STH);
1219 break;
1220 case INDEX_op_st_i32:
1221 case INDEX_op_st32_i64:
1222 tcg_out_ldst(s, args[0], args[1], args[2], STW);
1223 break;
1224 OP_32_64(add):
1225 c = ARITH_ADD;
1226 goto gen_arith;
1227 OP_32_64(sub):
1228 c = ARITH_SUB;
1229 goto gen_arith;
1230 OP_32_64(and):
1231 c = ARITH_AND;
1232 goto gen_arith;
1233 OP_32_64(andc):
1234 c = ARITH_ANDN;
1235 goto gen_arith;
1236 OP_32_64(or):
1237 c = ARITH_OR;
1238 goto gen_arith;
1239 OP_32_64(orc):
1240 c = ARITH_ORN;
1241 goto gen_arith;
1242 OP_32_64(xor):
1243 c = ARITH_XOR;
1244 goto gen_arith;
1245 case INDEX_op_shl_i32:
1246 c = SHIFT_SLL;
1247 do_shift32:
1248 /* Limit immediate shift count lest we create an illegal insn. */
1249 tcg_out_arithc(s, args[0], args[1], args[2] & 31, const_args[2], c);
1250 break;
1251 case INDEX_op_shr_i32:
1252 c = SHIFT_SRL;
1253 goto do_shift32;
1254 case INDEX_op_sar_i32:
1255 c = SHIFT_SRA;
1256 goto do_shift32;
1257 case INDEX_op_mul_i32:
1258 c = ARITH_UMUL;
1259 goto gen_arith;
1261 OP_32_64(neg):
1262 c = ARITH_SUB;
1263 goto gen_arith1;
1264 OP_32_64(not):
1265 c = ARITH_ORN;
1266 goto gen_arith1;
1268 case INDEX_op_div_i32:
1269 tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 0);
1270 break;
1271 case INDEX_op_divu_i32:
1272 tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 1);
1273 break;
1275 case INDEX_op_brcond_i32:
1276 tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
1277 args[3]);
1278 break;
1279 case INDEX_op_setcond_i32:
1280 tcg_out_setcond_i32(s, args[3], args[0], args[1],
1281 args[2], const_args[2]);
1282 break;
1283 case INDEX_op_movcond_i32:
1284 tcg_out_movcond_i32(s, args[5], args[0], args[1],
1285 args[2], const_args[2], args[3], const_args[3]);
1286 break;
1288 case INDEX_op_add2_i32:
1289 tcg_out_addsub2(s, args[0], args[1], args[2], args[3],
1290 args[4], const_args[4], args[5], const_args[5],
1291 ARITH_ADDCC, ARITH_ADDX);
1292 break;
1293 case INDEX_op_sub2_i32:
1294 tcg_out_addsub2(s, args[0], args[1], args[2], args[3],
1295 args[4], const_args[4], args[5], const_args[5],
1296 ARITH_SUBCC, ARITH_SUBX);
1297 break;
1298 case INDEX_op_mulu2_i32:
1299 c = ARITH_UMUL;
1300 goto do_mul2;
1301 case INDEX_op_muls2_i32:
1302 c = ARITH_SMUL;
1303 do_mul2:
1304 /* The 32-bit multiply insns produce a full 64-bit result. If the
1305 destination register can hold it, we can avoid the slower RDY. */
1306 tcg_out_arithc(s, args[0], args[2], args[3], const_args[3], c);
1307 if (SPARC64 || args[0] <= TCG_REG_O7) {
1308 tcg_out_arithi(s, args[1], args[0], 32, SHIFT_SRLX);
1309 } else {
1310 tcg_out_rdy(s, args[1]);
1312 break;
1314 case INDEX_op_qemu_ld_i32:
1315 tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3], false);
1316 break;
1317 case INDEX_op_qemu_ld_i64:
1318 tcg_out_qemu_ld(s, args[0], args[1], args[2], args[3], true);
1319 break;
1320 case INDEX_op_qemu_st_i32:
1321 tcg_out_qemu_st(s, args[0], args[1], args[2], args[3]);
1322 break;
1323 case INDEX_op_qemu_st_i64:
1324 tcg_out_qemu_st(s, args[0], args[1], args[2], args[3]);
1325 break;
1327 case INDEX_op_movi_i64:
1328 tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
1329 break;
1330 case INDEX_op_ld32s_i64:
1331 tcg_out_ldst(s, args[0], args[1], args[2], LDSW);
1332 break;
1333 case INDEX_op_ld_i64:
1334 tcg_out_ldst(s, args[0], args[1], args[2], LDX);
1335 break;
1336 case INDEX_op_st_i64:
1337 tcg_out_ldst(s, args[0], args[1], args[2], STX);
1338 break;
1339 case INDEX_op_shl_i64:
1340 c = SHIFT_SLLX;
1341 do_shift64:
1342 /* Limit immediate shift count lest we create an illegal insn. */
1343 tcg_out_arithc(s, args[0], args[1], args[2] & 63, const_args[2], c);
1344 break;
1345 case INDEX_op_shr_i64:
1346 c = SHIFT_SRLX;
1347 goto do_shift64;
1348 case INDEX_op_sar_i64:
1349 c = SHIFT_SRAX;
1350 goto do_shift64;
1351 case INDEX_op_mul_i64:
1352 c = ARITH_MULX;
1353 goto gen_arith;
1354 case INDEX_op_div_i64:
1355 c = ARITH_SDIVX;
1356 goto gen_arith;
1357 case INDEX_op_divu_i64:
1358 c = ARITH_UDIVX;
1359 goto gen_arith;
1360 case INDEX_op_ext32s_i64:
1361 tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRA);
1362 break;
1363 case INDEX_op_ext32u_i64:
1364 tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
1365 break;
1366 case INDEX_op_trunc_shr_i32:
1367 if (args[2] == 0) {
1368 tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1369 } else {
1370 tcg_out_arithi(s, args[0], args[1], args[2], SHIFT_SRLX);
1372 break;
1374 case INDEX_op_brcond_i64:
1375 tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
1376 args[3]);
1377 break;
1378 case INDEX_op_setcond_i64:
1379 tcg_out_setcond_i64(s, args[3], args[0], args[1],
1380 args[2], const_args[2]);
1381 break;
1382 case INDEX_op_movcond_i64:
1383 tcg_out_movcond_i64(s, args[5], args[0], args[1],
1384 args[2], const_args[2], args[3], const_args[3]);
1385 break;
1387 gen_arith:
1388 tcg_out_arithc(s, args[0], args[1], args[2], const_args[2], c);
1389 break;
1391 gen_arith1:
1392 tcg_out_arithc(s, args[0], TCG_REG_G0, args[1], const_args[1], c);
1393 break;
1395 default:
1396 fprintf(stderr, "unknown opcode 0x%x\n", opc);
1397 tcg_abort();
1401 static const TCGTargetOpDef sparc_op_defs[] = {
1402 { INDEX_op_exit_tb, { } },
1403 { INDEX_op_goto_tb, { } },
1404 { INDEX_op_call, { "ri" } },
1405 { INDEX_op_br, { } },
1407 { INDEX_op_mov_i32, { "r", "r" } },
1408 { INDEX_op_movi_i32, { "r" } },
1409 { INDEX_op_ld8u_i32, { "r", "r" } },
1410 { INDEX_op_ld8s_i32, { "r", "r" } },
1411 { INDEX_op_ld16u_i32, { "r", "r" } },
1412 { INDEX_op_ld16s_i32, { "r", "r" } },
1413 { INDEX_op_ld_i32, { "r", "r" } },
1414 { INDEX_op_st8_i32, { "rZ", "r" } },
1415 { INDEX_op_st16_i32, { "rZ", "r" } },
1416 { INDEX_op_st_i32, { "rZ", "r" } },
1418 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
1419 { INDEX_op_mul_i32, { "r", "rZ", "rJ" } },
1420 { INDEX_op_div_i32, { "r", "rZ", "rJ" } },
1421 { INDEX_op_divu_i32, { "r", "rZ", "rJ" } },
1422 { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
1423 { INDEX_op_and_i32, { "r", "rZ", "rJ" } },
1424 { INDEX_op_andc_i32, { "r", "rZ", "rJ" } },
1425 { INDEX_op_or_i32, { "r", "rZ", "rJ" } },
1426 { INDEX_op_orc_i32, { "r", "rZ", "rJ" } },
1427 { INDEX_op_xor_i32, { "r", "rZ", "rJ" } },
1429 { INDEX_op_shl_i32, { "r", "rZ", "rJ" } },
1430 { INDEX_op_shr_i32, { "r", "rZ", "rJ" } },
1431 { INDEX_op_sar_i32, { "r", "rZ", "rJ" } },
1433 { INDEX_op_neg_i32, { "r", "rJ" } },
1434 { INDEX_op_not_i32, { "r", "rJ" } },
1436 { INDEX_op_brcond_i32, { "rZ", "rJ" } },
1437 { INDEX_op_setcond_i32, { "r", "rZ", "rJ" } },
1438 { INDEX_op_movcond_i32, { "r", "rZ", "rJ", "rI", "0" } },
1440 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1441 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1442 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rJ" } },
1443 { INDEX_op_muls2_i32, { "r", "r", "rZ", "rJ" } },
1445 { INDEX_op_mov_i64, { "R", "R" } },
1446 { INDEX_op_movi_i64, { "R" } },
1447 { INDEX_op_ld8u_i64, { "R", "r" } },
1448 { INDEX_op_ld8s_i64, { "R", "r" } },
1449 { INDEX_op_ld16u_i64, { "R", "r" } },
1450 { INDEX_op_ld16s_i64, { "R", "r" } },
1451 { INDEX_op_ld32u_i64, { "R", "r" } },
1452 { INDEX_op_ld32s_i64, { "R", "r" } },
1453 { INDEX_op_ld_i64, { "R", "r" } },
1454 { INDEX_op_st8_i64, { "RZ", "r" } },
1455 { INDEX_op_st16_i64, { "RZ", "r" } },
1456 { INDEX_op_st32_i64, { "RZ", "r" } },
1457 { INDEX_op_st_i64, { "RZ", "r" } },
1459 { INDEX_op_add_i64, { "R", "RZ", "RJ" } },
1460 { INDEX_op_mul_i64, { "R", "RZ", "RJ" } },
1461 { INDEX_op_div_i64, { "R", "RZ", "RJ" } },
1462 { INDEX_op_divu_i64, { "R", "RZ", "RJ" } },
1463 { INDEX_op_sub_i64, { "R", "RZ", "RJ" } },
1464 { INDEX_op_and_i64, { "R", "RZ", "RJ" } },
1465 { INDEX_op_andc_i64, { "R", "RZ", "RJ" } },
1466 { INDEX_op_or_i64, { "R", "RZ", "RJ" } },
1467 { INDEX_op_orc_i64, { "R", "RZ", "RJ" } },
1468 { INDEX_op_xor_i64, { "R", "RZ", "RJ" } },
1470 { INDEX_op_shl_i64, { "R", "RZ", "RJ" } },
1471 { INDEX_op_shr_i64, { "R", "RZ", "RJ" } },
1472 { INDEX_op_sar_i64, { "R", "RZ", "RJ" } },
1474 { INDEX_op_neg_i64, { "R", "RJ" } },
1475 { INDEX_op_not_i64, { "R", "RJ" } },
1477 { INDEX_op_ext32s_i64, { "R", "r" } },
1478 { INDEX_op_ext32u_i64, { "R", "r" } },
1479 { INDEX_op_trunc_shr_i32, { "r", "R" } },
1481 { INDEX_op_brcond_i64, { "RZ", "RJ" } },
1482 { INDEX_op_setcond_i64, { "R", "RZ", "RJ" } },
1483 { INDEX_op_movcond_i64, { "R", "RZ", "RJ", "RI", "0" } },
1485 { INDEX_op_qemu_ld_i32, { "r", "A" } },
1486 { INDEX_op_qemu_ld_i64, { "R", "A" } },
1487 { INDEX_op_qemu_st_i32, { "s", "A" } },
1488 { INDEX_op_qemu_st_i64, { "S", "A" } },
1490 { -1 },
1493 static void tcg_target_init(TCGContext *s)
1495 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1496 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, ALL_64);
1498 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1499 (1 << TCG_REG_G1) |
1500 (1 << TCG_REG_G2) |
1501 (1 << TCG_REG_G3) |
1502 (1 << TCG_REG_G4) |
1503 (1 << TCG_REG_G5) |
1504 (1 << TCG_REG_G6) |
1505 (1 << TCG_REG_G7) |
1506 (1 << TCG_REG_O0) |
1507 (1 << TCG_REG_O1) |
1508 (1 << TCG_REG_O2) |
1509 (1 << TCG_REG_O3) |
1510 (1 << TCG_REG_O4) |
1511 (1 << TCG_REG_O5) |
1512 (1 << TCG_REG_O7));
1514 tcg_regset_clear(s->reserved_regs);
1515 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */
1516 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */
1517 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */
1518 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); /* frame pointer */
1519 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); /* return address */
1520 tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */
1521 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */
1522 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
1524 tcg_add_target_add_op_defs(sparc_op_defs);
1527 #if SPARC64
1528 # define ELF_HOST_MACHINE EM_SPARCV9
1529 #else
1530 # define ELF_HOST_MACHINE EM_SPARC32PLUS
1531 # define ELF_HOST_FLAGS EF_SPARC_32PLUS
1532 #endif
1534 typedef struct {
1535 DebugFrameCIE cie;
1536 DebugFrameFDEHeader fde;
1537 uint8_t fde_def_cfa[SPARC64 ? 4 : 2];
1538 uint8_t fde_win_save;
1539 uint8_t fde_ret_save[3];
1540 } DebugFrame;
1542 static DebugFrame debug_frame = {
1543 .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
1544 .cie.id = -1,
1545 .cie.version = 1,
1546 .cie.code_align = 1,
1547 .cie.data_align = -sizeof(void *) & 0x7f,
1548 .cie.return_column = 15, /* o7 */
1550 /* Total FDE size does not include the "len" member. */
1551 .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
1553 .fde_def_cfa = {
1554 #if SPARC64
1555 12, 30, /* DW_CFA_def_cfa i6, 2047 */
1556 (2047 & 0x7f) | 0x80, (2047 >> 7)
1557 #else
1558 13, 30 /* DW_CFA_def_cfa_register i6 */
1559 #endif
1561 .fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */
1562 .fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
1565 void tcg_register_jit(void *buf, size_t buf_size)
1567 debug_frame.fde.func_start = (uintptr_t)buf;
1568 debug_frame.fde.func_len = buf_size;
1570 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
1573 void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
1575 uint32_t *ptr = (uint32_t *)jmp_addr;
1576 uintptr_t disp = addr - jmp_addr;
1578 /* We can reach the entire address space for 32-bit. For 64-bit
1579 the code_gen_buffer can't be larger than 2GB. */
1580 assert(disp == (int32_t)disp);
1582 *ptr = CALL | (uint32_t)disp >> 2;
1583 flush_icache_range(jmp_addr, jmp_addr + 4);