tcg-sparc: Fix setcond
[qemu/kevin.git] / tcg / sparc / tcg-target.c
blob31e8204b31d1c9633a985746677e1345424b170f
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 #ifndef NDEBUG
26 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
27 "%g0",
28 "%g1",
29 "%g2",
30 "%g3",
31 "%g4",
32 "%g5",
33 "%g6",
34 "%g7",
35 "%o0",
36 "%o1",
37 "%o2",
38 "%o3",
39 "%o4",
40 "%o5",
41 "%o6",
42 "%o7",
43 "%l0",
44 "%l1",
45 "%l2",
46 "%l3",
47 "%l4",
48 "%l5",
49 "%l6",
50 "%l7",
51 "%i0",
52 "%i1",
53 "%i2",
54 "%i3",
55 "%i4",
56 "%i5",
57 "%i6",
58 "%i7",
60 #endif
62 /* Define some temporary registers. T2 is used for constant generation. */
63 #define TCG_REG_T1 TCG_REG_G1
64 #define TCG_REG_T2 TCG_REG_O7
66 #ifdef CONFIG_USE_GUEST_BASE
67 # define TCG_GUEST_BASE_REG TCG_REG_I5
68 #else
69 # define TCG_GUEST_BASE_REG TCG_REG_G0
70 #endif
72 static const int tcg_target_reg_alloc_order[] = {
73 TCG_REG_L0,
74 TCG_REG_L1,
75 TCG_REG_L2,
76 TCG_REG_L3,
77 TCG_REG_L4,
78 TCG_REG_L5,
79 TCG_REG_L6,
80 TCG_REG_L7,
82 TCG_REG_I0,
83 TCG_REG_I1,
84 TCG_REG_I2,
85 TCG_REG_I3,
86 TCG_REG_I4,
87 TCG_REG_I5,
89 TCG_REG_G2,
90 TCG_REG_G3,
91 TCG_REG_G4,
92 TCG_REG_G5,
94 TCG_REG_O0,
95 TCG_REG_O1,
96 TCG_REG_O2,
97 TCG_REG_O3,
98 TCG_REG_O4,
99 TCG_REG_O5,
102 static const int tcg_target_call_iarg_regs[6] = {
103 TCG_REG_O0,
104 TCG_REG_O1,
105 TCG_REG_O2,
106 TCG_REG_O3,
107 TCG_REG_O4,
108 TCG_REG_O5,
111 static const int tcg_target_call_oarg_regs[] = {
112 TCG_REG_O0,
113 TCG_REG_O1,
114 TCG_REG_O2,
115 TCG_REG_O3,
118 static inline int check_fit_tl(tcg_target_long val, unsigned int bits)
120 return (val << ((sizeof(tcg_target_long) * 8 - bits))
121 >> (sizeof(tcg_target_long) * 8 - bits)) == val;
124 static inline int check_fit_i32(uint32_t val, unsigned int bits)
126 return ((val << (32 - bits)) >> (32 - bits)) == val;
129 static void patch_reloc(uint8_t *code_ptr, int type,
130 tcg_target_long value, tcg_target_long addend)
132 value += addend;
133 switch (type) {
134 case R_SPARC_32:
135 if (value != (uint32_t)value)
136 tcg_abort();
137 *(uint32_t *)code_ptr = value;
138 break;
139 case R_SPARC_WDISP22:
140 value -= (long)code_ptr;
141 value >>= 2;
142 if (!check_fit_tl(value, 22))
143 tcg_abort();
144 *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x3fffff) | value;
145 break;
146 case R_SPARC_WDISP19:
147 value -= (long)code_ptr;
148 value >>= 2;
149 if (!check_fit_tl(value, 19))
150 tcg_abort();
151 *(uint32_t *)code_ptr = ((*(uint32_t *)code_ptr) & ~0x7ffff) | value;
152 break;
153 default:
154 tcg_abort();
158 /* parse target specific constraints */
159 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
161 const char *ct_str;
163 ct_str = *pct_str;
164 switch (ct_str[0]) {
165 case 'r':
166 ct->ct |= TCG_CT_REG;
167 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
168 break;
169 case 'L': /* qemu_ld/st constraint */
170 ct->ct |= TCG_CT_REG;
171 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
172 // Helper args
173 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
174 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
175 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
176 break;
177 case 'I':
178 ct->ct |= TCG_CT_CONST_S11;
179 break;
180 case 'J':
181 ct->ct |= TCG_CT_CONST_S13;
182 break;
183 default:
184 return -1;
186 ct_str++;
187 *pct_str = ct_str;
188 return 0;
191 /* test if a constant matches the constraint */
192 static inline int tcg_target_const_match(tcg_target_long val,
193 const TCGArgConstraint *arg_ct)
195 int ct;
197 ct = arg_ct->ct;
198 if (ct & TCG_CT_CONST)
199 return 1;
200 else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11))
201 return 1;
202 else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13))
203 return 1;
204 else
205 return 0;
208 #define INSN_OP(x) ((x) << 30)
209 #define INSN_OP2(x) ((x) << 22)
210 #define INSN_OP3(x) ((x) << 19)
211 #define INSN_OPF(x) ((x) << 5)
212 #define INSN_RD(x) ((x) << 25)
213 #define INSN_RS1(x) ((x) << 14)
214 #define INSN_RS2(x) (x)
215 #define INSN_ASI(x) ((x) << 5)
217 #define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff))
218 #define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff))
219 #define INSN_OFF19(x) (((x) >> 2) & 0x07ffff)
220 #define INSN_OFF22(x) (((x) >> 2) & 0x3fffff)
222 #define INSN_COND(x, a) (((x) << 25) | ((a) << 29))
223 #define COND_N 0x0
224 #define COND_E 0x1
225 #define COND_LE 0x2
226 #define COND_L 0x3
227 #define COND_LEU 0x4
228 #define COND_CS 0x5
229 #define COND_NEG 0x6
230 #define COND_VS 0x7
231 #define COND_A 0x8
232 #define COND_NE 0x9
233 #define COND_G 0xa
234 #define COND_GE 0xb
235 #define COND_GU 0xc
236 #define COND_CC 0xd
237 #define COND_POS 0xe
238 #define COND_VC 0xf
239 #define BA (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))
241 #define MOVCC_ICC (1 << 18)
242 #define MOVCC_XCC (1 << 18 | 1 << 12)
244 #define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00))
245 #define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
246 #define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01))
247 #define ARITH_ANDN (INSN_OP(2) | INSN_OP3(0x05))
248 #define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02))
249 #define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12))
250 #define ARITH_ORN (INSN_OP(2) | INSN_OP3(0x06))
251 #define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03))
252 #define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04))
253 #define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
254 #define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x08))
255 #define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
256 #define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
257 #define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
258 #define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f))
259 #define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09))
260 #define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d))
261 #define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d))
262 #define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c))
264 #define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25))
265 #define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26))
266 #define SHIFT_SRA (INSN_OP(2) | INSN_OP3(0x27))
268 #define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))
269 #define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
270 #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
272 #define RDY (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0))
273 #define WRY (INSN_OP(2) | INSN_OP3(0x30) | INSN_RD(0))
274 #define JMPL (INSN_OP(2) | INSN_OP3(0x38))
275 #define SAVE (INSN_OP(2) | INSN_OP3(0x3c))
276 #define RESTORE (INSN_OP(2) | INSN_OP3(0x3d))
277 #define SETHI (INSN_OP(0) | INSN_OP2(0x4))
278 #define CALL INSN_OP(1)
279 #define LDUB (INSN_OP(3) | INSN_OP3(0x01))
280 #define LDSB (INSN_OP(3) | INSN_OP3(0x09))
281 #define LDUH (INSN_OP(3) | INSN_OP3(0x02))
282 #define LDSH (INSN_OP(3) | INSN_OP3(0x0a))
283 #define LDUW (INSN_OP(3) | INSN_OP3(0x00))
284 #define LDSW (INSN_OP(3) | INSN_OP3(0x08))
285 #define LDX (INSN_OP(3) | INSN_OP3(0x0b))
286 #define STB (INSN_OP(3) | INSN_OP3(0x05))
287 #define STH (INSN_OP(3) | INSN_OP3(0x06))
288 #define STW (INSN_OP(3) | INSN_OP3(0x04))
289 #define STX (INSN_OP(3) | INSN_OP3(0x0e))
290 #define LDUBA (INSN_OP(3) | INSN_OP3(0x11))
291 #define LDSBA (INSN_OP(3) | INSN_OP3(0x19))
292 #define LDUHA (INSN_OP(3) | INSN_OP3(0x12))
293 #define LDSHA (INSN_OP(3) | INSN_OP3(0x1a))
294 #define LDUWA (INSN_OP(3) | INSN_OP3(0x10))
295 #define LDSWA (INSN_OP(3) | INSN_OP3(0x18))
296 #define LDXA (INSN_OP(3) | INSN_OP3(0x1b))
297 #define STBA (INSN_OP(3) | INSN_OP3(0x15))
298 #define STHA (INSN_OP(3) | INSN_OP3(0x16))
299 #define STWA (INSN_OP(3) | INSN_OP3(0x14))
300 #define STXA (INSN_OP(3) | INSN_OP3(0x1e))
302 #ifndef ASI_PRIMARY_LITTLE
303 #define ASI_PRIMARY_LITTLE 0x88
304 #endif
306 #define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
307 #define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
308 #define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
309 #define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
310 #define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE))
312 #define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE))
313 #define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
314 #define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
316 static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
317 int op)
319 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
320 INSN_RS2(rs2));
323 static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1,
324 uint32_t offset, int op)
326 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) |
327 INSN_IMM13(offset));
330 static void tcg_out_arithc(TCGContext *s, int rd, int rs1,
331 int val2, int val2const, int op)
333 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1)
334 | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
337 static inline void tcg_out_mov(TCGContext *s, TCGType type,
338 TCGReg ret, TCGReg arg)
340 if (ret != arg) {
341 tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
345 static inline void tcg_out_sethi(TCGContext *s, int ret, uint32_t arg)
347 tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10));
350 static inline void tcg_out_movi_imm13(TCGContext *s, int ret, uint32_t arg)
352 tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR);
355 static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
357 if (check_fit_tl(arg, 13))
358 tcg_out_movi_imm13(s, ret, arg);
359 else {
360 tcg_out_sethi(s, ret, arg);
361 if (arg & 0x3ff)
362 tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
366 static inline void tcg_out_movi(TCGContext *s, TCGType type,
367 TCGReg ret, tcg_target_long arg)
369 /* All 32-bit constants, as well as 64-bit constants with
370 no high bits set go through movi_imm32. */
371 if (TCG_TARGET_REG_BITS == 32
372 || type == TCG_TYPE_I32
373 || (arg & ~(tcg_target_long)0xffffffff) == 0) {
374 tcg_out_movi_imm32(s, ret, arg);
375 } else if (check_fit_tl(arg, 13)) {
376 /* A 13-bit constant sign-extended to 64-bits. */
377 tcg_out_movi_imm13(s, ret, arg);
378 } else if (check_fit_tl(arg, 32)) {
379 /* A 32-bit constant sign-extended to 64-bits. */
380 tcg_out_sethi(s, ret, ~arg);
381 tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
382 } else {
383 tcg_out_movi_imm32(s, ret, arg >> (TCG_TARGET_REG_BITS / 2));
384 tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
385 tcg_out_movi_imm32(s, TCG_REG_T2, arg);
386 tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR);
390 static inline void tcg_out_ldst_rr(TCGContext *s, int data, int a1,
391 int a2, int op)
393 tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2));
396 static inline void tcg_out_ldst(TCGContext *s, int ret, int addr,
397 int offset, int op)
399 if (check_fit_tl(offset, 13)) {
400 tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
401 INSN_IMM13(offset));
402 } else {
403 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, offset);
404 tcg_out_ldst_rr(s, ret, addr, TCG_REG_T1, op);
408 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
409 TCGReg arg1, tcg_target_long arg2)
411 tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX));
414 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
415 TCGReg arg1, tcg_target_long arg2)
417 tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
420 static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
421 tcg_target_long arg)
423 if (!check_fit_tl(arg, 10)) {
424 tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
426 tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, arg & 0x3ff);
429 static inline void tcg_out_sety(TCGContext *s, int rs)
431 tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
434 static inline void tcg_out_rdy(TCGContext *s, int rd)
436 tcg_out32(s, RDY | INSN_RD(rd));
439 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
441 if (val != 0) {
442 if (check_fit_tl(val, 13))
443 tcg_out_arithi(s, reg, reg, val, ARITH_ADD);
444 else {
445 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, val);
446 tcg_out_arith(s, reg, reg, TCG_REG_T1, ARITH_ADD);
451 static inline void tcg_out_andi(TCGContext *s, int rd, int rs,
452 tcg_target_long val)
454 if (val != 0) {
455 if (check_fit_tl(val, 13))
456 tcg_out_arithi(s, rd, rs, val, ARITH_AND);
457 else {
458 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T1, val);
459 tcg_out_arith(s, rd, rs, TCG_REG_T1, ARITH_AND);
464 static void tcg_out_div32(TCGContext *s, int rd, int rs1,
465 int val2, int val2const, int uns)
467 /* Load Y with the sign/zero extension of RS1 to 64-bits. */
468 if (uns) {
469 tcg_out_sety(s, TCG_REG_G0);
470 } else {
471 tcg_out_arithi(s, TCG_REG_T1, rs1, 31, SHIFT_SRA);
472 tcg_out_sety(s, TCG_REG_T1);
475 tcg_out_arithc(s, rd, rs1, val2, val2const,
476 uns ? ARITH_UDIV : ARITH_SDIV);
479 static inline void tcg_out_nop(TCGContext *s)
481 tcg_out_sethi(s, TCG_REG_G0, 0);
484 static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
486 TCGLabel *l = &s->labels[label_index];
487 uint32_t off22;
489 if (l->has_value) {
490 off22 = INSN_OFF22(l->u.value - (unsigned long)s->code_ptr);
491 } else {
492 /* Make sure to preserve destinations during retranslation. */
493 off22 = *(uint32_t *)s->code_ptr & INSN_OFF22(-1);
494 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP22, label_index, 0);
496 tcg_out32(s, INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | off22);
499 #if TCG_TARGET_REG_BITS == 64
500 static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
502 TCGLabel *l = &s->labels[label_index];
503 uint32_t off19;
505 if (l->has_value) {
506 off19 = INSN_OFF19(l->u.value - (unsigned long)s->code_ptr);
507 } else {
508 /* Make sure to preserve destinations during retranslation. */
509 off19 = *(uint32_t *)s->code_ptr & INSN_OFF19(-1);
510 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label_index, 0);
512 tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
513 (0x5 << 19) | off19));
515 #endif
517 static const uint8_t tcg_cond_to_bcond[] = {
518 [TCG_COND_EQ] = COND_E,
519 [TCG_COND_NE] = COND_NE,
520 [TCG_COND_LT] = COND_L,
521 [TCG_COND_GE] = COND_GE,
522 [TCG_COND_LE] = COND_LE,
523 [TCG_COND_GT] = COND_G,
524 [TCG_COND_LTU] = COND_CS,
525 [TCG_COND_GEU] = COND_CC,
526 [TCG_COND_LEU] = COND_LEU,
527 [TCG_COND_GTU] = COND_GU,
530 static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const)
532 tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
535 static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond,
536 TCGArg arg1, TCGArg arg2, int const_arg2,
537 int label_index)
539 tcg_out_cmp(s, arg1, arg2, const_arg2);
540 tcg_out_branch_i32(s, tcg_cond_to_bcond[cond], label_index);
541 tcg_out_nop(s);
544 static void tcg_out_movcc(TCGContext *s, TCGCond cond, int cc, TCGArg ret,
545 TCGArg v1, int v1const)
547 tcg_out32(s, ARITH_MOVCC | cc | INSN_RD(ret)
548 | INSN_RS1(tcg_cond_to_bcond[cond])
549 | (v1const ? INSN_IMM11(v1) : INSN_RS2(v1)));
552 static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
553 TCGArg c1, TCGArg c2, int c2const,
554 TCGArg v1, int v1const)
556 tcg_out_cmp(s, c1, c2, c2const);
557 tcg_out_movcc(s, cond, MOVCC_ICC, ret, v1, v1const);
560 #if TCG_TARGET_REG_BITS == 64
561 static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond,
562 TCGArg arg1, TCGArg arg2, int const_arg2,
563 int label_index)
565 tcg_out_cmp(s, arg1, arg2, const_arg2);
566 tcg_out_branch_i64(s, tcg_cond_to_bcond[cond], label_index);
567 tcg_out_nop(s);
570 static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGArg ret,
571 TCGArg c1, TCGArg c2, int c2const,
572 TCGArg v1, int v1const)
574 tcg_out_cmp(s, c1, c2, c2const);
575 tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const);
577 #else
578 static void tcg_out_brcond2_i32(TCGContext *s, TCGCond cond,
579 TCGArg al, TCGArg ah,
580 TCGArg bl, int blconst,
581 TCGArg bh, int bhconst, int label_dest)
583 int cc, label_next = gen_new_label();
585 tcg_out_cmp(s, ah, bh, bhconst);
587 /* Note that we fill one of the delay slots with the second compare. */
588 switch (cond) {
589 case TCG_COND_EQ:
590 tcg_out_branch_i32(s, COND_NE, label_next);
591 tcg_out_cmp(s, al, bl, blconst);
592 tcg_out_branch_i32(s, COND_E, label_dest);
593 break;
595 case TCG_COND_NE:
596 tcg_out_branch_i32(s, COND_NE, label_dest);
597 tcg_out_cmp(s, al, bl, blconst);
598 tcg_out_branch_i32(s, COND_NE, label_dest);
599 break;
601 default:
602 cc = tcg_cond_to_bcond[tcg_high_cond(cond)];
603 tcg_out_branch_i32(s, cc, label_dest);
604 tcg_out_nop(s);
605 tcg_out_branch_i32(s, COND_NE, label_next);
606 tcg_out_cmp(s, al, bl, blconst);
607 cc = tcg_cond_to_bcond[tcg_unsigned_cond(cond)];
608 tcg_out_branch_i32(s, cc, label_dest);
609 break;
611 tcg_out_nop(s);
613 tcg_out_label(s, label_next, s->code_ptr);
615 #endif
617 static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGArg ret,
618 TCGArg c1, TCGArg c2, int c2const)
620 /* For 32-bit comparisons, we can play games with ADDX/SUBX. */
621 switch (cond) {
622 case TCG_COND_LTU:
623 case TCG_COND_GEU:
624 /* The result of the comparison is in the carry bit. */
625 break;
627 case TCG_COND_EQ:
628 case TCG_COND_NE:
629 /* For equality, we can transform to inequality vs zero. */
630 if (c2 != 0) {
631 tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR);
633 c1 = TCG_REG_G0, c2 = ret, c2const = 0;
634 cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU);
635 break;
637 case TCG_COND_GTU:
638 case TCG_COND_LEU:
639 /* If we don't need to load a constant into a register, we can
640 swap the operands on GTU/LEU. There's no benefit to loading
641 the constant into a temporary register. */
642 if (!c2const || c2 == 0) {
643 TCGArg t = c1;
644 c1 = c2;
645 c2 = t;
646 c2const = 0;
647 cond = tcg_swap_cond(cond);
648 break;
650 /* FALLTHRU */
652 default:
653 tcg_out_cmp(s, c1, c2, c2const);
654 tcg_out_movi_imm13(s, ret, 0);
655 tcg_out_movcc(s, cond, MOVCC_ICC, ret, 1, 1);
656 return;
659 tcg_out_cmp(s, c1, c2, c2const);
660 if (cond == TCG_COND_LTU) {
661 tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDX);
662 } else {
663 tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBX);
667 #if TCG_TARGET_REG_BITS == 64
668 static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGArg ret,
669 TCGArg c1, TCGArg c2, int c2const)
671 tcg_out_cmp(s, c1, c2, c2const);
672 tcg_out_movi_imm13(s, ret, 0);
673 tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1);
675 #else
676 static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
677 TCGArg al, TCGArg ah,
678 TCGArg bl, int blconst,
679 TCGArg bh, int bhconst)
681 int tmp = TCG_REG_T1;
683 /* Note that the low parts are fully consumed before tmp is set. */
684 if (ret != ah && (bhconst || ret != bh)) {
685 tmp = ret;
688 switch (cond) {
689 case TCG_COND_EQ:
690 case TCG_COND_NE:
691 tcg_out_setcond_i32(s, cond, tmp, al, bl, blconst);
692 tcg_out_cmp(s, ah, bh, bhconst);
693 tcg_out_mov(s, TCG_TYPE_I32, ret, tmp);
694 tcg_out_movcc(s, TCG_COND_NE, MOVCC_ICC, ret, cond == TCG_COND_NE, 1);
695 break;
697 default:
698 /* <= : ah < bh | (ah == bh && al <= bl) */
699 tcg_out_setcond_i32(s, tcg_unsigned_cond(cond), tmp, al, bl, blconst);
700 tcg_out_cmp(s, ah, bh, bhconst);
701 tcg_out_mov(s, TCG_TYPE_I32, ret, tmp);
702 tcg_out_movcc(s, TCG_COND_NE, MOVCC_ICC, ret, 0, 1);
703 tcg_out_movcc(s, tcg_high_cond(cond), MOVCC_ICC, ret, 1, 1);
704 break;
707 #endif
709 /* Generate global QEMU prologue and epilogue code */
710 static void tcg_target_qemu_prologue(TCGContext *s)
712 int tmp_buf_size, frame_size;
714 /* The TCG temp buffer is at the top of the frame, immediately
715 below the frame pointer. */
716 tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long);
717 tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_STACK_BIAS - tmp_buf_size,
718 tmp_buf_size);
720 /* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
721 otherwise the minimal frame usable by callees. */
722 frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS;
723 frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size;
724 frame_size += TCG_TARGET_STACK_ALIGN - 1;
725 frame_size &= -TCG_TARGET_STACK_ALIGN;
726 tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
727 INSN_IMM13(-frame_size));
729 #ifdef CONFIG_USE_GUEST_BASE
730 if (GUEST_BASE != 0) {
731 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
732 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
734 #endif
736 tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I1) |
737 INSN_RS2(TCG_REG_G0));
738 /* delay slot */
739 tcg_out_nop(s);
741 /* No epilogue required. We issue ret + restore directly in the TB. */
744 #if defined(CONFIG_SOFTMMU)
746 #include "../../softmmu_defs.h"
748 /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
749 int mmu_idx) */
750 static const void * const qemu_ld_helpers[4] = {
751 helper_ldb_mmu,
752 helper_ldw_mmu,
753 helper_ldl_mmu,
754 helper_ldq_mmu,
757 /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
758 uintxx_t val, int mmu_idx) */
759 static const void * const qemu_st_helpers[4] = {
760 helper_stb_mmu,
761 helper_stw_mmu,
762 helper_stl_mmu,
763 helper_stq_mmu,
766 /* Perform the TLB load and compare.
768 Inputs:
769 ADDRLO_IDX contains the index into ARGS of the low part of the
770 address; the high part of the address is at ADDR_LOW_IDX+1.
772 MEM_INDEX and S_BITS are the memory context and log2 size of the load.
774 WHICH is the offset into the CPUTLBEntry structure of the slot to read.
775 This should be offsetof addr_read or addr_write.
777 The result of the TLB comparison is in %[ix]cc. The sanitized address
778 is in the returned register, maybe %o0. The TLB addend is in %o1. */
780 static int tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
781 int s_bits, const TCGArg *args, int which)
783 const int addrlo = args[addrlo_idx];
784 const int r0 = TCG_REG_O0;
785 const int r1 = TCG_REG_O1;
786 const int r2 = TCG_REG_O2;
787 int addr = addrlo;
788 int tlb_ofs;
790 if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
791 /* Assemble the 64-bit address in R0. */
792 tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
793 tcg_out_arithi(s, r1, args[addrlo_idx + 1], 32, SHIFT_SLLX);
794 tcg_out_arith(s, r0, r0, r1, ARITH_OR);
797 /* Shift the page number down to tlb-entry. */
798 tcg_out_arithi(s, r1, addrlo,
799 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS, SHIFT_SRL);
801 /* Mask out the page offset, except for the required alignment. */
802 tcg_out_andi(s, r0, addr, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
804 /* Compute tlb index, modulo tlb size. */
805 tcg_out_andi(s, r1, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
807 /* Relative to the current ENV. */
808 tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD);
810 /* Find a base address that can load both tlb comparator and addend. */
811 tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
812 if (!check_fit_tl(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
813 tcg_out_addi(s, r1, tlb_ofs);
814 tlb_ofs = 0;
817 /* Load the tlb comparator and the addend. */
818 tcg_out_ld(s, TCG_TYPE_TL, r2, r1, tlb_ofs + which);
819 tcg_out_ld(s, TCG_TYPE_PTR, r1, r1, tlb_ofs+offsetof(CPUTLBEntry, addend));
821 /* subcc arg0, arg2, %g0 */
822 tcg_out_cmp(s, r0, r2, 0);
824 /* If the guest address must be zero-extended, do so now. */
825 if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
826 tcg_out_arithi(s, r0, addrlo, 0, SHIFT_SRL);
827 return r0;
829 return addrlo;
831 #endif /* CONFIG_SOFTMMU */
833 static const int qemu_ld_opc[8] = {
834 #ifdef TARGET_WORDS_BIGENDIAN
835 LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX
836 #else
837 LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE
838 #endif
841 static const int qemu_st_opc[4] = {
842 #ifdef TARGET_WORDS_BIGENDIAN
843 STB, STH, STW, STX
844 #else
845 STB, STH_LE, STW_LE, STX_LE
846 #endif
849 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int sizeop)
851 int addrlo_idx = 1, datalo, datahi, addr_reg;
852 #if defined(CONFIG_SOFTMMU)
853 int memi_idx, memi, s_bits, n;
854 uint32_t *label_ptr[2];
855 #endif
857 datahi = datalo = args[0];
858 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
859 datahi = args[1];
860 addrlo_idx = 2;
863 #if defined(CONFIG_SOFTMMU)
864 memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
865 memi = args[memi_idx];
866 s_bits = sizeop & 3;
868 addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, s_bits, args,
869 offsetof(CPUTLBEntry, addr_read));
871 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
872 int reg64;
874 /* bne,pn %[xi]cc, label0 */
875 label_ptr[0] = (uint32_t *)s->code_ptr;
876 tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_NE, 0) | INSN_OP2(0x1)
877 | ((TARGET_LONG_BITS == 64) << 21)));
879 /* TLB Hit. */
880 /* Load all 64-bits into an O/G register. */
881 reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
882 tcg_out_ldst_rr(s, reg64, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
884 /* Move the two 32-bit pieces into the destination registers. */
885 tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
886 if (reg64 != datalo) {
887 tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
890 /* b,a,pt label1 */
891 label_ptr[1] = (uint32_t *)s->code_ptr;
892 tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x1)
893 | (1 << 29) | (1 << 19)));
894 } else {
895 /* The fast path is exactly one insn. Thus we can perform the
896 entire TLB Hit in the (annulled) delay slot of the branch
897 over the TLB Miss case. */
899 /* beq,a,pt %[xi]cc, label0 */
900 label_ptr[0] = NULL;
901 label_ptr[1] = (uint32_t *)s->code_ptr;
902 tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1)
903 | ((TARGET_LONG_BITS == 64) << 21)
904 | (1 << 29) | (1 << 19)));
905 /* delay slot */
906 tcg_out_ldst_rr(s, datalo, addr_reg, TCG_REG_O1, qemu_ld_opc[sizeop]);
909 /* TLB Miss. */
911 if (label_ptr[0]) {
912 *label_ptr[0] |= INSN_OFF19((unsigned long)s->code_ptr -
913 (unsigned long)label_ptr[0]);
915 n = 0;
916 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
917 if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
918 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
919 args[addrlo_idx + 1]);
921 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
922 args[addrlo_idx]);
924 /* qemu_ld_helper[s_bits](arg0, arg1) */
925 tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_ld_helpers[s_bits]
926 - (tcg_target_ulong)s->code_ptr) >> 2)
927 & 0x3fffffff));
928 /* delay slot */
929 tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[n], memi);
931 n = tcg_target_call_oarg_regs[0];
932 /* datalo = sign_extend(arg0) */
933 switch (sizeop) {
934 case 0 | 4:
935 /* Recall that SRA sign extends from bit 31 through bit 63. */
936 tcg_out_arithi(s, datalo, n, 24, SHIFT_SLL);
937 tcg_out_arithi(s, datalo, datalo, 24, SHIFT_SRA);
938 break;
939 case 1 | 4:
940 tcg_out_arithi(s, datalo, n, 16, SHIFT_SLL);
941 tcg_out_arithi(s, datalo, datalo, 16, SHIFT_SRA);
942 break;
943 case 2 | 4:
944 tcg_out_arithi(s, datalo, n, 0, SHIFT_SRA);
945 break;
946 case 3:
947 if (TCG_TARGET_REG_BITS == 32) {
948 tcg_out_mov(s, TCG_TYPE_REG, datahi, n);
949 tcg_out_mov(s, TCG_TYPE_REG, datalo, n + 1);
950 break;
952 /* FALLTHRU */
953 case 0:
954 case 1:
955 case 2:
956 default:
957 /* mov */
958 tcg_out_mov(s, TCG_TYPE_REG, datalo, n);
959 break;
962 *label_ptr[1] |= INSN_OFF19((unsigned long)s->code_ptr -
963 (unsigned long)label_ptr[1]);
964 #else
965 addr_reg = args[addrlo_idx];
966 if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
967 tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
968 addr_reg = TCG_REG_T1;
970 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
971 int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
973 tcg_out_ldst_rr(s, reg64, addr_reg,
974 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
975 qemu_ld_opc[sizeop]);
977 tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
978 if (reg64 != datalo) {
979 tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
981 } else {
982 tcg_out_ldst_rr(s, datalo, addr_reg,
983 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
984 qemu_ld_opc[sizeop]);
986 #endif /* CONFIG_SOFTMMU */
989 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int sizeop)
991 int addrlo_idx = 1, datalo, datahi, addr_reg;
992 #if defined(CONFIG_SOFTMMU)
993 int memi_idx, memi, n, datafull;
994 uint32_t *label_ptr;
995 #endif
997 datahi = datalo = args[0];
998 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
999 datahi = args[1];
1000 addrlo_idx = 2;
1003 #if defined(CONFIG_SOFTMMU)
1004 memi_idx = addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS);
1005 memi = args[memi_idx];
1007 addr_reg = tcg_out_tlb_load(s, addrlo_idx, memi, sizeop, args,
1008 offsetof(CPUTLBEntry, addr_write));
1010 datafull = datalo;
1011 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
1012 /* Reconstruct the full 64-bit value. */
1013 tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
1014 tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
1015 tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
1016 datafull = TCG_REG_O2;
1019 /* The fast path is exactly one insn. Thus we can perform the entire
1020 TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
1021 /* beq,a,pt %[xi]cc, label0 */
1022 label_ptr = (uint32_t *)s->code_ptr;
1023 tcg_out32(s, (INSN_OP(0) | INSN_COND(COND_E, 0) | INSN_OP2(0x1)
1024 | ((TARGET_LONG_BITS == 64) << 21)
1025 | (1 << 29) | (1 << 19)));
1026 /* delay slot */
1027 tcg_out_ldst_rr(s, datafull, addr_reg, TCG_REG_O1, qemu_st_opc[sizeop]);
1029 /* TLB Miss. */
1031 n = 0;
1032 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[n++], TCG_AREG0);
1033 if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
1034 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
1035 args[addrlo_idx + 1]);
1037 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++],
1038 args[addrlo_idx]);
1039 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
1040 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datahi);
1042 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n++], datalo);
1044 /* qemu_st_helper[s_bits](arg0, arg1, arg2) */
1045 tcg_out32(s, CALL | ((((tcg_target_ulong)qemu_st_helpers[sizeop]
1046 - (tcg_target_ulong)s->code_ptr) >> 2)
1047 & 0x3fffffff));
1048 /* delay slot */
1049 tcg_out_movi(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[n], memi);
1051 *label_ptr |= INSN_OFF19((unsigned long)s->code_ptr -
1052 (unsigned long)label_ptr);
1053 #else
1054 addr_reg = args[addrlo_idx];
1055 if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 32) {
1056 tcg_out_arithi(s, TCG_REG_T1, addr_reg, 0, SHIFT_SRL);
1057 addr_reg = TCG_REG_T1;
1059 if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
1060 tcg_out_arithi(s, TCG_REG_T1, datalo, 0, SHIFT_SRL);
1061 tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
1062 tcg_out_arith(s, TCG_REG_O2, TCG_REG_T1, TCG_REG_O2, ARITH_OR);
1063 datalo = TCG_REG_O2;
1065 tcg_out_ldst_rr(s, datalo, addr_reg,
1066 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1067 qemu_st_opc[sizeop]);
1068 #endif /* CONFIG_SOFTMMU */
1071 static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
1072 const int *const_args)
1074 int c;
1076 switch (opc) {
1077 case INDEX_op_exit_tb:
1078 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, args[0]);
1079 tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_I7) |
1080 INSN_IMM13(8));
1081 tcg_out32(s, RESTORE | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_G0) |
1082 INSN_RS2(TCG_REG_G0));
1083 break;
1084 case INDEX_op_goto_tb:
1085 if (s->tb_jmp_offset) {
1086 /* direct jump method */
1087 uint32_t old_insn = *(uint32_t *)s->code_ptr;
1088 s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1089 /* Make sure to preserve links during retranslation. */
1090 tcg_out32(s, CALL | (old_insn & ~INSN_OP(-1)));
1091 } else {
1092 /* indirect jump method */
1093 tcg_out_ld_ptr(s, TCG_REG_T1,
1094 (tcg_target_long)(s->tb_next + args[0]));
1095 tcg_out32(s, JMPL | INSN_RD(TCG_REG_G0) | INSN_RS1(TCG_REG_T1) |
1096 INSN_RS2(TCG_REG_G0));
1098 tcg_out_nop(s);
1099 s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1100 break;
1101 case INDEX_op_call:
1102 if (const_args[0]) {
1103 tcg_out32(s, CALL | ((((tcg_target_ulong)args[0]
1104 - (tcg_target_ulong)s->code_ptr) >> 2)
1105 & 0x3fffffff));
1106 } else {
1107 tcg_out_ld_ptr(s, TCG_REG_T1,
1108 (tcg_target_long)(s->tb_next + args[0]));
1109 tcg_out32(s, JMPL | INSN_RD(TCG_REG_O7) | INSN_RS1(TCG_REG_T1) |
1110 INSN_RS2(TCG_REG_G0));
1112 /* delay slot */
1113 tcg_out_nop(s);
1114 break;
1115 case INDEX_op_br:
1116 tcg_out_branch_i32(s, COND_A, args[0]);
1117 tcg_out_nop(s);
1118 break;
1119 case INDEX_op_movi_i32:
1120 tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
1121 break;
1123 #if TCG_TARGET_REG_BITS == 64
1124 #define OP_32_64(x) \
1125 glue(glue(case INDEX_op_, x), _i32): \
1126 glue(glue(case INDEX_op_, x), _i64)
1127 #else
1128 #define OP_32_64(x) \
1129 glue(glue(case INDEX_op_, x), _i32)
1130 #endif
1131 OP_32_64(ld8u):
1132 tcg_out_ldst(s, args[0], args[1], args[2], LDUB);
1133 break;
1134 OP_32_64(ld8s):
1135 tcg_out_ldst(s, args[0], args[1], args[2], LDSB);
1136 break;
1137 OP_32_64(ld16u):
1138 tcg_out_ldst(s, args[0], args[1], args[2], LDUH);
1139 break;
1140 OP_32_64(ld16s):
1141 tcg_out_ldst(s, args[0], args[1], args[2], LDSH);
1142 break;
1143 case INDEX_op_ld_i32:
1144 #if TCG_TARGET_REG_BITS == 64
1145 case INDEX_op_ld32u_i64:
1146 #endif
1147 tcg_out_ldst(s, args[0], args[1], args[2], LDUW);
1148 break;
1149 OP_32_64(st8):
1150 tcg_out_ldst(s, args[0], args[1], args[2], STB);
1151 break;
1152 OP_32_64(st16):
1153 tcg_out_ldst(s, args[0], args[1], args[2], STH);
1154 break;
1155 case INDEX_op_st_i32:
1156 #if TCG_TARGET_REG_BITS == 64
1157 case INDEX_op_st32_i64:
1158 #endif
1159 tcg_out_ldst(s, args[0], args[1], args[2], STW);
1160 break;
1161 OP_32_64(add):
1162 c = ARITH_ADD;
1163 goto gen_arith;
1164 OP_32_64(sub):
1165 c = ARITH_SUB;
1166 goto gen_arith;
1167 OP_32_64(and):
1168 c = ARITH_AND;
1169 goto gen_arith;
1170 OP_32_64(andc):
1171 c = ARITH_ANDN;
1172 goto gen_arith;
1173 OP_32_64(or):
1174 c = ARITH_OR;
1175 goto gen_arith;
1176 OP_32_64(orc):
1177 c = ARITH_ORN;
1178 goto gen_arith;
1179 OP_32_64(xor):
1180 c = ARITH_XOR;
1181 goto gen_arith;
1182 case INDEX_op_shl_i32:
1183 c = SHIFT_SLL;
1184 do_shift32:
1185 /* Limit immediate shift count lest we create an illegal insn. */
1186 tcg_out_arithc(s, args[0], args[1], args[2] & 31, const_args[2], c);
1187 break;
1188 case INDEX_op_shr_i32:
1189 c = SHIFT_SRL;
1190 goto do_shift32;
1191 case INDEX_op_sar_i32:
1192 c = SHIFT_SRA;
1193 goto do_shift32;
1194 case INDEX_op_mul_i32:
1195 c = ARITH_UMUL;
1196 goto gen_arith;
1198 OP_32_64(neg):
1199 c = ARITH_SUB;
1200 goto gen_arith1;
1201 OP_32_64(not):
1202 c = ARITH_ORN;
1203 goto gen_arith1;
1205 case INDEX_op_div_i32:
1206 tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 0);
1207 break;
1208 case INDEX_op_divu_i32:
1209 tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 1);
1210 break;
1212 case INDEX_op_rem_i32:
1213 case INDEX_op_remu_i32:
1214 tcg_out_div32(s, TCG_REG_T1, args[1], args[2], const_args[2],
1215 opc == INDEX_op_remu_i32);
1216 tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2],
1217 ARITH_UMUL);
1218 tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB);
1219 break;
1221 case INDEX_op_brcond_i32:
1222 tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
1223 args[3]);
1224 break;
1225 case INDEX_op_setcond_i32:
1226 tcg_out_setcond_i32(s, args[3], args[0], args[1],
1227 args[2], const_args[2]);
1228 break;
1229 case INDEX_op_movcond_i32:
1230 tcg_out_movcond_i32(s, args[5], args[0], args[1],
1231 args[2], const_args[2], args[3], const_args[3]);
1232 break;
1234 #if TCG_TARGET_REG_BITS == 32
1235 case INDEX_op_brcond2_i32:
1236 tcg_out_brcond2_i32(s, args[4], args[0], args[1],
1237 args[2], const_args[2],
1238 args[3], const_args[3], args[5]);
1239 break;
1240 case INDEX_op_setcond2_i32:
1241 tcg_out_setcond2_i32(s, args[5], args[0], args[1], args[2],
1242 args[3], const_args[3],
1243 args[4], const_args[4]);
1244 break;
1245 case INDEX_op_add2_i32:
1246 tcg_out_arithc(s, args[0], args[2], args[4], const_args[4],
1247 ARITH_ADDCC);
1248 tcg_out_arithc(s, args[1], args[3], args[5], const_args[5],
1249 ARITH_ADDX);
1250 break;
1251 case INDEX_op_sub2_i32:
1252 tcg_out_arithc(s, args[0], args[2], args[4], const_args[4],
1253 ARITH_SUBCC);
1254 tcg_out_arithc(s, args[1], args[3], args[5], const_args[5],
1255 ARITH_SUBX);
1256 break;
1257 case INDEX_op_mulu2_i32:
1258 tcg_out_arithc(s, args[0], args[2], args[3], const_args[3],
1259 ARITH_UMUL);
1260 tcg_out_rdy(s, args[1]);
1261 break;
1262 #endif
1264 case INDEX_op_qemu_ld8u:
1265 tcg_out_qemu_ld(s, args, 0);
1266 break;
1267 case INDEX_op_qemu_ld8s:
1268 tcg_out_qemu_ld(s, args, 0 | 4);
1269 break;
1270 case INDEX_op_qemu_ld16u:
1271 tcg_out_qemu_ld(s, args, 1);
1272 break;
1273 case INDEX_op_qemu_ld16s:
1274 tcg_out_qemu_ld(s, args, 1 | 4);
1275 break;
1276 case INDEX_op_qemu_ld32:
1277 #if TCG_TARGET_REG_BITS == 64
1278 case INDEX_op_qemu_ld32u:
1279 #endif
1280 tcg_out_qemu_ld(s, args, 2);
1281 break;
1282 #if TCG_TARGET_REG_BITS == 64
1283 case INDEX_op_qemu_ld32s:
1284 tcg_out_qemu_ld(s, args, 2 | 4);
1285 break;
1286 #endif
1287 case INDEX_op_qemu_ld64:
1288 tcg_out_qemu_ld(s, args, 3);
1289 break;
1290 case INDEX_op_qemu_st8:
1291 tcg_out_qemu_st(s, args, 0);
1292 break;
1293 case INDEX_op_qemu_st16:
1294 tcg_out_qemu_st(s, args, 1);
1295 break;
1296 case INDEX_op_qemu_st32:
1297 tcg_out_qemu_st(s, args, 2);
1298 break;
1299 case INDEX_op_qemu_st64:
1300 tcg_out_qemu_st(s, args, 3);
1301 break;
1303 #if TCG_TARGET_REG_BITS == 64
1304 case INDEX_op_movi_i64:
1305 tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
1306 break;
1307 case INDEX_op_ld32s_i64:
1308 tcg_out_ldst(s, args[0], args[1], args[2], LDSW);
1309 break;
1310 case INDEX_op_ld_i64:
1311 tcg_out_ldst(s, args[0], args[1], args[2], LDX);
1312 break;
1313 case INDEX_op_st_i64:
1314 tcg_out_ldst(s, args[0], args[1], args[2], STX);
1315 break;
1316 case INDEX_op_shl_i64:
1317 c = SHIFT_SLLX;
1318 do_shift64:
1319 /* Limit immediate shift count lest we create an illegal insn. */
1320 tcg_out_arithc(s, args[0], args[1], args[2] & 63, const_args[2], c);
1321 break;
1322 case INDEX_op_shr_i64:
1323 c = SHIFT_SRLX;
1324 goto do_shift64;
1325 case INDEX_op_sar_i64:
1326 c = SHIFT_SRAX;
1327 goto do_shift64;
1328 case INDEX_op_mul_i64:
1329 c = ARITH_MULX;
1330 goto gen_arith;
1331 case INDEX_op_div_i64:
1332 c = ARITH_SDIVX;
1333 goto gen_arith;
1334 case INDEX_op_divu_i64:
1335 c = ARITH_UDIVX;
1336 goto gen_arith;
1337 case INDEX_op_rem_i64:
1338 case INDEX_op_remu_i64:
1339 tcg_out_arithc(s, TCG_REG_T1, args[1], args[2], const_args[2],
1340 opc == INDEX_op_rem_i64 ? ARITH_SDIVX : ARITH_UDIVX);
1341 tcg_out_arithc(s, TCG_REG_T1, TCG_REG_T1, args[2], const_args[2],
1342 ARITH_MULX);
1343 tcg_out_arith(s, args[0], args[1], TCG_REG_T1, ARITH_SUB);
1344 break;
1345 case INDEX_op_ext32s_i64:
1346 if (const_args[1]) {
1347 tcg_out_movi(s, TCG_TYPE_I64, args[0], (int32_t)args[1]);
1348 } else {
1349 tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRA);
1351 break;
1352 case INDEX_op_ext32u_i64:
1353 if (const_args[1]) {
1354 tcg_out_movi_imm32(s, args[0], args[1]);
1355 } else {
1356 tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
1358 break;
1360 case INDEX_op_brcond_i64:
1361 tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
1362 args[3]);
1363 break;
1364 case INDEX_op_setcond_i64:
1365 tcg_out_setcond_i64(s, args[3], args[0], args[1],
1366 args[2], const_args[2]);
1367 break;
1368 case INDEX_op_movcond_i64:
1369 tcg_out_movcond_i64(s, args[5], args[0], args[1],
1370 args[2], const_args[2], args[3], const_args[3]);
1371 break;
1372 #endif
1373 gen_arith:
1374 tcg_out_arithc(s, args[0], args[1], args[2], const_args[2], c);
1375 break;
1377 gen_arith1:
1378 tcg_out_arithc(s, args[0], TCG_REG_G0, args[1], const_args[1], c);
1379 break;
1381 default:
1382 fprintf(stderr, "unknown opcode 0x%x\n", opc);
1383 tcg_abort();
1387 static const TCGTargetOpDef sparc_op_defs[] = {
1388 { INDEX_op_exit_tb, { } },
1389 { INDEX_op_goto_tb, { } },
1390 { INDEX_op_call, { "ri" } },
1391 { INDEX_op_br, { } },
1393 { INDEX_op_mov_i32, { "r", "r" } },
1394 { INDEX_op_movi_i32, { "r" } },
1395 { INDEX_op_ld8u_i32, { "r", "r" } },
1396 { INDEX_op_ld8s_i32, { "r", "r" } },
1397 { INDEX_op_ld16u_i32, { "r", "r" } },
1398 { INDEX_op_ld16s_i32, { "r", "r" } },
1399 { INDEX_op_ld_i32, { "r", "r" } },
1400 { INDEX_op_st8_i32, { "r", "r" } },
1401 { INDEX_op_st16_i32, { "r", "r" } },
1402 { INDEX_op_st_i32, { "r", "r" } },
1404 { INDEX_op_add_i32, { "r", "r", "rJ" } },
1405 { INDEX_op_mul_i32, { "r", "r", "rJ" } },
1406 { INDEX_op_div_i32, { "r", "r", "rJ" } },
1407 { INDEX_op_divu_i32, { "r", "r", "rJ" } },
1408 { INDEX_op_rem_i32, { "r", "r", "rJ" } },
1409 { INDEX_op_remu_i32, { "r", "r", "rJ" } },
1410 { INDEX_op_sub_i32, { "r", "r", "rJ" } },
1411 { INDEX_op_and_i32, { "r", "r", "rJ" } },
1412 { INDEX_op_andc_i32, { "r", "r", "rJ" } },
1413 { INDEX_op_or_i32, { "r", "r", "rJ" } },
1414 { INDEX_op_orc_i32, { "r", "r", "rJ" } },
1415 { INDEX_op_xor_i32, { "r", "r", "rJ" } },
1417 { INDEX_op_shl_i32, { "r", "r", "rJ" } },
1418 { INDEX_op_shr_i32, { "r", "r", "rJ" } },
1419 { INDEX_op_sar_i32, { "r", "r", "rJ" } },
1421 { INDEX_op_neg_i32, { "r", "rJ" } },
1422 { INDEX_op_not_i32, { "r", "rJ" } },
1424 { INDEX_op_brcond_i32, { "r", "rJ" } },
1425 { INDEX_op_setcond_i32, { "r", "r", "rJ" } },
1426 { INDEX_op_movcond_i32, { "r", "r", "rJ", "rI", "0" } },
1428 #if TCG_TARGET_REG_BITS == 32
1429 { INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } },
1430 { INDEX_op_setcond2_i32, { "r", "r", "r", "rJ", "rJ" } },
1431 { INDEX_op_add2_i32, { "r", "r", "r", "r", "rJ", "rJ" } },
1432 { INDEX_op_sub2_i32, { "r", "r", "r", "r", "rJ", "rJ" } },
1433 { INDEX_op_mulu2_i32, { "r", "r", "r", "rJ" } },
1434 #endif
1436 #if TCG_TARGET_REG_BITS == 64
1437 { INDEX_op_mov_i64, { "r", "r" } },
1438 { INDEX_op_movi_i64, { "r" } },
1439 { INDEX_op_ld8u_i64, { "r", "r" } },
1440 { INDEX_op_ld8s_i64, { "r", "r" } },
1441 { INDEX_op_ld16u_i64, { "r", "r" } },
1442 { INDEX_op_ld16s_i64, { "r", "r" } },
1443 { INDEX_op_ld32u_i64, { "r", "r" } },
1444 { INDEX_op_ld32s_i64, { "r", "r" } },
1445 { INDEX_op_ld_i64, { "r", "r" } },
1446 { INDEX_op_st8_i64, { "r", "r" } },
1447 { INDEX_op_st16_i64, { "r", "r" } },
1448 { INDEX_op_st32_i64, { "r", "r" } },
1449 { INDEX_op_st_i64, { "r", "r" } },
1451 { INDEX_op_add_i64, { "r", "r", "rJ" } },
1452 { INDEX_op_mul_i64, { "r", "r", "rJ" } },
1453 { INDEX_op_div_i64, { "r", "r", "rJ" } },
1454 { INDEX_op_divu_i64, { "r", "r", "rJ" } },
1455 { INDEX_op_rem_i64, { "r", "r", "rJ" } },
1456 { INDEX_op_remu_i64, { "r", "r", "rJ" } },
1457 { INDEX_op_sub_i64, { "r", "r", "rJ" } },
1458 { INDEX_op_and_i64, { "r", "r", "rJ" } },
1459 { INDEX_op_andc_i64, { "r", "r", "rJ" } },
1460 { INDEX_op_or_i64, { "r", "r", "rJ" } },
1461 { INDEX_op_orc_i64, { "r", "r", "rJ" } },
1462 { INDEX_op_xor_i64, { "r", "r", "rJ" } },
1464 { INDEX_op_shl_i64, { "r", "r", "rJ" } },
1465 { INDEX_op_shr_i64, { "r", "r", "rJ" } },
1466 { INDEX_op_sar_i64, { "r", "r", "rJ" } },
1468 { INDEX_op_neg_i64, { "r", "rJ" } },
1469 { INDEX_op_not_i64, { "r", "rJ" } },
1471 { INDEX_op_ext32s_i64, { "r", "ri" } },
1472 { INDEX_op_ext32u_i64, { "r", "ri" } },
1474 { INDEX_op_brcond_i64, { "r", "rJ" } },
1475 { INDEX_op_setcond_i64, { "r", "r", "rJ" } },
1476 { INDEX_op_movcond_i64, { "r", "r", "rJ", "rI", "0" } },
1477 #endif
1479 #if TCG_TARGET_REG_BITS == 64
1480 { INDEX_op_qemu_ld8u, { "r", "L" } },
1481 { INDEX_op_qemu_ld8s, { "r", "L" } },
1482 { INDEX_op_qemu_ld16u, { "r", "L" } },
1483 { INDEX_op_qemu_ld16s, { "r", "L" } },
1484 { INDEX_op_qemu_ld32, { "r", "L" } },
1485 { INDEX_op_qemu_ld32u, { "r", "L" } },
1486 { INDEX_op_qemu_ld32s, { "r", "L" } },
1487 { INDEX_op_qemu_ld64, { "r", "L" } },
1489 { INDEX_op_qemu_st8, { "L", "L" } },
1490 { INDEX_op_qemu_st16, { "L", "L" } },
1491 { INDEX_op_qemu_st32, { "L", "L" } },
1492 { INDEX_op_qemu_st64, { "L", "L" } },
1493 #elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
1494 { INDEX_op_qemu_ld8u, { "r", "L" } },
1495 { INDEX_op_qemu_ld8s, { "r", "L" } },
1496 { INDEX_op_qemu_ld16u, { "r", "L" } },
1497 { INDEX_op_qemu_ld16s, { "r", "L" } },
1498 { INDEX_op_qemu_ld32, { "r", "L" } },
1499 { INDEX_op_qemu_ld64, { "r", "r", "L" } },
1501 { INDEX_op_qemu_st8, { "L", "L" } },
1502 { INDEX_op_qemu_st16, { "L", "L" } },
1503 { INDEX_op_qemu_st32, { "L", "L" } },
1504 { INDEX_op_qemu_st64, { "L", "L", "L" } },
1505 #else
1506 { INDEX_op_qemu_ld8u, { "r", "L", "L" } },
1507 { INDEX_op_qemu_ld8s, { "r", "L", "L" } },
1508 { INDEX_op_qemu_ld16u, { "r", "L", "L" } },
1509 { INDEX_op_qemu_ld16s, { "r", "L", "L" } },
1510 { INDEX_op_qemu_ld32, { "r", "L", "L" } },
1511 { INDEX_op_qemu_ld64, { "L", "L", "L", "L" } },
1513 { INDEX_op_qemu_st8, { "L", "L", "L" } },
1514 { INDEX_op_qemu_st16, { "L", "L", "L" } },
1515 { INDEX_op_qemu_st32, { "L", "L", "L" } },
1516 { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },
1517 #endif
1519 { -1 },
1522 static void tcg_target_init(TCGContext *s)
1524 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1525 #if TCG_TARGET_REG_BITS == 64
1526 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1527 #endif
1528 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1529 (1 << TCG_REG_G1) |
1530 (1 << TCG_REG_G2) |
1531 (1 << TCG_REG_G3) |
1532 (1 << TCG_REG_G4) |
1533 (1 << TCG_REG_G5) |
1534 (1 << TCG_REG_G6) |
1535 (1 << TCG_REG_G7) |
1536 (1 << TCG_REG_O0) |
1537 (1 << TCG_REG_O1) |
1538 (1 << TCG_REG_O2) |
1539 (1 << TCG_REG_O3) |
1540 (1 << TCG_REG_O4) |
1541 (1 << TCG_REG_O5) |
1542 (1 << TCG_REG_O7));
1544 tcg_regset_clear(s->reserved_regs);
1545 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */
1546 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */
1547 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */
1548 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); /* frame pointer */
1549 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); /* return address */
1550 tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */
1551 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */
1552 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
1554 tcg_add_target_add_op_defs(sparc_op_defs);
1557 #if TCG_TARGET_REG_BITS == 64
1558 # define ELF_HOST_MACHINE EM_SPARCV9
1559 #else
1560 # define ELF_HOST_MACHINE EM_SPARC32PLUS
1561 # define ELF_HOST_FLAGS EF_SPARC_32PLUS
1562 #endif
1564 typedef struct {
1565 uint32_t len __attribute__((aligned((sizeof(void *)))));
1566 uint32_t id;
1567 uint8_t version;
1568 char augmentation[1];
1569 uint8_t code_align;
1570 uint8_t data_align;
1571 uint8_t return_column;
1572 } DebugFrameCIE;
1574 typedef struct {
1575 uint32_t len __attribute__((aligned((sizeof(void *)))));
1576 uint32_t cie_offset;
1577 tcg_target_long func_start __attribute__((packed));
1578 tcg_target_long func_len __attribute__((packed));
1579 uint8_t def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2];
1580 uint8_t win_save;
1581 uint8_t ret_save[3];
1582 } DebugFrameFDE;
1584 typedef struct {
1585 DebugFrameCIE cie;
1586 DebugFrameFDE fde;
1587 } DebugFrame;
1589 static DebugFrame debug_frame = {
1590 .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
1591 .cie.id = -1,
1592 .cie.version = 1,
1593 .cie.code_align = 1,
1594 .cie.data_align = -sizeof(void *) & 0x7f,
1595 .cie.return_column = 15, /* o7 */
1597 .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */
1598 .fde.def_cfa = {
1599 #if TCG_TARGET_REG_BITS == 64
1600 12, 30, /* DW_CFA_def_cfa i6, 2047 */
1601 (2047 & 0x7f) | 0x80, (2047 >> 7)
1602 #else
1603 13, 30 /* DW_CFA_def_cfa_register i6 */
1604 #endif
1606 .fde.win_save = 0x2d, /* DW_CFA_GNU_window_save */
1607 .fde.ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
1610 void tcg_register_jit(void *buf, size_t buf_size)
1612 debug_frame.fde.func_start = (tcg_target_long) buf;
1613 debug_frame.fde.func_len = buf_size;
1615 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
1618 void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
1620 uint32_t *ptr = (uint32_t *)jmp_addr;
1621 tcg_target_long disp = (tcg_target_long)(addr - jmp_addr) >> 2;
1623 /* We can reach the entire address space for 32-bit. For 64-bit
1624 the code_gen_buffer can't be larger than 2GB. */
1625 if (TCG_TARGET_REG_BITS == 64 && !check_fit_tl(disp, 30)) {
1626 tcg_abort();
1629 *ptr = CALL | (disp & 0x3fffffff);
1630 flush_icache_range(jmp_addr, jmp_addr + 4);