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
25 #include "tcg-be-null.h"
28 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
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. */
77 # define ALL_64 0xffffffffu
79 # define ALL_64 0xffffu
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
89 # define TCG_GUEST_BASE_REG TCG_REG_G0
92 static const int tcg_target_reg_alloc_order[] = {
122 static const int tcg_target_call_iarg_regs[6] = {
131 static const int tcg_target_call_oarg_regs[] = {
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)
170 #define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2))
179 #define MOVCC_ICC (1 << 18)
180 #define MOVCC_XCC (1 << 18 | 1 << 12)
183 #define BPCC_XCC (2 << 20)
184 #define BPCC_PT (1 << 19)
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 ARITH_ADDXC (INSN_OP(2) | INSN_OP3(0x36) | INSN_OPF(0x11))
214 #define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25))
215 #define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26))
216 #define SHIFT_SRA (INSN_OP(2) | INSN_OP3(0x27))
218 #define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12))
219 #define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
220 #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
222 #define RDY (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0))
223 #define WRY (INSN_OP(2) | INSN_OP3(0x30) | INSN_RD(0))
224 #define JMPL (INSN_OP(2) | INSN_OP3(0x38))
225 #define RETURN (INSN_OP(2) | INSN_OP3(0x39))
226 #define SAVE (INSN_OP(2) | INSN_OP3(0x3c))
227 #define RESTORE (INSN_OP(2) | INSN_OP3(0x3d))
228 #define SETHI (INSN_OP(0) | INSN_OP2(0x4))
229 #define CALL INSN_OP(1)
230 #define LDUB (INSN_OP(3) | INSN_OP3(0x01))
231 #define LDSB (INSN_OP(3) | INSN_OP3(0x09))
232 #define LDUH (INSN_OP(3) | INSN_OP3(0x02))
233 #define LDSH (INSN_OP(3) | INSN_OP3(0x0a))
234 #define LDUW (INSN_OP(3) | INSN_OP3(0x00))
235 #define LDSW (INSN_OP(3) | INSN_OP3(0x08))
236 #define LDX (INSN_OP(3) | INSN_OP3(0x0b))
237 #define STB (INSN_OP(3) | INSN_OP3(0x05))
238 #define STH (INSN_OP(3) | INSN_OP3(0x06))
239 #define STW (INSN_OP(3) | INSN_OP3(0x04))
240 #define STX (INSN_OP(3) | INSN_OP3(0x0e))
241 #define LDUBA (INSN_OP(3) | INSN_OP3(0x11))
242 #define LDSBA (INSN_OP(3) | INSN_OP3(0x19))
243 #define LDUHA (INSN_OP(3) | INSN_OP3(0x12))
244 #define LDSHA (INSN_OP(3) | INSN_OP3(0x1a))
245 #define LDUWA (INSN_OP(3) | INSN_OP3(0x10))
246 #define LDSWA (INSN_OP(3) | INSN_OP3(0x18))
247 #define LDXA (INSN_OP(3) | INSN_OP3(0x1b))
248 #define STBA (INSN_OP(3) | INSN_OP3(0x15))
249 #define STHA (INSN_OP(3) | INSN_OP3(0x16))
250 #define STWA (INSN_OP(3) | INSN_OP3(0x14))
251 #define STXA (INSN_OP(3) | INSN_OP3(0x1e))
253 #ifndef ASI_PRIMARY_LITTLE
254 #define ASI_PRIMARY_LITTLE 0x88
257 #define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
258 #define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
259 #define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
260 #define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
261 #define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE))
263 #define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE))
264 #define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE))
265 #define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE))
267 #ifndef use_vis3_instructions
268 bool use_vis3_instructions;
271 static inline int check_fit_i64(int64_t val, unsigned int bits)
273 return val == sextract64(val, 0, bits);
276 static inline int check_fit_i32(int32_t val, unsigned int bits)
278 return val == sextract32(val, 0, bits);
281 #define check_fit_tl check_fit_i64
283 # define check_fit_ptr check_fit_i64
285 # define check_fit_ptr check_fit_i32
288 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
289 intptr_t value, intptr_t addend)
294 value = tcg_ptr_byte_diff((tcg_insn_unit *)value, code_ptr);
297 case R_SPARC_WDISP16:
298 if (!check_fit_ptr(value >> 2, 16)) {
302 insn &= ~INSN_OFF16(-1);
303 insn |= INSN_OFF16(value);
306 case R_SPARC_WDISP19:
307 if (!check_fit_ptr(value >> 2, 19)) {
311 insn &= ~INSN_OFF19(-1);
312 insn |= INSN_OFF19(value);
320 /* parse target specific constraints */
321 static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
328 ct->ct |= TCG_CT_REG;
329 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
332 ct->ct |= TCG_CT_REG;
333 tcg_regset_set32(ct->u.regs, 0, ALL_64);
335 case 'A': /* qemu_ld/st address constraint */
336 ct->ct |= TCG_CT_REG;
337 tcg_regset_set32(ct->u.regs, 0,
338 TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff);
340 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
341 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
342 tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
344 case 's': /* qemu_st data 32-bit constraint */
345 ct->ct |= TCG_CT_REG;
346 tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
347 goto reserve_helpers;
348 case 'S': /* qemu_st data 64-bit constraint */
349 ct->ct |= TCG_CT_REG;
350 tcg_regset_set32(ct->u.regs, 0, ALL_64);
351 goto reserve_helpers;
353 ct->ct |= TCG_CT_CONST_S11;
356 ct->ct |= TCG_CT_CONST_S13;
359 ct->ct |= TCG_CT_CONST_ZERO;
369 /* test if a constant matches the constraint */
370 static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
371 const TCGArgConstraint *arg_ct)
375 if (ct & TCG_CT_CONST) {
379 if (type == TCG_TYPE_I32) {
383 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
385 } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) {
387 } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) {
394 static inline void tcg_out_arith(TCGContext *s, TCGReg rd, TCGReg rs1,
397 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) | INSN_RS2(rs2));
400 static inline void tcg_out_arithi(TCGContext *s, TCGReg rd, TCGReg rs1,
401 int32_t offset, int op)
403 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) | INSN_IMM13(offset));
406 static void tcg_out_arithc(TCGContext *s, TCGReg rd, TCGReg rs1,
407 int32_t val2, int val2const, int op)
409 tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1)
410 | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
413 static inline void tcg_out_mov(TCGContext *s, TCGType type,
414 TCGReg ret, TCGReg arg)
417 tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
421 static inline void tcg_out_sethi(TCGContext *s, TCGReg ret, uint32_t arg)
423 tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10));
426 static inline void tcg_out_movi_imm13(TCGContext *s, TCGReg ret, int32_t arg)
428 tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR);
431 static void tcg_out_movi(TCGContext *s, TCGType type,
432 TCGReg ret, tcg_target_long arg)
434 tcg_target_long hi, lo = (int32_t)arg;
436 /* Make sure we test 32-bit constants for imm13 properly. */
437 if (type == TCG_TYPE_I32) {
441 /* A 13-bit constant sign-extended to 64-bits. */
442 if (check_fit_tl(arg, 13)) {
443 tcg_out_movi_imm13(s, ret, arg);
447 /* A 32-bit constant, or 32-bit zero-extended to 64-bits. */
448 if (type == TCG_TYPE_I32 || arg == (uint32_t)arg) {
449 tcg_out_sethi(s, ret, arg);
451 tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR);
456 /* A 32-bit constant sign-extended to 64-bits. */
458 tcg_out_sethi(s, ret, ~arg);
459 tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR);
463 /* A 64-bit constant decomposed into 2 32-bit pieces. */
464 if (check_fit_i32(lo, 13)) {
465 hi = (arg - lo) >> 32;
466 tcg_out_movi(s, TCG_TYPE_I32, ret, hi);
467 tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
468 tcg_out_arithi(s, ret, ret, lo, ARITH_ADD);
471 tcg_out_movi(s, TCG_TYPE_I32, ret, hi);
472 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T2, lo);
473 tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX);
474 tcg_out_arith(s, ret, ret, TCG_REG_T2, ARITH_OR);
478 static inline void tcg_out_ldst_rr(TCGContext *s, TCGReg data, TCGReg a1,
481 tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2));
484 static void tcg_out_ldst(TCGContext *s, TCGReg ret, TCGReg addr,
485 intptr_t offset, int op)
487 if (check_fit_ptr(offset, 13)) {
488 tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
491 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, offset);
492 tcg_out_ldst_rr(s, ret, addr, TCG_REG_T1, op);
496 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
497 TCGReg arg1, intptr_t arg2)
499 tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX));
502 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
503 TCGReg arg1, intptr_t arg2)
505 tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
508 static void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, uintptr_t arg)
510 tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
511 tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, arg & 0x3ff);
514 static inline void tcg_out_sety(TCGContext *s, TCGReg rs)
516 tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
519 static inline void tcg_out_rdy(TCGContext *s, TCGReg rd)
521 tcg_out32(s, RDY | INSN_RD(rd));
524 static void tcg_out_div32(TCGContext *s, TCGReg rd, TCGReg rs1,
525 int32_t val2, int val2const, int uns)
527 /* Load Y with the sign/zero extension of RS1 to 64-bits. */
529 tcg_out_sety(s, TCG_REG_G0);
531 tcg_out_arithi(s, TCG_REG_T1, rs1, 31, SHIFT_SRA);
532 tcg_out_sety(s, TCG_REG_T1);
535 tcg_out_arithc(s, rd, rs1, val2, val2const,
536 uns ? ARITH_UDIV : ARITH_SDIV);
539 static inline void tcg_out_nop(TCGContext *s)
541 tcg_out_sethi(s, TCG_REG_G0, 0);
544 static const uint8_t tcg_cond_to_bcond[] = {
545 [TCG_COND_EQ] = COND_E,
546 [TCG_COND_NE] = COND_NE,
547 [TCG_COND_LT] = COND_L,
548 [TCG_COND_GE] = COND_GE,
549 [TCG_COND_LE] = COND_LE,
550 [TCG_COND_GT] = COND_G,
551 [TCG_COND_LTU] = COND_CS,
552 [TCG_COND_GEU] = COND_CC,
553 [TCG_COND_LEU] = COND_LEU,
554 [TCG_COND_GTU] = COND_GU,
557 static const uint8_t tcg_cond_to_rcond[] = {
558 [TCG_COND_EQ] = RCOND_Z,
559 [TCG_COND_NE] = RCOND_NZ,
560 [TCG_COND_LT] = RCOND_LZ,
561 [TCG_COND_GT] = RCOND_GZ,
562 [TCG_COND_LE] = RCOND_LEZ,
563 [TCG_COND_GE] = RCOND_GEZ
566 static void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19)
568 tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19);
571 static void tcg_out_bpcc(TCGContext *s, int scond, int flags, int label)
573 TCGLabel *l = &s->labels[label];
577 off19 = INSN_OFF19(tcg_pcrel_diff(s, l->u.value_ptr));
579 /* Make sure to preserve destinations during retranslation. */
580 off19 = *s->code_ptr & INSN_OFF19(-1);
581 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, label, 0);
583 tcg_out_bpcc0(s, scond, flags, off19);
586 static void tcg_out_cmp(TCGContext *s, TCGReg c1, int32_t c2, int c2const)
588 tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
591 static void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGReg arg1,
592 int32_t arg2, int const_arg2, int label)
594 tcg_out_cmp(s, arg1, arg2, const_arg2);
595 tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, label);
599 static void tcg_out_movcc(TCGContext *s, TCGCond cond, int cc, TCGReg ret,
600 int32_t v1, int v1const)
602 tcg_out32(s, ARITH_MOVCC | cc | INSN_RD(ret)
603 | INSN_RS1(tcg_cond_to_bcond[cond])
604 | (v1const ? INSN_IMM11(v1) : INSN_RS2(v1)));
607 static void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
608 TCGReg c1, int32_t c2, int c2const,
609 int32_t v1, int v1const)
611 tcg_out_cmp(s, c1, c2, c2const);
612 tcg_out_movcc(s, cond, MOVCC_ICC, ret, v1, v1const);
615 static void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1,
616 int32_t arg2, int const_arg2, int label)
618 /* For 64-bit signed comparisons vs zero, we can avoid the compare. */
619 if (arg2 == 0 && !is_unsigned_cond(cond)) {
620 TCGLabel *l = &s->labels[label];
624 off16 = INSN_OFF16(tcg_pcrel_diff(s, l->u.value_ptr));
626 /* Make sure to preserve destinations during retranslation. */
627 off16 = *s->code_ptr & INSN_OFF16(-1);
628 tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, label, 0);
630 tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1)
631 | INSN_COND(tcg_cond_to_rcond[cond]) | off16);
633 tcg_out_cmp(s, arg1, arg2, const_arg2);
634 tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, label);
639 static void tcg_out_movr(TCGContext *s, TCGCond cond, TCGReg ret, TCGReg c1,
640 int32_t v1, int v1const)
642 tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1)
643 | (tcg_cond_to_rcond[cond] << 10)
644 | (v1const ? INSN_IMM10(v1) : INSN_RS2(v1)));
647 static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
648 TCGReg c1, int32_t c2, int c2const,
649 int32_t v1, int v1const)
651 /* For 64-bit signed comparisons vs zero, we can avoid the compare.
652 Note that the immediate range is one bit smaller, so we must check
654 if (c2 == 0 && !is_unsigned_cond(cond)
655 && (!v1const || check_fit_i32(v1, 10))) {
656 tcg_out_movr(s, cond, ret, c1, v1, v1const);
658 tcg_out_cmp(s, c1, c2, c2const);
659 tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const);
663 static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
664 TCGReg c1, int32_t c2, int c2const)
666 /* For 32-bit comparisons, we can play games with ADDX/SUBX. */
670 /* The result of the comparison is in the carry bit. */
675 /* For equality, we can transform to inequality vs zero. */
677 tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR);
679 c1 = TCG_REG_G0, c2 = ret, c2const = 0;
680 cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU);
685 /* If we don't need to load a constant into a register, we can
686 swap the operands on GTU/LEU. There's no benefit to loading
687 the constant into a temporary register. */
688 if (!c2const || c2 == 0) {
693 cond = tcg_swap_cond(cond);
699 tcg_out_cmp(s, c1, c2, c2const);
700 tcg_out_movi_imm13(s, ret, 0);
701 tcg_out_movcc(s, cond, MOVCC_ICC, ret, 1, 1);
705 tcg_out_cmp(s, c1, c2, c2const);
706 if (cond == TCG_COND_LTU) {
707 tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDX);
709 tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBX);
713 static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
714 TCGReg c1, int32_t c2, int c2const)
716 /* For 64-bit signed comparisons vs zero, we can avoid the compare
717 if the input does not overlap the output. */
718 if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) {
719 tcg_out_movi_imm13(s, ret, 0);
720 tcg_out_movr(s, cond, ret, c1, 1, 1);
722 tcg_out_cmp(s, c1, c2, c2const);
723 tcg_out_movi_imm13(s, ret, 0);
724 tcg_out_movcc(s, cond, MOVCC_XCC, ret, 1, 1);
728 static void tcg_out_addsub2_i32(TCGContext *s, TCGReg rl, TCGReg rh,
729 TCGReg al, TCGReg ah, int32_t bl, int blconst,
730 int32_t bh, int bhconst, int opl, int oph)
732 TCGReg tmp = TCG_REG_T1;
734 /* Note that the low parts are fully consumed before tmp is set. */
735 if (rl != ah && (bhconst || rl != bh)) {
739 tcg_out_arithc(s, tmp, al, bl, blconst, opl);
740 tcg_out_arithc(s, rh, ah, bh, bhconst, oph);
741 tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
744 static void tcg_out_addsub2_i64(TCGContext *s, TCGReg rl, TCGReg rh,
745 TCGReg al, TCGReg ah, int32_t bl, int blconst,
746 int32_t bh, int bhconst, bool is_sub)
748 TCGReg tmp = TCG_REG_T1;
750 /* Note that the low parts are fully consumed before tmp is set. */
751 if (rl != ah && (bhconst || rl != bh)) {
755 tcg_out_arithc(s, tmp, al, bl, blconst, is_sub ? ARITH_SUBCC : ARITH_ADDCC);
757 if (use_vis3_instructions && !is_sub) {
758 /* Note that ADDXC doesn't accept immediates. */
759 if (bhconst && bh != 0) {
760 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_T2, bh);
763 tcg_out_arith(s, rh, ah, bh, ARITH_ADDXC);
764 } else if (bh == TCG_REG_G0) {
765 /* If we have a zero, we can perform the operation in two insns,
766 with the arithmetic first, and a conditional move into place. */
768 tcg_out_arithi(s, TCG_REG_T2, ah, 1,
769 is_sub ? ARITH_SUB : ARITH_ADD);
770 tcg_out_movcc(s, TCG_COND_LTU, MOVCC_XCC, rh, TCG_REG_T2, 0);
772 tcg_out_arithi(s, rh, ah, 1, is_sub ? ARITH_SUB : ARITH_ADD);
773 tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, rh, ah, 0);
776 /* Otherwise adjust BH as if there is carry into T2 ... */
778 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_T2, bh + (is_sub ? -1 : 1));
780 tcg_out_arithi(s, TCG_REG_T2, bh, 1,
781 is_sub ? ARITH_SUB : ARITH_ADD);
783 /* ... smoosh T2 back to original BH if carry is clear ... */
784 tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, TCG_REG_T2, bh, bhconst);
785 /* ... and finally perform the arithmetic with the new operand. */
786 tcg_out_arith(s, rh, ah, TCG_REG_T2, is_sub ? ARITH_SUB : ARITH_ADD);
789 tcg_out_mov(s, TCG_TYPE_I64, rl, tmp);
792 static void tcg_out_call_nodelay(TCGContext *s, tcg_insn_unit *dest)
794 ptrdiff_t disp = tcg_pcrel_diff(s, dest);
796 if (disp == (int32_t)disp) {
797 tcg_out32(s, CALL | (uint32_t)disp >> 2);
799 uintptr_t desti = (uintptr_t)dest;
800 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, desti & ~0xfff);
801 tcg_out_arithi(s, TCG_REG_O7, TCG_REG_T1, desti & 0xfff, JMPL);
805 static void tcg_out_call(TCGContext *s, tcg_insn_unit *dest)
807 tcg_out_call_nodelay(s, dest);
811 #ifdef CONFIG_SOFTMMU
812 static tcg_insn_unit *qemu_ld_trampoline[16];
813 static tcg_insn_unit *qemu_st_trampoline[16];
815 static void build_trampolines(TCGContext *s)
817 static void * const qemu_ld_helpers[16] = {
818 [MO_UB] = helper_ret_ldub_mmu,
819 [MO_SB] = helper_ret_ldsb_mmu,
820 [MO_LEUW] = helper_le_lduw_mmu,
821 [MO_LESW] = helper_le_ldsw_mmu,
822 [MO_LEUL] = helper_le_ldul_mmu,
823 [MO_LEQ] = helper_le_ldq_mmu,
824 [MO_BEUW] = helper_be_lduw_mmu,
825 [MO_BESW] = helper_be_ldsw_mmu,
826 [MO_BEUL] = helper_be_ldul_mmu,
827 [MO_BEQ] = helper_be_ldq_mmu,
829 static void * const qemu_st_helpers[16] = {
830 [MO_UB] = helper_ret_stb_mmu,
831 [MO_LEUW] = helper_le_stw_mmu,
832 [MO_LEUL] = helper_le_stl_mmu,
833 [MO_LEQ] = helper_le_stq_mmu,
834 [MO_BEUW] = helper_be_stw_mmu,
835 [MO_BEUL] = helper_be_stl_mmu,
836 [MO_BEQ] = helper_be_stq_mmu,
842 for (i = 0; i < 16; ++i) {
843 if (qemu_ld_helpers[i] == NULL) {
847 /* May as well align the trampoline. */
848 while ((uintptr_t)s->code_ptr & 15) {
851 qemu_ld_trampoline[i] = s->code_ptr;
853 if (SPARC64 || TARGET_LONG_BITS == 32) {
856 /* Install the high part of the address. */
857 tcg_out_arithi(s, TCG_REG_O1, TCG_REG_O2, 32, SHIFT_SRLX);
861 /* Set the retaddr operand. */
862 tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
863 /* Set the env operand. */
864 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
866 tcg_out_call_nodelay(s, qemu_ld_helpers[i]);
867 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
870 for (i = 0; i < 16; ++i) {
871 if (qemu_st_helpers[i] == NULL) {
875 /* May as well align the trampoline. */
876 while ((uintptr_t)s->code_ptr & 15) {
879 qemu_st_trampoline[i] = s->code_ptr;
885 if (TARGET_LONG_BITS == 64) {
886 /* Install the high part of the address. */
887 tcg_out_arithi(s, ra, ra + 1, 32, SHIFT_SRLX);
892 if ((i & MO_SIZE) == MO_64) {
893 /* Install the high part of the data. */
894 tcg_out_arithi(s, ra, ra + 1, 32, SHIFT_SRLX);
899 /* Skip the mem_index argument. */
903 /* Set the retaddr operand. */
904 if (ra >= TCG_REG_O6) {
905 tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_O7, TCG_REG_CALL_STACK,
906 TCG_TARGET_CALL_STACK_OFFSET);
909 tcg_out_mov(s, TCG_TYPE_PTR, ra, TCG_REG_O7);
910 /* Set the env operand. */
911 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O0, TCG_AREG0);
913 tcg_out_call_nodelay(s, qemu_st_helpers[i]);
914 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_O7, ra);
919 /* Generate global QEMU prologue and epilogue code */
920 static void tcg_target_qemu_prologue(TCGContext *s)
922 int tmp_buf_size, frame_size;
924 /* The TCG temp buffer is at the top of the frame, immediately
925 below the frame pointer. */
926 tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long);
927 tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_STACK_BIAS - tmp_buf_size,
930 /* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
931 otherwise the minimal frame usable by callees. */
932 frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS;
933 frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size;
934 frame_size += TCG_TARGET_STACK_ALIGN - 1;
935 frame_size &= -TCG_TARGET_STACK_ALIGN;
936 tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
937 INSN_IMM13(-frame_size));
939 #ifdef CONFIG_USE_GUEST_BASE
940 if (GUEST_BASE != 0) {
941 tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
942 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
946 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL);
950 /* No epilogue required. We issue ret + restore directly in the TB. */
952 #ifdef CONFIG_SOFTMMU
953 build_trampolines(s);
957 #if defined(CONFIG_SOFTMMU)
958 /* Perform the TLB load and compare.
961 ADDRLO and ADDRHI contain the possible two parts of the address.
963 MEM_INDEX and S_BITS are the memory context and log2 size of the load.
965 WHICH is the offset into the CPUTLBEntry structure of the slot to read.
966 This should be offsetof addr_read or addr_write.
968 The result of the TLB comparison is in %[ix]cc. The sanitized address
969 is in the returned register, maybe %o0. The TLB addend is in %o1. */
971 static TCGReg tcg_out_tlb_load(TCGContext *s, TCGReg addr, int mem_index,
972 TCGMemOp s_bits, int which)
974 const TCGReg r0 = TCG_REG_O0;
975 const TCGReg r1 = TCG_REG_O1;
976 const TCGReg r2 = TCG_REG_O2;
979 /* Shift the page number down. */
980 tcg_out_arithi(s, r1, addr, TARGET_PAGE_BITS, SHIFT_SRL);
982 /* Mask out the page offset, except for the required alignment. */
983 tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_T1,
984 TARGET_PAGE_MASK | ((1 << s_bits) - 1));
986 /* Mask the tlb index. */
987 tcg_out_arithi(s, r1, r1, CPU_TLB_SIZE - 1, ARITH_AND);
989 /* Mask page, part 2. */
990 tcg_out_arith(s, r0, addr, TCG_REG_T1, ARITH_AND);
992 /* Shift the tlb index into place. */
993 tcg_out_arithi(s, r1, r1, CPU_TLB_ENTRY_BITS, SHIFT_SLL);
995 /* Relative to the current ENV. */
996 tcg_out_arith(s, r1, TCG_AREG0, r1, ARITH_ADD);
998 /* Find a base address that can load both tlb comparator and addend. */
999 tlb_ofs = offsetof(CPUArchState, tlb_table[mem_index][0]);
1000 if (!check_fit_ptr(tlb_ofs + sizeof(CPUTLBEntry), 13)) {
1001 if (tlb_ofs & ~0x3ff) {
1002 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, tlb_ofs & ~0x3ff);
1003 tcg_out_arith(s, r1, r1, TCG_REG_T1, ARITH_ADD);
1008 /* Load the tlb comparator and the addend. */
1009 tcg_out_ld(s, TCG_TYPE_TL, r2, r1, tlb_ofs + which);
1010 tcg_out_ld(s, TCG_TYPE_PTR, r1, r1, tlb_ofs+offsetof(CPUTLBEntry, addend));
1012 /* subcc arg0, arg2, %g0 */
1013 tcg_out_cmp(s, r0, r2, 0);
1015 /* If the guest address must be zero-extended, do so now. */
1016 if (SPARC64 && TARGET_LONG_BITS == 32) {
1017 tcg_out_arithi(s, r0, addr, 0, SHIFT_SRL);
1022 #endif /* CONFIG_SOFTMMU */
1024 static const int qemu_ld_opc[16] = {
1034 [MO_LEUW] = LDUH_LE,
1035 [MO_LESW] = LDSH_LE,
1036 [MO_LEUL] = LDUW_LE,
1037 [MO_LESL] = LDSW_LE,
1041 static const int qemu_st_opc[16] = {
1053 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr,
1054 TCGMemOp memop, int memi, bool is_64)
1056 #ifdef CONFIG_SOFTMMU
1057 TCGMemOp s_bits = memop & MO_SIZE;
1058 TCGReg addrz, param;
1059 tcg_insn_unit *func;
1060 tcg_insn_unit *label_ptr;
1062 addrz = tcg_out_tlb_load(s, addr, memi, s_bits,
1063 offsetof(CPUTLBEntry, addr_read));
1065 /* The fast path is exactly one insn. Thus we can perform the
1066 entire TLB Hit in the (annulled) delay slot of the branch
1067 over the TLB Miss case. */
1069 /* beq,a,pt %[xi]cc, label0 */
1070 label_ptr = s->code_ptr;
1071 tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
1072 | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
1074 tcg_out_ldst_rr(s, data, addrz, TCG_REG_O1, qemu_ld_opc[memop]);
1079 if (!SPARC64 && TARGET_LONG_BITS == 64) {
1080 /* Skip the high-part; we'll perform the extract in the trampoline. */
1083 tcg_out_mov(s, TCG_TYPE_REG, param++, addr);
1085 /* We use the helpers to extend SB and SW data, leaving the case
1086 of SL needing explicit extending below. */
1087 if ((memop & ~MO_BSWAP) == MO_SL) {
1088 func = qemu_ld_trampoline[memop & ~MO_SIGN];
1090 func = qemu_ld_trampoline[memop];
1092 assert(func != NULL);
1093 tcg_out_call_nodelay(s, func);
1095 tcg_out_movi(s, TCG_TYPE_I32, param, memi);
1097 /* Recall that all of the helpers return 64-bit results.
1098 Which complicates things for sparcv8plus. */
1100 /* We let the helper sign-extend SB and SW, but leave SL for here. */
1101 if (is_64 && (memop & ~MO_BSWAP) == MO_SL) {
1102 tcg_out_arithi(s, data, TCG_REG_O0, 0, SHIFT_SRA);
1104 tcg_out_mov(s, TCG_TYPE_REG, data, TCG_REG_O0);
1107 if (s_bits == MO_64) {
1108 tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, 32, SHIFT_SLLX);
1109 tcg_out_arithi(s, TCG_REG_O1, TCG_REG_O1, 0, SHIFT_SRL);
1110 tcg_out_arith(s, data, TCG_REG_O0, TCG_REG_O1, ARITH_OR);
1112 /* Re-extend from 32-bit rather than reassembling when we
1113 know the high register must be an extension. */
1114 tcg_out_arithi(s, data, TCG_REG_O1, 0,
1115 memop & MO_SIGN ? SHIFT_SRA : SHIFT_SRL);
1117 tcg_out_mov(s, TCG_TYPE_I32, data, TCG_REG_O1);
1121 *label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
1123 if (SPARC64 && TARGET_LONG_BITS == 32) {
1124 tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
1127 tcg_out_ldst_rr(s, data, addr,
1128 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1129 qemu_ld_opc[memop]);
1130 #endif /* CONFIG_SOFTMMU */
1133 static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr,
1134 TCGMemOp memop, int memi)
1136 #ifdef CONFIG_SOFTMMU
1137 TCGMemOp s_bits = memop & MO_SIZE;
1138 TCGReg addrz, param;
1139 tcg_insn_unit *func;
1140 tcg_insn_unit *label_ptr;
1142 addrz = tcg_out_tlb_load(s, addr, memi, s_bits,
1143 offsetof(CPUTLBEntry, addr_write));
1145 /* The fast path is exactly one insn. Thus we can perform the entire
1146 TLB Hit in the (annulled) delay slot of the branch over TLB Miss. */
1147 /* beq,a,pt %[xi]cc, label0 */
1148 label_ptr = s->code_ptr;
1149 tcg_out_bpcc0(s, COND_E, BPCC_A | BPCC_PT
1150 | (TARGET_LONG_BITS == 64 ? BPCC_XCC : BPCC_ICC), 0);
1152 tcg_out_ldst_rr(s, data, addrz, TCG_REG_O1, qemu_st_opc[memop]);
1157 if (!SPARC64 && TARGET_LONG_BITS == 64) {
1158 /* Skip the high-part; we'll perform the extract in the trampoline. */
1161 tcg_out_mov(s, TCG_TYPE_REG, param++, addr);
1162 if (!SPARC64 && s_bits == MO_64) {
1163 /* Skip the high-part; we'll perform the extract in the trampoline. */
1166 tcg_out_mov(s, TCG_TYPE_REG, param++, data);
1168 func = qemu_st_trampoline[memop];
1169 assert(func != NULL);
1170 tcg_out_call_nodelay(s, func);
1172 tcg_out_movi(s, TCG_TYPE_REG, param, memi);
1174 *label_ptr |= INSN_OFF19(tcg_ptr_byte_diff(s->code_ptr, label_ptr));
1176 if (SPARC64 && TARGET_LONG_BITS == 32) {
1177 tcg_out_arithi(s, TCG_REG_T1, addr, 0, SHIFT_SRL);
1180 tcg_out_ldst_rr(s, data, addr,
1181 (GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_G0),
1182 qemu_st_opc[memop]);
1183 #endif /* CONFIG_SOFTMMU */
1186 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
1187 const TCGArg args[TCG_MAX_OP_ARGS],
1188 const int const_args[TCG_MAX_OP_ARGS])
1193 /* Hoist the loads of the most common arguments. */
1200 case INDEX_op_exit_tb:
1201 if (check_fit_ptr(a0, 13)) {
1202 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
1203 tcg_out_movi_imm13(s, TCG_REG_O0, a0);
1205 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, a0 & ~0x3ff);
1206 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN);
1207 tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR);
1210 case INDEX_op_goto_tb:
1211 if (s->tb_jmp_offset) {
1212 /* direct jump method */
1213 s->tb_jmp_offset[a0] = tcg_current_code_size(s);
1214 /* Make sure to preserve links during retranslation. */
1215 tcg_out32(s, CALL | (*s->code_ptr & ~INSN_OP(-1)));
1217 /* indirect jump method */
1218 tcg_out_ld_ptr(s, TCG_REG_T1, (uintptr_t)(s->tb_next + a0));
1219 tcg_out_arithi(s, TCG_REG_G0, TCG_REG_T1, 0, JMPL);
1222 s->tb_next_offset[a0] = tcg_current_code_size(s);
1225 tcg_out_bpcc(s, COND_A, BPCC_PT, a0);
1229 #define OP_32_64(x) \
1230 glue(glue(case INDEX_op_, x), _i32): \
1231 glue(glue(case INDEX_op_, x), _i64)
1234 tcg_out_ldst(s, a0, a1, a2, LDUB);
1237 tcg_out_ldst(s, a0, a1, a2, LDSB);
1240 tcg_out_ldst(s, a0, a1, a2, LDUH);
1243 tcg_out_ldst(s, a0, a1, a2, LDSH);
1245 case INDEX_op_ld_i32:
1246 case INDEX_op_ld32u_i64:
1247 tcg_out_ldst(s, a0, a1, a2, LDUW);
1250 tcg_out_ldst(s, a0, a1, a2, STB);
1253 tcg_out_ldst(s, a0, a1, a2, STH);
1255 case INDEX_op_st_i32:
1256 case INDEX_op_st32_i64:
1257 tcg_out_ldst(s, a0, a1, a2, STW);
1280 case INDEX_op_shl_i32:
1283 /* Limit immediate shift count lest we create an illegal insn. */
1284 tcg_out_arithc(s, a0, a1, a2 & 31, c2, c);
1286 case INDEX_op_shr_i32:
1289 case INDEX_op_sar_i32:
1292 case INDEX_op_mul_i32:
1303 case INDEX_op_div_i32:
1304 tcg_out_div32(s, a0, a1, a2, c2, 0);
1306 case INDEX_op_divu_i32:
1307 tcg_out_div32(s, a0, a1, a2, c2, 1);
1310 case INDEX_op_brcond_i32:
1311 tcg_out_brcond_i32(s, a2, a0, a1, const_args[1], args[3]);
1313 case INDEX_op_setcond_i32:
1314 tcg_out_setcond_i32(s, args[3], a0, a1, a2, c2);
1316 case INDEX_op_movcond_i32:
1317 tcg_out_movcond_i32(s, args[5], a0, a1, a2, c2, args[3], const_args[3]);
1320 case INDEX_op_add2_i32:
1321 tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3],
1322 args[4], const_args[4], args[5], const_args[5],
1323 ARITH_ADDCC, ARITH_ADDX);
1325 case INDEX_op_sub2_i32:
1326 tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3],
1327 args[4], const_args[4], args[5], const_args[5],
1328 ARITH_SUBCC, ARITH_SUBX);
1330 case INDEX_op_mulu2_i32:
1333 case INDEX_op_muls2_i32:
1336 /* The 32-bit multiply insns produce a full 64-bit result. If the
1337 destination register can hold it, we can avoid the slower RDY. */
1338 tcg_out_arithc(s, a0, a2, args[3], const_args[3], c);
1339 if (SPARC64 || a0 <= TCG_REG_O7) {
1340 tcg_out_arithi(s, a1, a0, 32, SHIFT_SRLX);
1346 case INDEX_op_qemu_ld_i32:
1347 tcg_out_qemu_ld(s, a0, a1, a2, args[3], false);
1349 case INDEX_op_qemu_ld_i64:
1350 tcg_out_qemu_ld(s, a0, a1, a2, args[3], true);
1352 case INDEX_op_qemu_st_i32:
1353 case INDEX_op_qemu_st_i64:
1354 tcg_out_qemu_st(s, a0, a1, a2, args[3]);
1357 case INDEX_op_ld32s_i64:
1358 tcg_out_ldst(s, a0, a1, a2, LDSW);
1360 case INDEX_op_ld_i64:
1361 tcg_out_ldst(s, a0, a1, a2, LDX);
1363 case INDEX_op_st_i64:
1364 tcg_out_ldst(s, a0, a1, a2, STX);
1366 case INDEX_op_shl_i64:
1369 /* Limit immediate shift count lest we create an illegal insn. */
1370 tcg_out_arithc(s, a0, a1, a2 & 63, c2, c);
1372 case INDEX_op_shr_i64:
1375 case INDEX_op_sar_i64:
1378 case INDEX_op_mul_i64:
1381 case INDEX_op_div_i64:
1384 case INDEX_op_divu_i64:
1387 case INDEX_op_ext32s_i64:
1388 tcg_out_arithi(s, a0, a1, 0, SHIFT_SRA);
1390 case INDEX_op_ext32u_i64:
1391 tcg_out_arithi(s, a0, a1, 0, SHIFT_SRL);
1393 case INDEX_op_trunc_shr_i32:
1395 tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
1397 tcg_out_arithi(s, a0, a1, a2, SHIFT_SRLX);
1401 case INDEX_op_brcond_i64:
1402 tcg_out_brcond_i64(s, a2, a0, a1, const_args[1], args[3]);
1404 case INDEX_op_setcond_i64:
1405 tcg_out_setcond_i64(s, args[3], a0, a1, a2, c2);
1407 case INDEX_op_movcond_i64:
1408 tcg_out_movcond_i64(s, args[5], a0, a1, a2, c2, args[3], const_args[3]);
1410 case INDEX_op_add2_i64:
1411 tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4],
1412 const_args[4], args[5], const_args[5], false);
1414 case INDEX_op_sub2_i64:
1415 tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4],
1416 const_args[4], args[5], const_args[5], true);
1420 tcg_out_arithc(s, a0, a1, a2, c2, c);
1424 tcg_out_arithc(s, a0, TCG_REG_G0, a1, const_args[1], c);
1427 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1428 case INDEX_op_mov_i64:
1429 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1430 case INDEX_op_movi_i64:
1431 case INDEX_op_call: /* Always emitted via tcg_out_call. */
1437 static const TCGTargetOpDef sparc_op_defs[] = {
1438 { INDEX_op_exit_tb, { } },
1439 { INDEX_op_goto_tb, { } },
1440 { INDEX_op_br, { } },
1442 { INDEX_op_ld8u_i32, { "r", "r" } },
1443 { INDEX_op_ld8s_i32, { "r", "r" } },
1444 { INDEX_op_ld16u_i32, { "r", "r" } },
1445 { INDEX_op_ld16s_i32, { "r", "r" } },
1446 { INDEX_op_ld_i32, { "r", "r" } },
1447 { INDEX_op_st8_i32, { "rZ", "r" } },
1448 { INDEX_op_st16_i32, { "rZ", "r" } },
1449 { INDEX_op_st_i32, { "rZ", "r" } },
1451 { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
1452 { INDEX_op_mul_i32, { "r", "rZ", "rJ" } },
1453 { INDEX_op_div_i32, { "r", "rZ", "rJ" } },
1454 { INDEX_op_divu_i32, { "r", "rZ", "rJ" } },
1455 { INDEX_op_sub_i32, { "r", "rZ", "rJ" } },
1456 { INDEX_op_and_i32, { "r", "rZ", "rJ" } },
1457 { INDEX_op_andc_i32, { "r", "rZ", "rJ" } },
1458 { INDEX_op_or_i32, { "r", "rZ", "rJ" } },
1459 { INDEX_op_orc_i32, { "r", "rZ", "rJ" } },
1460 { INDEX_op_xor_i32, { "r", "rZ", "rJ" } },
1462 { INDEX_op_shl_i32, { "r", "rZ", "rJ" } },
1463 { INDEX_op_shr_i32, { "r", "rZ", "rJ" } },
1464 { INDEX_op_sar_i32, { "r", "rZ", "rJ" } },
1466 { INDEX_op_neg_i32, { "r", "rJ" } },
1467 { INDEX_op_not_i32, { "r", "rJ" } },
1469 { INDEX_op_brcond_i32, { "rZ", "rJ" } },
1470 { INDEX_op_setcond_i32, { "r", "rZ", "rJ" } },
1471 { INDEX_op_movcond_i32, { "r", "rZ", "rJ", "rI", "0" } },
1473 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1474 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJ", "rJ" } },
1475 { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rJ" } },
1476 { INDEX_op_muls2_i32, { "r", "r", "rZ", "rJ" } },
1478 { INDEX_op_ld8u_i64, { "R", "r" } },
1479 { INDEX_op_ld8s_i64, { "R", "r" } },
1480 { INDEX_op_ld16u_i64, { "R", "r" } },
1481 { INDEX_op_ld16s_i64, { "R", "r" } },
1482 { INDEX_op_ld32u_i64, { "R", "r" } },
1483 { INDEX_op_ld32s_i64, { "R", "r" } },
1484 { INDEX_op_ld_i64, { "R", "r" } },
1485 { INDEX_op_st8_i64, { "RZ", "r" } },
1486 { INDEX_op_st16_i64, { "RZ", "r" } },
1487 { INDEX_op_st32_i64, { "RZ", "r" } },
1488 { INDEX_op_st_i64, { "RZ", "r" } },
1490 { INDEX_op_add_i64, { "R", "RZ", "RJ" } },
1491 { INDEX_op_mul_i64, { "R", "RZ", "RJ" } },
1492 { INDEX_op_div_i64, { "R", "RZ", "RJ" } },
1493 { INDEX_op_divu_i64, { "R", "RZ", "RJ" } },
1494 { INDEX_op_sub_i64, { "R", "RZ", "RJ" } },
1495 { INDEX_op_and_i64, { "R", "RZ", "RJ" } },
1496 { INDEX_op_andc_i64, { "R", "RZ", "RJ" } },
1497 { INDEX_op_or_i64, { "R", "RZ", "RJ" } },
1498 { INDEX_op_orc_i64, { "R", "RZ", "RJ" } },
1499 { INDEX_op_xor_i64, { "R", "RZ", "RJ" } },
1501 { INDEX_op_shl_i64, { "R", "RZ", "RJ" } },
1502 { INDEX_op_shr_i64, { "R", "RZ", "RJ" } },
1503 { INDEX_op_sar_i64, { "R", "RZ", "RJ" } },
1505 { INDEX_op_neg_i64, { "R", "RJ" } },
1506 { INDEX_op_not_i64, { "R", "RJ" } },
1508 { INDEX_op_ext32s_i64, { "R", "r" } },
1509 { INDEX_op_ext32u_i64, { "R", "r" } },
1510 { INDEX_op_trunc_shr_i32, { "r", "R" } },
1512 { INDEX_op_brcond_i64, { "RZ", "RJ" } },
1513 { INDEX_op_setcond_i64, { "R", "RZ", "RJ" } },
1514 { INDEX_op_movcond_i64, { "R", "RZ", "RJ", "RI", "0" } },
1516 { INDEX_op_add2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
1517 { INDEX_op_sub2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
1519 { INDEX_op_qemu_ld_i32, { "r", "A" } },
1520 { INDEX_op_qemu_ld_i64, { "R", "A" } },
1521 { INDEX_op_qemu_st_i32, { "sZ", "A" } },
1522 { INDEX_op_qemu_st_i64, { "SZ", "A" } },
1527 static void tcg_target_init(TCGContext *s)
1529 /* Only probe for the platform and capabilities if we havn't already
1530 determined maximum values at compile time. */
1531 #ifndef use_vis3_instructions
1533 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
1534 use_vis3_instructions = (hwcap & HWCAP_SPARC_VIS3) != 0;
1538 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1539 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, ALL_64);
1541 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1557 tcg_regset_clear(s->reserved_regs);
1558 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */
1559 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */
1560 tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */
1561 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); /* frame pointer */
1562 tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); /* return address */
1563 tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */
1564 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */
1565 tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */
1567 tcg_add_target_add_op_defs(sparc_op_defs);
1571 # define ELF_HOST_MACHINE EM_SPARCV9
1573 # define ELF_HOST_MACHINE EM_SPARC32PLUS
1574 # define ELF_HOST_FLAGS EF_SPARC_32PLUS
1579 uint8_t fde_def_cfa[SPARC64 ? 4 : 2];
1580 uint8_t fde_win_save;
1581 uint8_t fde_ret_save[3];
1584 static const DebugFrame debug_frame = {
1585 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
1588 .h.cie.code_align = 1,
1589 .h.cie.data_align = -sizeof(void *) & 0x7f,
1590 .h.cie.return_column = 15, /* o7 */
1592 /* Total FDE size does not include the "len" member. */
1593 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
1597 12, 30, /* DW_CFA_def_cfa i6, 2047 */
1598 (2047 & 0x7f) | 0x80, (2047 >> 7)
1600 13, 30 /* DW_CFA_def_cfa_register i6 */
1603 .fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */
1604 .fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */
1607 void tcg_register_jit(void *buf, size_t buf_size)
1609 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
1612 void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
1614 uint32_t *ptr = (uint32_t *)jmp_addr;
1615 uintptr_t disp = addr - jmp_addr;
1617 /* We can reach the entire address space for 32-bit. For 64-bit
1618 the code_gen_buffer can't be larger than 2GB. */
1619 assert(disp == (int32_t)disp);
1621 *ptr = CALL | (uint32_t)disp >> 2;
1622 flush_icache_range(jmp_addr, jmp_addr + 4);