16d0b52edSRichard Henderson/* 26d0b52edSRichard Henderson * Tiny Code Generator for QEMU 36d0b52edSRichard Henderson * 46d0b52edSRichard Henderson * Copyright (c) 2008 Fabrice Bellard 56d0b52edSRichard Henderson * 66d0b52edSRichard Henderson * Permission is hereby granted, free of charge, to any person obtaining a copy 76d0b52edSRichard Henderson * of this software and associated documentation files (the "Software"), to deal 86d0b52edSRichard Henderson * in the Software without restriction, including without limitation the rights 96d0b52edSRichard Henderson * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 106d0b52edSRichard Henderson * copies of the Software, and to permit persons to whom the Software is 116d0b52edSRichard Henderson * furnished to do so, subject to the following conditions: 126d0b52edSRichard Henderson * 136d0b52edSRichard Henderson * The above copyright notice and this permission notice shall be included in 146d0b52edSRichard Henderson * all copies or substantial portions of the Software. 156d0b52edSRichard Henderson * 166d0b52edSRichard Henderson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 176d0b52edSRichard Henderson * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 186d0b52edSRichard Henderson * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 196d0b52edSRichard Henderson * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 206d0b52edSRichard Henderson * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 216d0b52edSRichard Henderson * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 226d0b52edSRichard Henderson * THE SOFTWARE. 236d0b52edSRichard Henderson */ 246d0b52edSRichard Henderson 256d0b52edSRichard Henderson/* We only support generating code for 64-bit mode. */ 266d0b52edSRichard Henderson#ifndef __arch64__ 276d0b52edSRichard Henderson#error "unsupported code generation mode" 286d0b52edSRichard Henderson#endif 296d0b52edSRichard Henderson 3029086503SRichard Henderson#include "../tcg-ldst.c.inc" 316d0b52edSRichard Henderson#include "../tcg-pool.c.inc" 326d0b52edSRichard Henderson 336d0b52edSRichard Henderson#ifdef CONFIG_DEBUG_TCG 346d0b52edSRichard Hendersonstatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { 356d0b52edSRichard Henderson "%g0", 366d0b52edSRichard Henderson "%g1", 376d0b52edSRichard Henderson "%g2", 386d0b52edSRichard Henderson "%g3", 396d0b52edSRichard Henderson "%g4", 406d0b52edSRichard Henderson "%g5", 416d0b52edSRichard Henderson "%g6", 426d0b52edSRichard Henderson "%g7", 436d0b52edSRichard Henderson "%o0", 446d0b52edSRichard Henderson "%o1", 456d0b52edSRichard Henderson "%o2", 466d0b52edSRichard Henderson "%o3", 476d0b52edSRichard Henderson "%o4", 486d0b52edSRichard Henderson "%o5", 496d0b52edSRichard Henderson "%o6", 506d0b52edSRichard Henderson "%o7", 516d0b52edSRichard Henderson "%l0", 526d0b52edSRichard Henderson "%l1", 536d0b52edSRichard Henderson "%l2", 546d0b52edSRichard Henderson "%l3", 556d0b52edSRichard Henderson "%l4", 566d0b52edSRichard Henderson "%l5", 576d0b52edSRichard Henderson "%l6", 586d0b52edSRichard Henderson "%l7", 596d0b52edSRichard Henderson "%i0", 606d0b52edSRichard Henderson "%i1", 616d0b52edSRichard Henderson "%i2", 626d0b52edSRichard Henderson "%i3", 636d0b52edSRichard Henderson "%i4", 646d0b52edSRichard Henderson "%i5", 656d0b52edSRichard Henderson "%i6", 666d0b52edSRichard Henderson "%i7", 676d0b52edSRichard Henderson}; 686d0b52edSRichard Henderson#endif 696d0b52edSRichard Henderson 706d0b52edSRichard Henderson#define TCG_CT_CONST_S11 0x100 716d0b52edSRichard Henderson#define TCG_CT_CONST_S13 0x200 726d0b52edSRichard Henderson#define TCG_CT_CONST_ZERO 0x400 736d0b52edSRichard Henderson 746d0b52edSRichard Henderson#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) 756d0b52edSRichard Henderson 7633982b89SRichard Henderson/* Define some temporary registers. T3 is used for constant generation. */ 776d0b52edSRichard Henderson#define TCG_REG_T1 TCG_REG_G1 7833982b89SRichard Henderson#define TCG_REG_T2 TCG_REG_G2 7933982b89SRichard Henderson#define TCG_REG_T3 TCG_REG_O7 806d0b52edSRichard Henderson 816d0b52edSRichard Henderson#ifndef CONFIG_SOFTMMU 826d0b52edSRichard Henderson# define TCG_GUEST_BASE_REG TCG_REG_I5 836d0b52edSRichard Henderson#endif 846d0b52edSRichard Henderson 856d0b52edSRichard Henderson#define TCG_REG_TB TCG_REG_I1 866d0b52edSRichard Henderson 876d0b52edSRichard Hendersonstatic const int tcg_target_reg_alloc_order[] = { 886d0b52edSRichard Henderson TCG_REG_L0, 896d0b52edSRichard Henderson TCG_REG_L1, 906d0b52edSRichard Henderson TCG_REG_L2, 916d0b52edSRichard Henderson TCG_REG_L3, 926d0b52edSRichard Henderson TCG_REG_L4, 936d0b52edSRichard Henderson TCG_REG_L5, 946d0b52edSRichard Henderson TCG_REG_L6, 956d0b52edSRichard Henderson TCG_REG_L7, 966d0b52edSRichard Henderson 976d0b52edSRichard Henderson TCG_REG_I0, 986d0b52edSRichard Henderson TCG_REG_I1, 996d0b52edSRichard Henderson TCG_REG_I2, 1006d0b52edSRichard Henderson TCG_REG_I3, 1016d0b52edSRichard Henderson TCG_REG_I4, 1026d0b52edSRichard Henderson TCG_REG_I5, 1036d0b52edSRichard Henderson 1046d0b52edSRichard Henderson TCG_REG_G3, 1056d0b52edSRichard Henderson TCG_REG_G4, 1066d0b52edSRichard Henderson TCG_REG_G5, 1076d0b52edSRichard Henderson 1086d0b52edSRichard Henderson TCG_REG_O0, 1096d0b52edSRichard Henderson TCG_REG_O1, 1106d0b52edSRichard Henderson TCG_REG_O2, 1116d0b52edSRichard Henderson TCG_REG_O3, 1126d0b52edSRichard Henderson TCG_REG_O4, 1136d0b52edSRichard Henderson TCG_REG_O5, 1146d0b52edSRichard Henderson}; 1156d0b52edSRichard Henderson 1166d0b52edSRichard Hendersonstatic const int tcg_target_call_iarg_regs[6] = { 1176d0b52edSRichard Henderson TCG_REG_O0, 1186d0b52edSRichard Henderson TCG_REG_O1, 1196d0b52edSRichard Henderson TCG_REG_O2, 1206d0b52edSRichard Henderson TCG_REG_O3, 1216d0b52edSRichard Henderson TCG_REG_O4, 1226d0b52edSRichard Henderson TCG_REG_O5, 1236d0b52edSRichard Henderson}; 1246d0b52edSRichard Henderson 1255e3d0c19SRichard Hendersonstatic TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) 1265e3d0c19SRichard Henderson{ 1275e3d0c19SRichard Henderson tcg_debug_assert(kind == TCG_CALL_RET_NORMAL); 1285e3d0c19SRichard Henderson tcg_debug_assert(slot >= 0 && slot <= 3); 1295e3d0c19SRichard Henderson return TCG_REG_O0 + slot; 1305e3d0c19SRichard Henderson} 1316d0b52edSRichard Henderson 1326d0b52edSRichard Henderson#define INSN_OP(x) ((x) << 30) 1336d0b52edSRichard Henderson#define INSN_OP2(x) ((x) << 22) 1346d0b52edSRichard Henderson#define INSN_OP3(x) ((x) << 19) 1356d0b52edSRichard Henderson#define INSN_OPF(x) ((x) << 5) 1366d0b52edSRichard Henderson#define INSN_RD(x) ((x) << 25) 1376d0b52edSRichard Henderson#define INSN_RS1(x) ((x) << 14) 1386d0b52edSRichard Henderson#define INSN_RS2(x) (x) 1396d0b52edSRichard Henderson#define INSN_ASI(x) ((x) << 5) 1406d0b52edSRichard Henderson 1416d0b52edSRichard Henderson#define INSN_IMM10(x) ((1 << 13) | ((x) & 0x3ff)) 1426d0b52edSRichard Henderson#define INSN_IMM11(x) ((1 << 13) | ((x) & 0x7ff)) 1436d0b52edSRichard Henderson#define INSN_IMM13(x) ((1 << 13) | ((x) & 0x1fff)) 1446d0b52edSRichard Henderson#define INSN_OFF16(x) ((((x) >> 2) & 0x3fff) | ((((x) >> 16) & 3) << 20)) 1456d0b52edSRichard Henderson#define INSN_OFF19(x) (((x) >> 2) & 0x07ffff) 1466d0b52edSRichard Henderson#define INSN_COND(x) ((x) << 25) 1476d0b52edSRichard Henderson 1486d0b52edSRichard Henderson#define COND_N 0x0 1496d0b52edSRichard Henderson#define COND_E 0x1 1506d0b52edSRichard Henderson#define COND_LE 0x2 1516d0b52edSRichard Henderson#define COND_L 0x3 1526d0b52edSRichard Henderson#define COND_LEU 0x4 1536d0b52edSRichard Henderson#define COND_CS 0x5 1546d0b52edSRichard Henderson#define COND_NEG 0x6 1556d0b52edSRichard Henderson#define COND_VS 0x7 1566d0b52edSRichard Henderson#define COND_A 0x8 1576d0b52edSRichard Henderson#define COND_NE 0x9 1586d0b52edSRichard Henderson#define COND_G 0xa 1596d0b52edSRichard Henderson#define COND_GE 0xb 1606d0b52edSRichard Henderson#define COND_GU 0xc 1616d0b52edSRichard Henderson#define COND_CC 0xd 1626d0b52edSRichard Henderson#define COND_POS 0xe 1636d0b52edSRichard Henderson#define COND_VC 0xf 1646d0b52edSRichard Henderson#define BA (INSN_OP(0) | INSN_COND(COND_A) | INSN_OP2(0x2)) 1656d0b52edSRichard Henderson 1666d0b52edSRichard Henderson#define RCOND_Z 1 1676d0b52edSRichard Henderson#define RCOND_LEZ 2 1686d0b52edSRichard Henderson#define RCOND_LZ 3 1696d0b52edSRichard Henderson#define RCOND_NZ 5 1706d0b52edSRichard Henderson#define RCOND_GZ 6 1716d0b52edSRichard Henderson#define RCOND_GEZ 7 1726d0b52edSRichard Henderson 1736d0b52edSRichard Henderson#define MOVCC_ICC (1 << 18) 1746d0b52edSRichard Henderson#define MOVCC_XCC (1 << 18 | 1 << 12) 1756d0b52edSRichard Henderson 1766d0b52edSRichard Henderson#define BPCC_ICC 0 1776d0b52edSRichard Henderson#define BPCC_XCC (2 << 20) 1786d0b52edSRichard Henderson#define BPCC_PT (1 << 19) 1796d0b52edSRichard Henderson#define BPCC_PN 0 1806d0b52edSRichard Henderson#define BPCC_A (1 << 29) 1816d0b52edSRichard Henderson 1826d0b52edSRichard Henderson#define BPR_PT BPCC_PT 1836d0b52edSRichard Henderson 1846d0b52edSRichard Henderson#define ARITH_ADD (INSN_OP(2) | INSN_OP3(0x00)) 1856d0b52edSRichard Henderson#define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10)) 1866d0b52edSRichard Henderson#define ARITH_AND (INSN_OP(2) | INSN_OP3(0x01)) 1876d0b52edSRichard Henderson#define ARITH_ANDCC (INSN_OP(2) | INSN_OP3(0x11)) 1886d0b52edSRichard Henderson#define ARITH_ANDN (INSN_OP(2) | INSN_OP3(0x05)) 1896d0b52edSRichard Henderson#define ARITH_OR (INSN_OP(2) | INSN_OP3(0x02)) 1906d0b52edSRichard Henderson#define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12)) 1916d0b52edSRichard Henderson#define ARITH_ORN (INSN_OP(2) | INSN_OP3(0x06)) 1926d0b52edSRichard Henderson#define ARITH_XOR (INSN_OP(2) | INSN_OP3(0x03)) 1936d0b52edSRichard Henderson#define ARITH_SUB (INSN_OP(2) | INSN_OP3(0x04)) 1946d0b52edSRichard Henderson#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14)) 1956d0b52edSRichard Henderson#define ARITH_ADDC (INSN_OP(2) | INSN_OP3(0x08)) 1966d0b52edSRichard Henderson#define ARITH_SUBC (INSN_OP(2) | INSN_OP3(0x0c)) 1976d0b52edSRichard Henderson#define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a)) 1986d0b52edSRichard Henderson#define ARITH_SMUL (INSN_OP(2) | INSN_OP3(0x0b)) 1996d0b52edSRichard Henderson#define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e)) 2006d0b52edSRichard Henderson#define ARITH_SDIV (INSN_OP(2) | INSN_OP3(0x0f)) 2016d0b52edSRichard Henderson#define ARITH_MULX (INSN_OP(2) | INSN_OP3(0x09)) 2026d0b52edSRichard Henderson#define ARITH_UDIVX (INSN_OP(2) | INSN_OP3(0x0d)) 2036d0b52edSRichard Henderson#define ARITH_SDIVX (INSN_OP(2) | INSN_OP3(0x2d)) 2046d0b52edSRichard Henderson#define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c)) 2056d0b52edSRichard Henderson#define ARITH_MOVR (INSN_OP(2) | INSN_OP3(0x2f)) 2066d0b52edSRichard Henderson 2076d0b52edSRichard Henderson#define ARITH_ADDXC (INSN_OP(2) | INSN_OP3(0x36) | INSN_OPF(0x11)) 2086d0b52edSRichard Henderson#define ARITH_UMULXHI (INSN_OP(2) | INSN_OP3(0x36) | INSN_OPF(0x16)) 2096d0b52edSRichard Henderson 2106d0b52edSRichard Henderson#define SHIFT_SLL (INSN_OP(2) | INSN_OP3(0x25)) 2116d0b52edSRichard Henderson#define SHIFT_SRL (INSN_OP(2) | INSN_OP3(0x26)) 2126d0b52edSRichard Henderson#define SHIFT_SRA (INSN_OP(2) | INSN_OP3(0x27)) 2136d0b52edSRichard Henderson 2146d0b52edSRichard Henderson#define SHIFT_SLLX (INSN_OP(2) | INSN_OP3(0x25) | (1 << 12)) 2156d0b52edSRichard Henderson#define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12)) 2166d0b52edSRichard Henderson#define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12)) 2176d0b52edSRichard Henderson 2186d0b52edSRichard Henderson#define RDY (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0)) 2196d0b52edSRichard Henderson#define WRY (INSN_OP(2) | INSN_OP3(0x30) | INSN_RD(0)) 2206d0b52edSRichard Henderson#define JMPL (INSN_OP(2) | INSN_OP3(0x38)) 2216d0b52edSRichard Henderson#define RETURN (INSN_OP(2) | INSN_OP3(0x39)) 2226d0b52edSRichard Henderson#define SAVE (INSN_OP(2) | INSN_OP3(0x3c)) 2236d0b52edSRichard Henderson#define RESTORE (INSN_OP(2) | INSN_OP3(0x3d)) 2246d0b52edSRichard Henderson#define SETHI (INSN_OP(0) | INSN_OP2(0x4)) 2256d0b52edSRichard Henderson#define CALL INSN_OP(1) 2266d0b52edSRichard Henderson#define LDUB (INSN_OP(3) | INSN_OP3(0x01)) 2276d0b52edSRichard Henderson#define LDSB (INSN_OP(3) | INSN_OP3(0x09)) 2286d0b52edSRichard Henderson#define LDUH (INSN_OP(3) | INSN_OP3(0x02)) 2296d0b52edSRichard Henderson#define LDSH (INSN_OP(3) | INSN_OP3(0x0a)) 2306d0b52edSRichard Henderson#define LDUW (INSN_OP(3) | INSN_OP3(0x00)) 2316d0b52edSRichard Henderson#define LDSW (INSN_OP(3) | INSN_OP3(0x08)) 2326d0b52edSRichard Henderson#define LDX (INSN_OP(3) | INSN_OP3(0x0b)) 2336d0b52edSRichard Henderson#define STB (INSN_OP(3) | INSN_OP3(0x05)) 2346d0b52edSRichard Henderson#define STH (INSN_OP(3) | INSN_OP3(0x06)) 2356d0b52edSRichard Henderson#define STW (INSN_OP(3) | INSN_OP3(0x04)) 2366d0b52edSRichard Henderson#define STX (INSN_OP(3) | INSN_OP3(0x0e)) 2376d0b52edSRichard Henderson#define LDUBA (INSN_OP(3) | INSN_OP3(0x11)) 2386d0b52edSRichard Henderson#define LDSBA (INSN_OP(3) | INSN_OP3(0x19)) 2396d0b52edSRichard Henderson#define LDUHA (INSN_OP(3) | INSN_OP3(0x12)) 2406d0b52edSRichard Henderson#define LDSHA (INSN_OP(3) | INSN_OP3(0x1a)) 2416d0b52edSRichard Henderson#define LDUWA (INSN_OP(3) | INSN_OP3(0x10)) 2426d0b52edSRichard Henderson#define LDSWA (INSN_OP(3) | INSN_OP3(0x18)) 2436d0b52edSRichard Henderson#define LDXA (INSN_OP(3) | INSN_OP3(0x1b)) 2446d0b52edSRichard Henderson#define STBA (INSN_OP(3) | INSN_OP3(0x15)) 2456d0b52edSRichard Henderson#define STHA (INSN_OP(3) | INSN_OP3(0x16)) 2466d0b52edSRichard Henderson#define STWA (INSN_OP(3) | INSN_OP3(0x14)) 2476d0b52edSRichard Henderson#define STXA (INSN_OP(3) | INSN_OP3(0x1e)) 2486d0b52edSRichard Henderson 2496d0b52edSRichard Henderson#define MEMBAR (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(15) | (1 << 13)) 2506d0b52edSRichard Henderson 2516d0b52edSRichard Henderson#define NOP (SETHI | INSN_RD(TCG_REG_G0) | 0) 2526d0b52edSRichard Henderson 2536d0b52edSRichard Henderson#ifndef ASI_PRIMARY_LITTLE 2546d0b52edSRichard Henderson#define ASI_PRIMARY_LITTLE 0x88 2556d0b52edSRichard Henderson#endif 2566d0b52edSRichard Henderson 2576d0b52edSRichard Henderson#define LDUH_LE (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2586d0b52edSRichard Henderson#define LDSH_LE (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2596d0b52edSRichard Henderson#define LDUW_LE (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2606d0b52edSRichard Henderson#define LDSW_LE (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2616d0b52edSRichard Henderson#define LDX_LE (LDXA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2626d0b52edSRichard Henderson 2636d0b52edSRichard Henderson#define STH_LE (STHA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2646d0b52edSRichard Henderson#define STW_LE (STWA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2656d0b52edSRichard Henderson#define STX_LE (STXA | INSN_ASI(ASI_PRIMARY_LITTLE)) 2666d0b52edSRichard Henderson 2676d0b52edSRichard Henderson#ifndef use_vis3_instructions 2686d0b52edSRichard Hendersonbool use_vis3_instructions; 2696d0b52edSRichard Henderson#endif 2706d0b52edSRichard Henderson 2716d0b52edSRichard Hendersonstatic bool check_fit_i64(int64_t val, unsigned int bits) 2726d0b52edSRichard Henderson{ 2736d0b52edSRichard Henderson return val == sextract64(val, 0, bits); 2746d0b52edSRichard Henderson} 2756d0b52edSRichard Henderson 2766d0b52edSRichard Hendersonstatic bool check_fit_i32(int32_t val, unsigned int bits) 2776d0b52edSRichard Henderson{ 2786d0b52edSRichard Henderson return val == sextract32(val, 0, bits); 2796d0b52edSRichard Henderson} 2806d0b52edSRichard Henderson 2816d0b52edSRichard Henderson#define check_fit_tl check_fit_i64 2826d0b52edSRichard Henderson#define check_fit_ptr check_fit_i64 2836d0b52edSRichard Henderson 2846d0b52edSRichard Hendersonstatic bool patch_reloc(tcg_insn_unit *src_rw, int type, 2856d0b52edSRichard Henderson intptr_t value, intptr_t addend) 2866d0b52edSRichard Henderson{ 2876d0b52edSRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 2886d0b52edSRichard Henderson uint32_t insn = *src_rw; 2896d0b52edSRichard Henderson intptr_t pcrel; 2906d0b52edSRichard Henderson 2916d0b52edSRichard Henderson value += addend; 2926d0b52edSRichard Henderson pcrel = tcg_ptr_byte_diff((tcg_insn_unit *)value, src_rx); 2936d0b52edSRichard Henderson 2946d0b52edSRichard Henderson switch (type) { 2956d0b52edSRichard Henderson case R_SPARC_WDISP16: 2966d0b52edSRichard Henderson if (!check_fit_ptr(pcrel >> 2, 16)) { 2976d0b52edSRichard Henderson return false; 2986d0b52edSRichard Henderson } 2996d0b52edSRichard Henderson insn &= ~INSN_OFF16(-1); 3006d0b52edSRichard Henderson insn |= INSN_OFF16(pcrel); 3016d0b52edSRichard Henderson break; 3026d0b52edSRichard Henderson case R_SPARC_WDISP19: 3036d0b52edSRichard Henderson if (!check_fit_ptr(pcrel >> 2, 19)) { 3046d0b52edSRichard Henderson return false; 3056d0b52edSRichard Henderson } 3066d0b52edSRichard Henderson insn &= ~INSN_OFF19(-1); 3076d0b52edSRichard Henderson insn |= INSN_OFF19(pcrel); 3086d0b52edSRichard Henderson break; 3096d0b52edSRichard Henderson case R_SPARC_13: 3106d0b52edSRichard Henderson if (!check_fit_ptr(value, 13)) { 3116d0b52edSRichard Henderson return false; 3126d0b52edSRichard Henderson } 3136d0b52edSRichard Henderson insn &= ~INSN_IMM13(-1); 3146d0b52edSRichard Henderson insn |= INSN_IMM13(value); 3156d0b52edSRichard Henderson break; 3166d0b52edSRichard Henderson default: 3176d0b52edSRichard Henderson g_assert_not_reached(); 3186d0b52edSRichard Henderson } 3196d0b52edSRichard Henderson 3206d0b52edSRichard Henderson *src_rw = insn; 3216d0b52edSRichard Henderson return true; 3226d0b52edSRichard Henderson} 3236d0b52edSRichard Henderson 3246d0b52edSRichard Henderson/* test if a constant matches the constraint */ 32521e9a8aeSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct, 32621e9a8aeSRichard Henderson TCGType type, TCGCond cond, int vece) 3276d0b52edSRichard Henderson{ 3286d0b52edSRichard Henderson if (ct & TCG_CT_CONST) { 3296d0b52edSRichard Henderson return 1; 3306d0b52edSRichard Henderson } 3316d0b52edSRichard Henderson 3326d0b52edSRichard Henderson if (type == TCG_TYPE_I32) { 3336d0b52edSRichard Henderson val = (int32_t)val; 3346d0b52edSRichard Henderson } 3356d0b52edSRichard Henderson 3366d0b52edSRichard Henderson if ((ct & TCG_CT_CONST_ZERO) && val == 0) { 3376d0b52edSRichard Henderson return 1; 3386d0b52edSRichard Henderson } else if ((ct & TCG_CT_CONST_S11) && check_fit_tl(val, 11)) { 3396d0b52edSRichard Henderson return 1; 3406d0b52edSRichard Henderson } else if ((ct & TCG_CT_CONST_S13) && check_fit_tl(val, 13)) { 3416d0b52edSRichard Henderson return 1; 3426d0b52edSRichard Henderson } else { 3436d0b52edSRichard Henderson return 0; 3446d0b52edSRichard Henderson } 3456d0b52edSRichard Henderson} 3466d0b52edSRichard Henderson 3476d0b52edSRichard Hendersonstatic void tcg_out_nop(TCGContext *s) 3486d0b52edSRichard Henderson{ 3496d0b52edSRichard Henderson tcg_out32(s, NOP); 3506d0b52edSRichard Henderson} 3516d0b52edSRichard Henderson 3526d0b52edSRichard Hendersonstatic void tcg_out_arith(TCGContext *s, TCGReg rd, TCGReg rs1, 3536d0b52edSRichard Henderson TCGReg rs2, int op) 3546d0b52edSRichard Henderson{ 3556d0b52edSRichard Henderson tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) | INSN_RS2(rs2)); 3566d0b52edSRichard Henderson} 3576d0b52edSRichard Henderson 3586d0b52edSRichard Hendersonstatic void tcg_out_arithi(TCGContext *s, TCGReg rd, TCGReg rs1, 3596d0b52edSRichard Henderson int32_t offset, int op) 3606d0b52edSRichard Henderson{ 3616d0b52edSRichard Henderson tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) | INSN_IMM13(offset)); 3626d0b52edSRichard Henderson} 3636d0b52edSRichard Henderson 3646d0b52edSRichard Hendersonstatic void tcg_out_arithc(TCGContext *s, TCGReg rd, TCGReg rs1, 3656d0b52edSRichard Henderson int32_t val2, int val2const, int op) 3666d0b52edSRichard Henderson{ 3676d0b52edSRichard Henderson tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1) 3686d0b52edSRichard Henderson | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2))); 3696d0b52edSRichard Henderson} 3706d0b52edSRichard Henderson 3716d0b52edSRichard Hendersonstatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 3726d0b52edSRichard Henderson{ 3736d0b52edSRichard Henderson if (ret != arg) { 3746d0b52edSRichard Henderson tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR); 3756d0b52edSRichard Henderson } 3766d0b52edSRichard Henderson return true; 3776d0b52edSRichard Henderson} 3786d0b52edSRichard Henderson 3796d0b52edSRichard Hendersonstatic void tcg_out_mov_delay(TCGContext *s, TCGReg ret, TCGReg arg) 3806d0b52edSRichard Henderson{ 3816d0b52edSRichard Henderson if (ret != arg) { 3826d0b52edSRichard Henderson tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR); 3836d0b52edSRichard Henderson } else { 3846d0b52edSRichard Henderson tcg_out_nop(s); 3856d0b52edSRichard Henderson } 3866d0b52edSRichard Henderson} 3876d0b52edSRichard Henderson 3886d0b52edSRichard Hendersonstatic void tcg_out_sethi(TCGContext *s, TCGReg ret, uint32_t arg) 3896d0b52edSRichard Henderson{ 3906d0b52edSRichard Henderson tcg_out32(s, SETHI | INSN_RD(ret) | ((arg & 0xfffffc00) >> 10)); 3916d0b52edSRichard Henderson} 3926d0b52edSRichard Henderson 3938b14f862SRichard Henderson/* A 13-bit constant sign-extended to 64 bits. */ 3948b14f862SRichard Hendersonstatic void tcg_out_movi_s13(TCGContext *s, TCGReg ret, int32_t arg) 3956d0b52edSRichard Henderson{ 3966d0b52edSRichard Henderson tcg_out_arithi(s, ret, TCG_REG_G0, arg, ARITH_OR); 3976d0b52edSRichard Henderson} 3986d0b52edSRichard Henderson 3991a42d9d4SRichard Henderson/* A 32-bit constant sign-extended to 64 bits. */ 4001a42d9d4SRichard Hendersonstatic void tcg_out_movi_s32(TCGContext *s, TCGReg ret, int32_t arg) 4011a42d9d4SRichard Henderson{ 4021a42d9d4SRichard Henderson tcg_out_sethi(s, ret, ~arg); 4031a42d9d4SRichard Henderson tcg_out_arithi(s, ret, ret, (arg & 0x3ff) | -0x400, ARITH_XOR); 4041a42d9d4SRichard Henderson} 4051a42d9d4SRichard Henderson 4066d0b52edSRichard Henderson/* A 32-bit constant zero-extended to 64 bits. */ 4072cb3f794SRichard Hendersonstatic void tcg_out_movi_u32(TCGContext *s, TCGReg ret, uint32_t arg) 4082cb3f794SRichard Henderson{ 4096d0b52edSRichard Henderson tcg_out_sethi(s, ret, arg); 4106d0b52edSRichard Henderson if (arg & 0x3ff) { 4116d0b52edSRichard Henderson tcg_out_arithi(s, ret, ret, arg & 0x3ff, ARITH_OR); 4126d0b52edSRichard Henderson } 4136d0b52edSRichard Henderson} 4146d0b52edSRichard Henderson 4156d0b52edSRichard Hendersonstatic void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, 4166d0b52edSRichard Henderson tcg_target_long arg, bool in_prologue, 4176d0b52edSRichard Henderson TCGReg scratch) 4186d0b52edSRichard Henderson{ 4196d0b52edSRichard Henderson tcg_target_long hi, lo = (int32_t)arg; 4206d0b52edSRichard Henderson tcg_target_long test, lsb; 4216d0b52edSRichard Henderson 4226d0b52edSRichard Henderson /* A 13-bit constant sign-extended to 64-bits. */ 4236d0b52edSRichard Henderson if (check_fit_tl(arg, 13)) { 4248b14f862SRichard Henderson tcg_out_movi_s13(s, ret, arg); 4256d0b52edSRichard Henderson return; 4266d0b52edSRichard Henderson } 4276d0b52edSRichard Henderson 428ca0681c9SRichard Henderson /* A 32-bit constant, or 32-bit zero-extended to 64-bits. */ 429ca0681c9SRichard Henderson if (type == TCG_TYPE_I32 || arg == (uint32_t)arg) { 4302cb3f794SRichard Henderson tcg_out_movi_u32(s, ret, arg); 431ca0681c9SRichard Henderson return; 432ca0681c9SRichard Henderson } 433ca0681c9SRichard Henderson 4346d0b52edSRichard Henderson /* A 13-bit constant relative to the TB. */ 4351e42b4f8SRichard Henderson if (!in_prologue) { 4366d0b52edSRichard Henderson test = tcg_tbrel_diff(s, (void *)arg); 4376d0b52edSRichard Henderson if (check_fit_ptr(test, 13)) { 4386d0b52edSRichard Henderson tcg_out_arithi(s, ret, TCG_REG_TB, test, ARITH_ADD); 4396d0b52edSRichard Henderson return; 4406d0b52edSRichard Henderson } 4416d0b52edSRichard Henderson } 4426d0b52edSRichard Henderson 4436d0b52edSRichard Henderson /* A 32-bit constant sign-extended to 64-bits. */ 4446d0b52edSRichard Henderson if (arg == lo) { 4451a42d9d4SRichard Henderson tcg_out_movi_s32(s, ret, arg); 4466d0b52edSRichard Henderson return; 4476d0b52edSRichard Henderson } 4486d0b52edSRichard Henderson 4496d0b52edSRichard Henderson /* A 32-bit constant, shifted. */ 4506d0b52edSRichard Henderson lsb = ctz64(arg); 4516d0b52edSRichard Henderson test = (tcg_target_long)arg >> lsb; 4526d0b52edSRichard Henderson if (lsb > 10 && test == extract64(test, 0, 21)) { 4536d0b52edSRichard Henderson tcg_out_sethi(s, ret, test << 10); 4546d0b52edSRichard Henderson tcg_out_arithi(s, ret, ret, lsb - 10, SHIFT_SLLX); 4556d0b52edSRichard Henderson return; 4566d0b52edSRichard Henderson } else if (test == (uint32_t)test || test == (int32_t)test) { 4576d0b52edSRichard Henderson tcg_out_movi_int(s, TCG_TYPE_I64, ret, test, in_prologue, scratch); 4586d0b52edSRichard Henderson tcg_out_arithi(s, ret, ret, lsb, SHIFT_SLLX); 4596d0b52edSRichard Henderson return; 4606d0b52edSRichard Henderson } 4616d0b52edSRichard Henderson 4626d0b52edSRichard Henderson /* Use the constant pool, if possible. */ 4631e42b4f8SRichard Henderson if (!in_prologue) { 4646d0b52edSRichard Henderson new_pool_label(s, arg, R_SPARC_13, s->code_ptr, 4656d0b52edSRichard Henderson tcg_tbrel_diff(s, NULL)); 4666d0b52edSRichard Henderson tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(TCG_REG_TB)); 4676d0b52edSRichard Henderson return; 4686d0b52edSRichard Henderson } 4696d0b52edSRichard Henderson 4706d0b52edSRichard Henderson /* A 64-bit constant decomposed into 2 32-bit pieces. */ 4716d0b52edSRichard Henderson if (check_fit_i32(lo, 13)) { 4726d0b52edSRichard Henderson hi = (arg - lo) >> 32; 4732cb3f794SRichard Henderson tcg_out_movi_u32(s, ret, hi); 4746d0b52edSRichard Henderson tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX); 4756d0b52edSRichard Henderson tcg_out_arithi(s, ret, ret, lo, ARITH_ADD); 4766d0b52edSRichard Henderson } else { 4776d0b52edSRichard Henderson hi = arg >> 32; 4782cb3f794SRichard Henderson tcg_out_movi_u32(s, ret, hi); 4792cb3f794SRichard Henderson tcg_out_movi_u32(s, scratch, lo); 4806d0b52edSRichard Henderson tcg_out_arithi(s, ret, ret, 32, SHIFT_SLLX); 4816d0b52edSRichard Henderson tcg_out_arith(s, ret, ret, scratch, ARITH_OR); 4826d0b52edSRichard Henderson } 4836d0b52edSRichard Henderson} 4846d0b52edSRichard Henderson 4856d0b52edSRichard Hendersonstatic void tcg_out_movi(TCGContext *s, TCGType type, 4866d0b52edSRichard Henderson TCGReg ret, tcg_target_long arg) 4876d0b52edSRichard Henderson{ 48833982b89SRichard Henderson tcg_debug_assert(ret != TCG_REG_T3); 48933982b89SRichard Henderson tcg_out_movi_int(s, type, ret, arg, false, TCG_REG_T3); 4906d0b52edSRichard Henderson} 4916d0b52edSRichard Henderson 492678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) 493678155b2SRichard Henderson{ 494678155b2SRichard Henderson g_assert_not_reached(); 495678155b2SRichard Henderson} 496678155b2SRichard Henderson 497753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) 498753e42eaSRichard Henderson{ 499753e42eaSRichard Henderson g_assert_not_reached(); 500753e42eaSRichard Henderson} 501753e42eaSRichard Henderson 502d0e66c89SRichard Hendersonstatic void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs) 503d0e66c89SRichard Henderson{ 504d0e66c89SRichard Henderson tcg_out_arithi(s, rd, rs, 0xff, ARITH_AND); 505d0e66c89SRichard Henderson} 506d0e66c89SRichard Henderson 507379afdffSRichard Hendersonstatic void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs) 508379afdffSRichard Henderson{ 509379afdffSRichard Henderson tcg_out_arithi(s, rd, rs, 16, SHIFT_SLL); 510379afdffSRichard Henderson tcg_out_arithi(s, rd, rd, 16, SHIFT_SRL); 511379afdffSRichard Henderson} 512379afdffSRichard Henderson 51352bf3398SRichard Hendersonstatic void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs) 51452bf3398SRichard Henderson{ 51552bf3398SRichard Henderson tcg_out_arithi(s, rd, rs, 0, SHIFT_SRA); 51652bf3398SRichard Henderson} 51752bf3398SRichard Henderson 5189ecf5f61SRichard Hendersonstatic void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rs) 5199ecf5f61SRichard Henderson{ 5209ecf5f61SRichard Henderson tcg_out_arithi(s, rd, rs, 0, SHIFT_SRL); 5219ecf5f61SRichard Henderson} 5229ecf5f61SRichard Henderson 5239c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs) 5249c6aa274SRichard Henderson{ 5259c6aa274SRichard Henderson tcg_out_ext32s(s, rd, rs); 5269c6aa274SRichard Henderson} 5279c6aa274SRichard Henderson 528b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs) 529b9bfe000SRichard Henderson{ 530b9bfe000SRichard Henderson tcg_out_ext32u(s, rd, rs); 531b9bfe000SRichard Henderson} 532b9bfe000SRichard Henderson 533d36ce28bSRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs) 534d36ce28bSRichard Henderson{ 535d36ce28bSRichard Henderson tcg_out_ext32u(s, rd, rs); 536d36ce28bSRichard Henderson} 537d36ce28bSRichard Henderson 538767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2) 539767c2503SRichard Henderson{ 540767c2503SRichard Henderson return false; 541767c2503SRichard Henderson} 542767c2503SRichard Henderson 5436a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs, 5446a6d772eSRichard Henderson tcg_target_long imm) 5456a6d772eSRichard Henderson{ 5466a6d772eSRichard Henderson /* This function is only used for passing structs by reference. */ 5476a6d772eSRichard Henderson g_assert_not_reached(); 5486a6d772eSRichard Henderson} 5496a6d772eSRichard Henderson 5506d0b52edSRichard Hendersonstatic void tcg_out_ldst_rr(TCGContext *s, TCGReg data, TCGReg a1, 5516d0b52edSRichard Henderson TCGReg a2, int op) 5526d0b52edSRichard Henderson{ 5536d0b52edSRichard Henderson tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2)); 5546d0b52edSRichard Henderson} 5556d0b52edSRichard Henderson 5566d0b52edSRichard Hendersonstatic void tcg_out_ldst(TCGContext *s, TCGReg ret, TCGReg addr, 5576d0b52edSRichard Henderson intptr_t offset, int op) 5586d0b52edSRichard Henderson{ 5596d0b52edSRichard Henderson if (check_fit_ptr(offset, 13)) { 5606d0b52edSRichard Henderson tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) | 5616d0b52edSRichard Henderson INSN_IMM13(offset)); 5626d0b52edSRichard Henderson } else { 5636d0b52edSRichard Henderson tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, offset); 5646d0b52edSRichard Henderson tcg_out_ldst_rr(s, ret, addr, TCG_REG_T1, op); 5656d0b52edSRichard Henderson } 5666d0b52edSRichard Henderson} 5676d0b52edSRichard Henderson 5686d0b52edSRichard Hendersonstatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, 5696d0b52edSRichard Henderson TCGReg arg1, intptr_t arg2) 5706d0b52edSRichard Henderson{ 5716d0b52edSRichard Henderson tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX)); 5726d0b52edSRichard Henderson} 5736d0b52edSRichard Henderson 5746d0b52edSRichard Hendersonstatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, 5756d0b52edSRichard Henderson TCGReg arg1, intptr_t arg2) 5766d0b52edSRichard Henderson{ 5776d0b52edSRichard Henderson tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX)); 5786d0b52edSRichard Henderson} 5796d0b52edSRichard Henderson 5806d0b52edSRichard Hendersonstatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, 5816d0b52edSRichard Henderson TCGReg base, intptr_t ofs) 5826d0b52edSRichard Henderson{ 5836d0b52edSRichard Henderson if (val == 0) { 5846d0b52edSRichard Henderson tcg_out_st(s, type, TCG_REG_G0, base, ofs); 5856d0b52edSRichard Henderson return true; 5866d0b52edSRichard Henderson } 5876d0b52edSRichard Henderson return false; 5886d0b52edSRichard Henderson} 5896d0b52edSRichard Henderson 5906d0b52edSRichard Hendersonstatic void tcg_out_sety(TCGContext *s, TCGReg rs) 5916d0b52edSRichard Henderson{ 5926d0b52edSRichard Henderson tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs)); 5936d0b52edSRichard Henderson} 5946d0b52edSRichard Henderson 5956d0b52edSRichard Hendersonstatic void tcg_out_div32(TCGContext *s, TCGReg rd, TCGReg rs1, 5966d0b52edSRichard Henderson int32_t val2, int val2const, int uns) 5976d0b52edSRichard Henderson{ 5986d0b52edSRichard Henderson /* Load Y with the sign/zero extension of RS1 to 64-bits. */ 5996d0b52edSRichard Henderson if (uns) { 6006d0b52edSRichard Henderson tcg_out_sety(s, TCG_REG_G0); 6016d0b52edSRichard Henderson } else { 6026d0b52edSRichard Henderson tcg_out_arithi(s, TCG_REG_T1, rs1, 31, SHIFT_SRA); 6036d0b52edSRichard Henderson tcg_out_sety(s, TCG_REG_T1); 6046d0b52edSRichard Henderson } 6056d0b52edSRichard Henderson 6066d0b52edSRichard Henderson tcg_out_arithc(s, rd, rs1, val2, val2const, 6076d0b52edSRichard Henderson uns ? ARITH_UDIV : ARITH_SDIV); 6086d0b52edSRichard Henderson} 6096d0b52edSRichard Henderson 610b9ddaf56SRichard Hendersonstatic const uint8_t tcg_cond_to_bcond[16] = { 6116d0b52edSRichard Henderson [TCG_COND_EQ] = COND_E, 6126d0b52edSRichard Henderson [TCG_COND_NE] = COND_NE, 613b9ddaf56SRichard Henderson [TCG_COND_TSTEQ] = COND_E, 614b9ddaf56SRichard Henderson [TCG_COND_TSTNE] = COND_NE, 6156d0b52edSRichard Henderson [TCG_COND_LT] = COND_L, 6166d0b52edSRichard Henderson [TCG_COND_GE] = COND_GE, 6176d0b52edSRichard Henderson [TCG_COND_LE] = COND_LE, 6186d0b52edSRichard Henderson [TCG_COND_GT] = COND_G, 6196d0b52edSRichard Henderson [TCG_COND_LTU] = COND_CS, 6206d0b52edSRichard Henderson [TCG_COND_GEU] = COND_CC, 6216d0b52edSRichard Henderson [TCG_COND_LEU] = COND_LEU, 6226d0b52edSRichard Henderson [TCG_COND_GTU] = COND_GU, 6236d0b52edSRichard Henderson}; 6246d0b52edSRichard Henderson 6256bc74a53SRichard Hendersonstatic const uint8_t tcg_cond_to_rcond[16] = { 6266d0b52edSRichard Henderson [TCG_COND_EQ] = RCOND_Z, 6276d0b52edSRichard Henderson [TCG_COND_NE] = RCOND_NZ, 6286d0b52edSRichard Henderson [TCG_COND_LT] = RCOND_LZ, 6296d0b52edSRichard Henderson [TCG_COND_GT] = RCOND_GZ, 6306d0b52edSRichard Henderson [TCG_COND_LE] = RCOND_LEZ, 6316d0b52edSRichard Henderson [TCG_COND_GE] = RCOND_GEZ 6326d0b52edSRichard Henderson}; 6336d0b52edSRichard Henderson 6346d0b52edSRichard Hendersonstatic void tcg_out_bpcc0(TCGContext *s, int scond, int flags, int off19) 6356d0b52edSRichard Henderson{ 6366d0b52edSRichard Henderson tcg_out32(s, INSN_OP(0) | INSN_OP2(1) | INSN_COND(scond) | flags | off19); 6376d0b52edSRichard Henderson} 6386d0b52edSRichard Henderson 6396d0b52edSRichard Hendersonstatic void tcg_out_bpcc(TCGContext *s, int scond, int flags, TCGLabel *l) 6406d0b52edSRichard Henderson{ 6416d0b52edSRichard Henderson int off19 = 0; 6426d0b52edSRichard Henderson 6436d0b52edSRichard Henderson if (l->has_value) { 6446d0b52edSRichard Henderson off19 = INSN_OFF19(tcg_pcrel_diff(s, l->u.value_ptr)); 6456d0b52edSRichard Henderson } else { 6466d0b52edSRichard Henderson tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP19, l, 0); 6476d0b52edSRichard Henderson } 6486d0b52edSRichard Henderson tcg_out_bpcc0(s, scond, flags, off19); 6496d0b52edSRichard Henderson} 6506d0b52edSRichard Henderson 651905afe37SRichard Hendersonstatic void tcg_out_cmp(TCGContext *s, TCGCond cond, 652905afe37SRichard Henderson TCGReg c1, int32_t c2, int c2const) 6536d0b52edSRichard Henderson{ 654b9ddaf56SRichard Henderson tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, 655b9ddaf56SRichard Henderson is_tst_cond(cond) ? ARITH_ANDCC : ARITH_SUBCC); 6566d0b52edSRichard Henderson} 6576d0b52edSRichard Henderson 6586d0b52edSRichard Hendersonstatic void tcg_out_brcond_i32(TCGContext *s, TCGCond cond, TCGReg arg1, 6596d0b52edSRichard Henderson int32_t arg2, int const_arg2, TCGLabel *l) 6606d0b52edSRichard Henderson{ 661905afe37SRichard Henderson tcg_out_cmp(s, cond, arg1, arg2, const_arg2); 6626d0b52edSRichard Henderson tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_ICC | BPCC_PT, l); 6636d0b52edSRichard Henderson tcg_out_nop(s); 6646d0b52edSRichard Henderson} 6656d0b52edSRichard Henderson 6666d0b52edSRichard Hendersonstatic void tcg_out_movcc(TCGContext *s, TCGCond cond, int cc, TCGReg ret, 6676d0b52edSRichard Henderson int32_t v1, int v1const) 6686d0b52edSRichard Henderson{ 6696d0b52edSRichard Henderson tcg_out32(s, ARITH_MOVCC | cc | INSN_RD(ret) 6706d0b52edSRichard Henderson | INSN_RS1(tcg_cond_to_bcond[cond]) 6716d0b52edSRichard Henderson | (v1const ? INSN_IMM11(v1) : INSN_RS2(v1))); 6726d0b52edSRichard Henderson} 6736d0b52edSRichard Henderson 6746d0b52edSRichard Hendersonstatic void tcg_out_movcond_i32(TCGContext *s, TCGCond cond, TCGReg ret, 6756d0b52edSRichard Henderson TCGReg c1, int32_t c2, int c2const, 6766d0b52edSRichard Henderson int32_t v1, int v1const) 6776d0b52edSRichard Henderson{ 678905afe37SRichard Henderson tcg_out_cmp(s, cond, c1, c2, c2const); 6796d0b52edSRichard Henderson tcg_out_movcc(s, cond, MOVCC_ICC, ret, v1, v1const); 6806d0b52edSRichard Henderson} 6816d0b52edSRichard Henderson 6826d0b52edSRichard Hendersonstatic void tcg_out_brcond_i64(TCGContext *s, TCGCond cond, TCGReg arg1, 6836d0b52edSRichard Henderson int32_t arg2, int const_arg2, TCGLabel *l) 6846d0b52edSRichard Henderson{ 6856d0b52edSRichard Henderson /* For 64-bit signed comparisons vs zero, we can avoid the compare. */ 6866bc74a53SRichard Henderson int rcond = tcg_cond_to_rcond[cond]; 6876bc74a53SRichard Henderson if (arg2 == 0 && rcond) { 6886d0b52edSRichard Henderson int off16 = 0; 6896d0b52edSRichard Henderson 6906d0b52edSRichard Henderson if (l->has_value) { 6916d0b52edSRichard Henderson off16 = INSN_OFF16(tcg_pcrel_diff(s, l->u.value_ptr)); 6926d0b52edSRichard Henderson } else { 6936d0b52edSRichard Henderson tcg_out_reloc(s, s->code_ptr, R_SPARC_WDISP16, l, 0); 6946d0b52edSRichard Henderson } 6956d0b52edSRichard Henderson tcg_out32(s, INSN_OP(0) | INSN_OP2(3) | BPR_PT | INSN_RS1(arg1) 6966bc74a53SRichard Henderson | INSN_COND(rcond) | off16); 6976d0b52edSRichard Henderson } else { 698905afe37SRichard Henderson tcg_out_cmp(s, cond, arg1, arg2, const_arg2); 6996d0b52edSRichard Henderson tcg_out_bpcc(s, tcg_cond_to_bcond[cond], BPCC_XCC | BPCC_PT, l); 7006d0b52edSRichard Henderson } 7016d0b52edSRichard Henderson tcg_out_nop(s); 7026d0b52edSRichard Henderson} 7036d0b52edSRichard Henderson 7046bc74a53SRichard Hendersonstatic void tcg_out_movr(TCGContext *s, int rcond, TCGReg ret, TCGReg c1, 7056d0b52edSRichard Henderson int32_t v1, int v1const) 7066d0b52edSRichard Henderson{ 7076bc74a53SRichard Henderson tcg_out32(s, ARITH_MOVR | INSN_RD(ret) | INSN_RS1(c1) | (rcond << 10) 7086d0b52edSRichard Henderson | (v1const ? INSN_IMM10(v1) : INSN_RS2(v1))); 7096d0b52edSRichard Henderson} 7106d0b52edSRichard Henderson 7116d0b52edSRichard Hendersonstatic void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGReg ret, 7126d0b52edSRichard Henderson TCGReg c1, int32_t c2, int c2const, 7136d0b52edSRichard Henderson int32_t v1, int v1const) 7146d0b52edSRichard Henderson{ 7156d0b52edSRichard Henderson /* For 64-bit signed comparisons vs zero, we can avoid the compare. 7166d0b52edSRichard Henderson Note that the immediate range is one bit smaller, so we must check 7176d0b52edSRichard Henderson for that as well. */ 7186bc74a53SRichard Henderson int rcond = tcg_cond_to_rcond[cond]; 7196bc74a53SRichard Henderson if (c2 == 0 && rcond && (!v1const || check_fit_i32(v1, 10))) { 7206bc74a53SRichard Henderson tcg_out_movr(s, rcond, ret, c1, v1, v1const); 7216d0b52edSRichard Henderson } else { 722905afe37SRichard Henderson tcg_out_cmp(s, cond, c1, c2, c2const); 7236d0b52edSRichard Henderson tcg_out_movcc(s, cond, MOVCC_XCC, ret, v1, v1const); 7246d0b52edSRichard Henderson } 7256d0b52edSRichard Henderson} 7266d0b52edSRichard Henderson 7276d0b52edSRichard Hendersonstatic void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret, 728a0fdd7c9SRichard Henderson TCGReg c1, int32_t c2, int c2const, bool neg) 7296d0b52edSRichard Henderson{ 7306d0b52edSRichard Henderson /* For 32-bit comparisons, we can play games with ADDC/SUBC. */ 7316d0b52edSRichard Henderson switch (cond) { 7326d0b52edSRichard Henderson case TCG_COND_LTU: 7336d0b52edSRichard Henderson case TCG_COND_GEU: 7346d0b52edSRichard Henderson /* The result of the comparison is in the carry bit. */ 7356d0b52edSRichard Henderson break; 7366d0b52edSRichard Henderson 7376d0b52edSRichard Henderson case TCG_COND_EQ: 7386d0b52edSRichard Henderson case TCG_COND_NE: 7396d0b52edSRichard Henderson /* For equality, we can transform to inequality vs zero. */ 7406d0b52edSRichard Henderson if (c2 != 0) { 7416d0b52edSRichard Henderson tcg_out_arithc(s, TCG_REG_T1, c1, c2, c2const, ARITH_XOR); 7426d0b52edSRichard Henderson c2 = TCG_REG_T1; 7436d0b52edSRichard Henderson } else { 7446d0b52edSRichard Henderson c2 = c1; 7456d0b52edSRichard Henderson } 7466d0b52edSRichard Henderson c1 = TCG_REG_G0, c2const = 0; 7476d0b52edSRichard Henderson cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU); 7486d0b52edSRichard Henderson break; 7496d0b52edSRichard Henderson 750b9ddaf56SRichard Henderson case TCG_COND_TSTEQ: 751b9ddaf56SRichard Henderson case TCG_COND_TSTNE: 752b9ddaf56SRichard Henderson /* Transform to inequality vs zero. */ 753b9ddaf56SRichard Henderson tcg_out_arithc(s, TCG_REG_T1, c1, c2, c2const, ARITH_AND); 754b9ddaf56SRichard Henderson c1 = TCG_REG_G0; 755b9ddaf56SRichard Henderson c2 = TCG_REG_T1, c2const = 0; 756b9ddaf56SRichard Henderson cond = (cond == TCG_COND_TSTEQ ? TCG_COND_GEU : TCG_COND_LTU); 757b9ddaf56SRichard Henderson break; 758b9ddaf56SRichard Henderson 7596d0b52edSRichard Henderson case TCG_COND_GTU: 7606d0b52edSRichard Henderson case TCG_COND_LEU: 7616d0b52edSRichard Henderson /* If we don't need to load a constant into a register, we can 7626d0b52edSRichard Henderson swap the operands on GTU/LEU. There's no benefit to loading 7636d0b52edSRichard Henderson the constant into a temporary register. */ 7646d0b52edSRichard Henderson if (!c2const || c2 == 0) { 7656d0b52edSRichard Henderson TCGReg t = c1; 7666d0b52edSRichard Henderson c1 = c2; 7676d0b52edSRichard Henderson c2 = t; 7686d0b52edSRichard Henderson c2const = 0; 7696d0b52edSRichard Henderson cond = tcg_swap_cond(cond); 7706d0b52edSRichard Henderson break; 7716d0b52edSRichard Henderson } 7726d0b52edSRichard Henderson /* FALLTHRU */ 7736d0b52edSRichard Henderson 7746d0b52edSRichard Henderson default: 775905afe37SRichard Henderson tcg_out_cmp(s, cond, c1, c2, c2const); 7768b14f862SRichard Henderson tcg_out_movi_s13(s, ret, 0); 777a0fdd7c9SRichard Henderson tcg_out_movcc(s, cond, MOVCC_ICC, ret, neg ? -1 : 1, 1); 7786d0b52edSRichard Henderson return; 7796d0b52edSRichard Henderson } 7806d0b52edSRichard Henderson 781905afe37SRichard Henderson tcg_out_cmp(s, cond, c1, c2, c2const); 7826d0b52edSRichard Henderson if (cond == TCG_COND_LTU) { 783a0fdd7c9SRichard Henderson if (neg) { 784a0fdd7c9SRichard Henderson /* 0 - 0 - C = -C = (C ? -1 : 0) */ 785a0fdd7c9SRichard Henderson tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_SUBC); 7866d0b52edSRichard Henderson } else { 787a0fdd7c9SRichard Henderson /* 0 + 0 + C = C = (C ? 1 : 0) */ 788a0fdd7c9SRichard Henderson tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDC); 789a0fdd7c9SRichard Henderson } 790a0fdd7c9SRichard Henderson } else { 791a0fdd7c9SRichard Henderson if (neg) { 792a0fdd7c9SRichard Henderson /* 0 + -1 + C = C - 1 = (C ? 0 : -1) */ 793a0fdd7c9SRichard Henderson tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_ADDC); 794a0fdd7c9SRichard Henderson } else { 795a0fdd7c9SRichard Henderson /* 0 - -1 - C = 1 - C = (C ? 0 : 1) */ 7966d0b52edSRichard Henderson tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBC); 7976d0b52edSRichard Henderson } 7986d0b52edSRichard Henderson } 799a0fdd7c9SRichard Henderson} 8006d0b52edSRichard Henderson 8016d0b52edSRichard Hendersonstatic void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret, 802a0fdd7c9SRichard Henderson TCGReg c1, int32_t c2, int c2const, bool neg) 8036d0b52edSRichard Henderson{ 8046bc74a53SRichard Henderson int rcond; 8056bc74a53SRichard Henderson 806a0fdd7c9SRichard Henderson if (use_vis3_instructions && !neg) { 8076d0b52edSRichard Henderson switch (cond) { 8086d0b52edSRichard Henderson case TCG_COND_NE: 8096d0b52edSRichard Henderson if (c2 != 0) { 8106d0b52edSRichard Henderson break; 8116d0b52edSRichard Henderson } 8126d0b52edSRichard Henderson c2 = c1, c2const = 0, c1 = TCG_REG_G0; 8136d0b52edSRichard Henderson /* FALLTHRU */ 8146d0b52edSRichard Henderson case TCG_COND_LTU: 815905afe37SRichard Henderson tcg_out_cmp(s, cond, c1, c2, c2const); 8166d0b52edSRichard Henderson tcg_out_arith(s, ret, TCG_REG_G0, TCG_REG_G0, ARITH_ADDXC); 8176d0b52edSRichard Henderson return; 8186d0b52edSRichard Henderson default: 8196d0b52edSRichard Henderson break; 8206d0b52edSRichard Henderson } 8216d0b52edSRichard Henderson } 8226d0b52edSRichard Henderson 8236d0b52edSRichard Henderson /* For 64-bit signed comparisons vs zero, we can avoid the compare 8246d0b52edSRichard Henderson if the input does not overlap the output. */ 8256bc74a53SRichard Henderson rcond = tcg_cond_to_rcond[cond]; 8266bc74a53SRichard Henderson if (c2 == 0 && rcond && c1 != ret) { 8278b14f862SRichard Henderson tcg_out_movi_s13(s, ret, 0); 8286bc74a53SRichard Henderson tcg_out_movr(s, rcond, ret, c1, neg ? -1 : 1, 1); 8296d0b52edSRichard Henderson } else { 830905afe37SRichard Henderson tcg_out_cmp(s, cond, c1, c2, c2const); 8318b14f862SRichard Henderson tcg_out_movi_s13(s, ret, 0); 832a0fdd7c9SRichard Henderson tcg_out_movcc(s, cond, MOVCC_XCC, ret, neg ? -1 : 1, 1); 8336d0b52edSRichard Henderson } 8346d0b52edSRichard Henderson} 8356d0b52edSRichard Henderson 8366d0b52edSRichard Hendersonstatic void tcg_out_addsub2_i32(TCGContext *s, TCGReg rl, TCGReg rh, 8376d0b52edSRichard Henderson TCGReg al, TCGReg ah, int32_t bl, int blconst, 8386d0b52edSRichard Henderson int32_t bh, int bhconst, int opl, int oph) 8396d0b52edSRichard Henderson{ 8406d0b52edSRichard Henderson TCGReg tmp = TCG_REG_T1; 8416d0b52edSRichard Henderson 8426d0b52edSRichard Henderson /* Note that the low parts are fully consumed before tmp is set. */ 8436d0b52edSRichard Henderson if (rl != ah && (bhconst || rl != bh)) { 8446d0b52edSRichard Henderson tmp = rl; 8456d0b52edSRichard Henderson } 8466d0b52edSRichard Henderson 8476d0b52edSRichard Henderson tcg_out_arithc(s, tmp, al, bl, blconst, opl); 8486d0b52edSRichard Henderson tcg_out_arithc(s, rh, ah, bh, bhconst, oph); 8496d0b52edSRichard Henderson tcg_out_mov(s, TCG_TYPE_I32, rl, tmp); 8506d0b52edSRichard Henderson} 8516d0b52edSRichard Henderson 8526d0b52edSRichard Hendersonstatic void tcg_out_addsub2_i64(TCGContext *s, TCGReg rl, TCGReg rh, 8536d0b52edSRichard Henderson TCGReg al, TCGReg ah, int32_t bl, int blconst, 8546d0b52edSRichard Henderson int32_t bh, int bhconst, bool is_sub) 8556d0b52edSRichard Henderson{ 8566d0b52edSRichard Henderson TCGReg tmp = TCG_REG_T1; 8576d0b52edSRichard Henderson 8586d0b52edSRichard Henderson /* Note that the low parts are fully consumed before tmp is set. */ 8596d0b52edSRichard Henderson if (rl != ah && (bhconst || rl != bh)) { 8606d0b52edSRichard Henderson tmp = rl; 8616d0b52edSRichard Henderson } 8626d0b52edSRichard Henderson 8636d0b52edSRichard Henderson tcg_out_arithc(s, tmp, al, bl, blconst, is_sub ? ARITH_SUBCC : ARITH_ADDCC); 8646d0b52edSRichard Henderson 8656d0b52edSRichard Henderson if (use_vis3_instructions && !is_sub) { 8666d0b52edSRichard Henderson /* Note that ADDXC doesn't accept immediates. */ 8676d0b52edSRichard Henderson if (bhconst && bh != 0) { 8688b14f862SRichard Henderson tcg_out_movi_s13(s, TCG_REG_T2, bh); 8696d0b52edSRichard Henderson bh = TCG_REG_T2; 8706d0b52edSRichard Henderson } 8716d0b52edSRichard Henderson tcg_out_arith(s, rh, ah, bh, ARITH_ADDXC); 8726d0b52edSRichard Henderson } else if (bh == TCG_REG_G0) { 8736d0b52edSRichard Henderson /* If we have a zero, we can perform the operation in two insns, 8746d0b52edSRichard Henderson with the arithmetic first, and a conditional move into place. */ 8756d0b52edSRichard Henderson if (rh == ah) { 8766d0b52edSRichard Henderson tcg_out_arithi(s, TCG_REG_T2, ah, 1, 8776d0b52edSRichard Henderson is_sub ? ARITH_SUB : ARITH_ADD); 8786d0b52edSRichard Henderson tcg_out_movcc(s, TCG_COND_LTU, MOVCC_XCC, rh, TCG_REG_T2, 0); 8796d0b52edSRichard Henderson } else { 8806d0b52edSRichard Henderson tcg_out_arithi(s, rh, ah, 1, is_sub ? ARITH_SUB : ARITH_ADD); 8816d0b52edSRichard Henderson tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, rh, ah, 0); 8826d0b52edSRichard Henderson } 8836d0b52edSRichard Henderson } else { 8846d0b52edSRichard Henderson /* 8856d0b52edSRichard Henderson * Otherwise adjust BH as if there is carry into T2. 8866d0b52edSRichard Henderson * Note that constant BH is constrained to 11 bits for the MOVCC, 8876d0b52edSRichard Henderson * so the adjustment fits 12 bits. 8886d0b52edSRichard Henderson */ 8896d0b52edSRichard Henderson if (bhconst) { 8908b14f862SRichard Henderson tcg_out_movi_s13(s, TCG_REG_T2, bh + (is_sub ? -1 : 1)); 8916d0b52edSRichard Henderson } else { 8926d0b52edSRichard Henderson tcg_out_arithi(s, TCG_REG_T2, bh, 1, 8936d0b52edSRichard Henderson is_sub ? ARITH_SUB : ARITH_ADD); 8946d0b52edSRichard Henderson } 8956d0b52edSRichard Henderson /* ... smoosh T2 back to original BH if carry is clear ... */ 8966d0b52edSRichard Henderson tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, TCG_REG_T2, bh, bhconst); 8976d0b52edSRichard Henderson /* ... and finally perform the arithmetic with the new operand. */ 8986d0b52edSRichard Henderson tcg_out_arith(s, rh, ah, TCG_REG_T2, is_sub ? ARITH_SUB : ARITH_ADD); 8996d0b52edSRichard Henderson } 9006d0b52edSRichard Henderson 9016d0b52edSRichard Henderson tcg_out_mov(s, TCG_TYPE_I64, rl, tmp); 9026d0b52edSRichard Henderson} 9036d0b52edSRichard Henderson 9046d0b52edSRichard Hendersonstatic void tcg_out_jmpl_const(TCGContext *s, const tcg_insn_unit *dest, 9056d0b52edSRichard Henderson bool in_prologue, bool tail_call) 9066d0b52edSRichard Henderson{ 9076d0b52edSRichard Henderson uintptr_t desti = (uintptr_t)dest; 9086d0b52edSRichard Henderson 9096d0b52edSRichard Henderson tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_REG_T1, 91033982b89SRichard Henderson desti & ~0xfff, in_prologue, TCG_REG_T2); 9116d0b52edSRichard Henderson tcg_out_arithi(s, tail_call ? TCG_REG_G0 : TCG_REG_O7, 9126d0b52edSRichard Henderson TCG_REG_T1, desti & 0xfff, JMPL); 9136d0b52edSRichard Henderson} 9146d0b52edSRichard Henderson 9156d0b52edSRichard Hendersonstatic void tcg_out_call_nodelay(TCGContext *s, const tcg_insn_unit *dest, 9166d0b52edSRichard Henderson bool in_prologue) 9176d0b52edSRichard Henderson{ 9186d0b52edSRichard Henderson ptrdiff_t disp = tcg_pcrel_diff(s, dest); 9196d0b52edSRichard Henderson 9206d0b52edSRichard Henderson if (disp == (int32_t)disp) { 9216d0b52edSRichard Henderson tcg_out32(s, CALL | (uint32_t)disp >> 2); 9226d0b52edSRichard Henderson } else { 9236d0b52edSRichard Henderson tcg_out_jmpl_const(s, dest, in_prologue, false); 9246d0b52edSRichard Henderson } 9256d0b52edSRichard Henderson} 9266d0b52edSRichard Henderson 927cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *dest, 928cee44b03SRichard Henderson const TCGHelperInfo *info) 9296d0b52edSRichard Henderson{ 9306d0b52edSRichard Henderson tcg_out_call_nodelay(s, dest, false); 9316d0b52edSRichard Henderson tcg_out_nop(s); 9326d0b52edSRichard Henderson} 9336d0b52edSRichard Henderson 9346d0b52edSRichard Hendersonstatic void tcg_out_mb(TCGContext *s, TCGArg a0) 9356d0b52edSRichard Henderson{ 9366d0b52edSRichard Henderson /* Note that the TCG memory order constants mirror the Sparc MEMBAR. */ 9376d0b52edSRichard Henderson tcg_out32(s, MEMBAR | (a0 & TCG_MO_ALL)); 9386d0b52edSRichard Henderson} 9396d0b52edSRichard Henderson 9406d0b52edSRichard Henderson/* Generate global QEMU prologue and epilogue code */ 9416d0b52edSRichard Hendersonstatic void tcg_target_qemu_prologue(TCGContext *s) 9426d0b52edSRichard Henderson{ 9436d0b52edSRichard Henderson int tmp_buf_size, frame_size; 9446d0b52edSRichard Henderson 9456d0b52edSRichard Henderson /* 9466d0b52edSRichard Henderson * The TCG temp buffer is at the top of the frame, immediately 9476d0b52edSRichard Henderson * below the frame pointer. Use the logical (aligned) offset here; 9486d0b52edSRichard Henderson * the stack bias is applied in temp_allocate_frame(). 9496d0b52edSRichard Henderson */ 9506d0b52edSRichard Henderson tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long); 9516d0b52edSRichard Henderson tcg_set_frame(s, TCG_REG_I6, -tmp_buf_size, tmp_buf_size); 9526d0b52edSRichard Henderson 9536d0b52edSRichard Henderson /* 9546d0b52edSRichard Henderson * TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is 9556d0b52edSRichard Henderson * otherwise the minimal frame usable by callees. 9566d0b52edSRichard Henderson */ 9576d0b52edSRichard Henderson frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS; 9586d0b52edSRichard Henderson frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size; 9596d0b52edSRichard Henderson frame_size += TCG_TARGET_STACK_ALIGN - 1; 9606d0b52edSRichard Henderson frame_size &= -TCG_TARGET_STACK_ALIGN; 9616d0b52edSRichard Henderson tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) | 9626d0b52edSRichard Henderson INSN_IMM13(-frame_size)); 9636d0b52edSRichard Henderson 9646d0b52edSRichard Henderson#ifndef CONFIG_SOFTMMU 9656d0b52edSRichard Henderson if (guest_base != 0) { 9666d0b52edSRichard Henderson tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, 9676d0b52edSRichard Henderson guest_base, true, TCG_REG_T1); 9686d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); 9696d0b52edSRichard Henderson } 9706d0b52edSRichard Henderson#endif 9716d0b52edSRichard Henderson 9726d0b52edSRichard Henderson /* We choose TCG_REG_TB such that no move is required. */ 9736d0b52edSRichard Henderson QEMU_BUILD_BUG_ON(TCG_REG_TB != TCG_REG_I1); 9746d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); 9756d0b52edSRichard Henderson 9766d0b52edSRichard Henderson tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL); 9776d0b52edSRichard Henderson /* delay slot */ 9786d0b52edSRichard Henderson tcg_out_nop(s); 9796d0b52edSRichard Henderson 9806d0b52edSRichard Henderson /* Epilogue for goto_ptr. */ 9816d0b52edSRichard Henderson tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); 9826d0b52edSRichard Henderson tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); 9836d0b52edSRichard Henderson /* delay slot */ 9848b14f862SRichard Henderson tcg_out_movi_s13(s, TCG_REG_O0, 0); 9856d0b52edSRichard Henderson} 9866d0b52edSRichard Henderson 9879358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s) 9889358fbbfSRichard Henderson{ 9899358fbbfSRichard Henderson /* nothing to do */ 9909358fbbfSRichard Henderson} 9919358fbbfSRichard Henderson 9926d0b52edSRichard Hendersonstatic void tcg_out_nop_fill(tcg_insn_unit *p, int count) 9936d0b52edSRichard Henderson{ 9946d0b52edSRichard Henderson int i; 9956d0b52edSRichard Henderson for (i = 0; i < count; ++i) { 9966d0b52edSRichard Henderson p[i] = NOP; 9976d0b52edSRichard Henderson } 9986d0b52edSRichard Henderson} 9996d0b52edSRichard Henderson 100029086503SRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = { 100129086503SRichard Henderson .ntmp = 1, .tmp = { TCG_REG_T1 } 100229086503SRichard Henderson}; 10036d0b52edSRichard Henderson 100429086503SRichard Hendersonstatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 10056d0b52edSRichard Henderson{ 100629086503SRichard Henderson MemOp opc = get_memop(lb->oi); 100729086503SRichard Henderson MemOp sgn; 100829086503SRichard Henderson 100929086503SRichard Henderson if (!patch_reloc(lb->label_ptr[0], R_SPARC_WDISP19, 101029086503SRichard Henderson (intptr_t)tcg_splitwx_to_rx(s->code_ptr), 0)) { 101129086503SRichard Henderson return false; 101229086503SRichard Henderson } 101329086503SRichard Henderson 101429086503SRichard Henderson /* Use inline tcg_out_ext32s; otherwise let the helper sign-extend. */ 101529086503SRichard Henderson sgn = (opc & MO_SIZE) < MO_32 ? MO_SIGN : 0; 101629086503SRichard Henderson 101729086503SRichard Henderson tcg_out_ld_helper_args(s, lb, &ldst_helper_param); 101829086503SRichard Henderson tcg_out_call(s, qemu_ld_helpers[opc & (MO_SIZE | sgn)], NULL); 101929086503SRichard Henderson tcg_out_ld_helper_ret(s, lb, sgn, &ldst_helper_param); 102029086503SRichard Henderson 102129086503SRichard Henderson tcg_out_bpcc0(s, COND_A, BPCC_A | BPCC_PT, 0); 102229086503SRichard Henderson return patch_reloc(s->code_ptr - 1, R_SPARC_WDISP19, 102329086503SRichard Henderson (intptr_t)lb->raddr, 0); 102429086503SRichard Henderson} 102529086503SRichard Henderson 102629086503SRichard Hendersonstatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) 102729086503SRichard Henderson{ 102829086503SRichard Henderson MemOp opc = get_memop(lb->oi); 102929086503SRichard Henderson 103029086503SRichard Henderson if (!patch_reloc(lb->label_ptr[0], R_SPARC_WDISP19, 103129086503SRichard Henderson (intptr_t)tcg_splitwx_to_rx(s->code_ptr), 0)) { 103229086503SRichard Henderson return false; 103329086503SRichard Henderson } 103429086503SRichard Henderson 103529086503SRichard Henderson tcg_out_st_helper_args(s, lb, &ldst_helper_param); 103629086503SRichard Henderson tcg_out_call(s, qemu_st_helpers[opc & MO_SIZE], NULL); 103729086503SRichard Henderson 103829086503SRichard Henderson tcg_out_bpcc0(s, COND_A, BPCC_A | BPCC_PT, 0); 103929086503SRichard Henderson return patch_reloc(s->code_ptr - 1, R_SPARC_WDISP19, 104029086503SRichard Henderson (intptr_t)lb->raddr, 0); 104129086503SRichard Henderson} 104229086503SRichard Henderson 104329086503SRichard Hendersontypedef struct { 104429086503SRichard Henderson TCGReg base; 104529086503SRichard Henderson TCGReg index; 10469ca63431SRichard Henderson TCGAtomAlign aa; 104729086503SRichard Henderson} HostAddress; 104829086503SRichard Henderson 10497b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop) 10507b880107SRichard Henderson{ 10517b880107SRichard Henderson return true; 10527b880107SRichard Henderson} 10537b880107SRichard Henderson 1054d0a9bb5eSRichard Henderson/* We expect to use a 13-bit negative offset from ENV. */ 1055d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS -(1 << 12) 1056d0a9bb5eSRichard Henderson 105729086503SRichard Henderson/* 10587893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare. 10597893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests. 106029086503SRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path 106129086503SRichard Henderson * is required and fill in @h with the host address for the fast path. 106229086503SRichard Henderson */ 106329086503SRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h, 106429086503SRichard Henderson TCGReg addr_reg, MemOpIdx oi, 106529086503SRichard Henderson bool is_ld) 106629086503SRichard Henderson{ 106740bca78dSRichard Henderson TCGType addr_type = s->addr_type; 106829086503SRichard Henderson TCGLabelQemuLdst *ldst = NULL; 106929086503SRichard Henderson MemOp opc = get_memop(oi); 10709ca63431SRichard Henderson MemOp s_bits = opc & MO_SIZE; 107129086503SRichard Henderson unsigned a_mask; 107229086503SRichard Henderson 107329086503SRichard Henderson /* We don't support unaligned accesses. */ 10749ca63431SRichard Henderson h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false); 10759ca63431SRichard Henderson h->aa.align = MAX(h->aa.align, s_bits); 10769ca63431SRichard Henderson a_mask = (1u << h->aa.align) - 1; 107729086503SRichard Henderson 107829086503SRichard Henderson#ifdef CONFIG_SOFTMMU 107929086503SRichard Henderson int mem_index = get_mmuidx(oi); 1080d0a9bb5eSRichard Henderson int fast_off = tlb_mask_table_ofs(s, mem_index); 10816d0b52edSRichard Henderson int mask_off = fast_off + offsetof(CPUTLBDescFast, mask); 10826d0b52edSRichard Henderson int table_off = fast_off + offsetof(CPUTLBDescFast, table); 108329086503SRichard Henderson int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read) 108429086503SRichard Henderson : offsetof(CPUTLBEntry, addr_write); 108529086503SRichard Henderson int add_off = offsetof(CPUTLBEntry, addend); 108629086503SRichard Henderson int compare_mask; 108729086503SRichard Henderson int cc; 10886d0b52edSRichard Henderson 10896d0b52edSRichard Henderson /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */ 109029086503SRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_T2, TCG_AREG0, mask_off); 109129086503SRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_T3, TCG_AREG0, table_off); 10926d0b52edSRichard Henderson 10936d0b52edSRichard Henderson /* Extract the page index, shifted into place for tlb index. */ 109429086503SRichard Henderson tcg_out_arithi(s, TCG_REG_T1, addr_reg, 1095aece72b7SRichard Henderson s->page_bits - CPU_TLB_ENTRY_BITS, SHIFT_SRL); 109629086503SRichard Henderson tcg_out_arith(s, TCG_REG_T1, TCG_REG_T1, TCG_REG_T2, ARITH_AND); 10976d0b52edSRichard Henderson 10986d0b52edSRichard Henderson /* Add the tlb_table pointer, creating the CPUTLBEntry address into R2. */ 109929086503SRichard Henderson tcg_out_arith(s, TCG_REG_T1, TCG_REG_T1, TCG_REG_T3, ARITH_ADD); 11006d0b52edSRichard Henderson 1101238f4380SRichard Henderson /* 1102238f4380SRichard Henderson * Load the tlb comparator and the addend. 1103238f4380SRichard Henderson * Always load the entire 64-bit comparator for simplicity. 1104238f4380SRichard Henderson * We will ignore the high bits via BPCC_ICC below. 1105238f4380SRichard Henderson */ 1106238f4380SRichard Henderson tcg_out_ld(s, TCG_TYPE_I64, TCG_REG_T2, TCG_REG_T1, cmp_off); 110729086503SRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_T1, TCG_REG_T1, add_off); 110829086503SRichard Henderson h->base = TCG_REG_T1; 11096d0b52edSRichard Henderson 111029086503SRichard Henderson /* Mask out the page offset, except for the required alignment. */ 1111aece72b7SRichard Henderson compare_mask = s->page_mask | a_mask; 11126d0b52edSRichard Henderson if (check_fit_tl(compare_mask, 13)) { 111329086503SRichard Henderson tcg_out_arithi(s, TCG_REG_T3, addr_reg, compare_mask, ARITH_AND); 11146d0b52edSRichard Henderson } else { 111529086503SRichard Henderson tcg_out_movi_s32(s, TCG_REG_T3, compare_mask); 111629086503SRichard Henderson tcg_out_arith(s, TCG_REG_T3, addr_reg, TCG_REG_T3, ARITH_AND); 11176d0b52edSRichard Henderson } 1118905afe37SRichard Henderson tcg_out_cmp(s, TCG_COND_NE, TCG_REG_T2, TCG_REG_T3, 0); 11196d0b52edSRichard Henderson 112029086503SRichard Henderson ldst = new_ldst_label(s); 112129086503SRichard Henderson ldst->is_ld = is_ld; 112229086503SRichard Henderson ldst->oi = oi; 112329086503SRichard Henderson ldst->addrlo_reg = addr_reg; 112429086503SRichard Henderson ldst->label_ptr[0] = s->code_ptr; 112529086503SRichard Henderson 112629086503SRichard Henderson /* bne,pn %[xi]cc, label0 */ 112740bca78dSRichard Henderson cc = addr_type == TCG_TYPE_I32 ? BPCC_ICC : BPCC_XCC; 112829086503SRichard Henderson tcg_out_bpcc0(s, COND_NE, BPCC_PN | cc, 0); 112929086503SRichard Henderson#else 113029086503SRichard Henderson /* 11319ca63431SRichard Henderson * If the size equals the required alignment, we can skip the test 11329ca63431SRichard Henderson * and allow host SIGBUS to deliver SIGBUS to the guest. 11339ca63431SRichard Henderson * Otherwise, test for at least natural alignment and defer 113429086503SRichard Henderson * everything else to the helper functions. 113529086503SRichard Henderson */ 1136*c5809eeeSRichard Henderson if (s_bits != memop_alignment_bits(opc)) { 113729086503SRichard Henderson tcg_debug_assert(check_fit_tl(a_mask, 13)); 113829086503SRichard Henderson tcg_out_arithi(s, TCG_REG_G0, addr_reg, a_mask, ARITH_ANDCC); 113929086503SRichard Henderson 114029086503SRichard Henderson ldst = new_ldst_label(s); 114129086503SRichard Henderson ldst->is_ld = is_ld; 114229086503SRichard Henderson ldst->oi = oi; 114329086503SRichard Henderson ldst->addrlo_reg = addr_reg; 114429086503SRichard Henderson ldst->label_ptr[0] = s->code_ptr; 114529086503SRichard Henderson 114629086503SRichard Henderson /* bne,pn %icc, label0 */ 114729086503SRichard Henderson tcg_out_bpcc0(s, COND_NE, BPCC_PN | BPCC_ICC, 0); 114829086503SRichard Henderson } 114929086503SRichard Henderson h->base = guest_base ? TCG_GUEST_BASE_REG : TCG_REG_G0; 115029086503SRichard Henderson#endif 115129086503SRichard Henderson 115229086503SRichard Henderson /* If the guest address must be zero-extended, do in the delay slot. */ 115340bca78dSRichard Henderson if (addr_type == TCG_TYPE_I32) { 115429086503SRichard Henderson tcg_out_ext32u(s, TCG_REG_T2, addr_reg); 115529086503SRichard Henderson h->index = TCG_REG_T2; 115629086503SRichard Henderson } else { 115729086503SRichard Henderson if (ldst) { 115829086503SRichard Henderson tcg_out_nop(s); 11596d0b52edSRichard Henderson } 116029086503SRichard Henderson h->index = addr_reg; 11616d0b52edSRichard Henderson } 116229086503SRichard Henderson return ldst; 116329086503SRichard Henderson} 11646d0b52edSRichard Henderson 116529086503SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr, 116629086503SRichard Henderson MemOpIdx oi, TCGType data_type) 116729086503SRichard Henderson{ 116829086503SRichard Henderson static const int ld_opc[(MO_SSIZE | MO_BSWAP) + 1] = { 11696d0b52edSRichard Henderson [MO_UB] = LDUB, 11706d0b52edSRichard Henderson [MO_SB] = LDSB, 11716d0b52edSRichard Henderson [MO_UB | MO_LE] = LDUB, 11726d0b52edSRichard Henderson [MO_SB | MO_LE] = LDSB, 11736d0b52edSRichard Henderson 11746d0b52edSRichard Henderson [MO_BEUW] = LDUH, 11756d0b52edSRichard Henderson [MO_BESW] = LDSH, 11766d0b52edSRichard Henderson [MO_BEUL] = LDUW, 11776d0b52edSRichard Henderson [MO_BESL] = LDSW, 11786d0b52edSRichard Henderson [MO_BEUQ] = LDX, 11796d0b52edSRichard Henderson [MO_BESQ] = LDX, 11806d0b52edSRichard Henderson 11816d0b52edSRichard Henderson [MO_LEUW] = LDUH_LE, 11826d0b52edSRichard Henderson [MO_LESW] = LDSH_LE, 11836d0b52edSRichard Henderson [MO_LEUL] = LDUW_LE, 11846d0b52edSRichard Henderson [MO_LESL] = LDSW_LE, 11856d0b52edSRichard Henderson [MO_LEUQ] = LDX_LE, 11866d0b52edSRichard Henderson [MO_LESQ] = LDX_LE, 11876d0b52edSRichard Henderson }; 11886d0b52edSRichard Henderson 118929086503SRichard Henderson TCGLabelQemuLdst *ldst; 119029086503SRichard Henderson HostAddress h; 119129086503SRichard Henderson 119229086503SRichard Henderson ldst = prepare_host_addr(s, &h, addr, oi, true); 119329086503SRichard Henderson 119429086503SRichard Henderson tcg_out_ldst_rr(s, data, h.base, h.index, 119529086503SRichard Henderson ld_opc[get_memop(oi) & (MO_BSWAP | MO_SSIZE)]); 119629086503SRichard Henderson 119729086503SRichard Henderson if (ldst) { 119829086503SRichard Henderson ldst->type = data_type; 119929086503SRichard Henderson ldst->datalo_reg = data; 120029086503SRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 120129086503SRichard Henderson } 120229086503SRichard Henderson} 120329086503SRichard Henderson 120429086503SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr, 120529086503SRichard Henderson MemOpIdx oi, TCGType data_type) 120629086503SRichard Henderson{ 120729086503SRichard Henderson static const int st_opc[(MO_SIZE | MO_BSWAP) + 1] = { 12086d0b52edSRichard Henderson [MO_UB] = STB, 12096d0b52edSRichard Henderson 12106d0b52edSRichard Henderson [MO_BEUW] = STH, 12116d0b52edSRichard Henderson [MO_BEUL] = STW, 12126d0b52edSRichard Henderson [MO_BEUQ] = STX, 12136d0b52edSRichard Henderson 12146d0b52edSRichard Henderson [MO_LEUW] = STH_LE, 12156d0b52edSRichard Henderson [MO_LEUL] = STW_LE, 12166d0b52edSRichard Henderson [MO_LEUQ] = STX_LE, 12176d0b52edSRichard Henderson }; 12186d0b52edSRichard Henderson 121929086503SRichard Henderson TCGLabelQemuLdst *ldst; 122029086503SRichard Henderson HostAddress h; 12216d0b52edSRichard Henderson 122229086503SRichard Henderson ldst = prepare_host_addr(s, &h, addr, oi, false); 12236d0b52edSRichard Henderson 122429086503SRichard Henderson tcg_out_ldst_rr(s, data, h.base, h.index, 122529086503SRichard Henderson st_opc[get_memop(oi) & (MO_BSWAP | MO_SIZE)]); 12266d0b52edSRichard Henderson 122729086503SRichard Henderson if (ldst) { 122829086503SRichard Henderson ldst->type = data_type; 122929086503SRichard Henderson ldst->datalo_reg = data; 123029086503SRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 12316d0b52edSRichard Henderson } 12326d0b52edSRichard Henderson} 12336d0b52edSRichard Henderson 1234b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) 1235b55a8d9dSRichard Henderson{ 1236b55a8d9dSRichard Henderson if (check_fit_ptr(a0, 13)) { 1237b55a8d9dSRichard Henderson tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); 12388b14f862SRichard Henderson tcg_out_movi_s13(s, TCG_REG_O0, a0); 1239b55a8d9dSRichard Henderson return; 12401e42b4f8SRichard Henderson } else { 1241b55a8d9dSRichard Henderson intptr_t tb_diff = tcg_tbrel_diff(s, (void *)a0); 1242b55a8d9dSRichard Henderson if (check_fit_ptr(tb_diff, 13)) { 1243b55a8d9dSRichard Henderson tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); 1244b55a8d9dSRichard Henderson /* Note that TCG_REG_TB has been unwound to O1. */ 1245b55a8d9dSRichard Henderson tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O1, tb_diff, ARITH_ADD); 1246b55a8d9dSRichard Henderson return; 1247b55a8d9dSRichard Henderson } 1248b55a8d9dSRichard Henderson } 1249b55a8d9dSRichard Henderson tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, a0 & ~0x3ff); 1250b55a8d9dSRichard Henderson tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); 1251b55a8d9dSRichard Henderson tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR); 1252b55a8d9dSRichard Henderson} 1253b55a8d9dSRichard Henderson 1254cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which) 1255cf7d6b8eSRichard Henderson{ 1256a228ae3eSRichard Henderson ptrdiff_t off = tcg_tbrel_diff(s, (void *)get_jmp_target_addr(s, which)); 12571e42b4f8SRichard Henderson 12581ffbe5d6SRichard Henderson /* Load link and indirect branch. */ 1259cf7d6b8eSRichard Henderson set_jmp_insn_offset(s, which); 1260a228ae3eSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TB, TCG_REG_TB, off); 12611ffbe5d6SRichard Henderson tcg_out_arithi(s, TCG_REG_G0, TCG_REG_TB, 0, JMPL); 12621ffbe5d6SRichard Henderson /* delay slot */ 12631ffbe5d6SRichard Henderson tcg_out_nop(s); 1264cf7d6b8eSRichard Henderson set_jmp_reset_offset(s, which); 1265cf7d6b8eSRichard Henderson 1266cf7d6b8eSRichard Henderson /* 1267cf7d6b8eSRichard Henderson * For the unlinked path of goto_tb, we need to reset TCG_REG_TB 1268cf7d6b8eSRichard Henderson * to the beginning of this TB. 1269cf7d6b8eSRichard Henderson */ 1270a228ae3eSRichard Henderson off = -tcg_current_code_size(s); 1271a228ae3eSRichard Henderson if (check_fit_i32(off, 13)) { 1272a228ae3eSRichard Henderson tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, off, ARITH_ADD); 1273cf7d6b8eSRichard Henderson } else { 1274a228ae3eSRichard Henderson tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, off); 1275cf7d6b8eSRichard Henderson tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); 1276cf7d6b8eSRichard Henderson } 1277cf7d6b8eSRichard Henderson} 1278cf7d6b8eSRichard Henderson 1279a228ae3eSRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n, 1280a228ae3eSRichard Henderson uintptr_t jmp_rx, uintptr_t jmp_rw) 1281a228ae3eSRichard Henderson{ 1282a228ae3eSRichard Henderson} 1283a228ae3eSRichard Henderson 12846d0b52edSRichard Hendersonstatic void tcg_out_op(TCGContext *s, TCGOpcode opc, 12856d0b52edSRichard Henderson const TCGArg args[TCG_MAX_OP_ARGS], 12866d0b52edSRichard Henderson const int const_args[TCG_MAX_OP_ARGS]) 12876d0b52edSRichard Henderson{ 12886d0b52edSRichard Henderson TCGArg a0, a1, a2; 12896d0b52edSRichard Henderson int c, c2; 12906d0b52edSRichard Henderson 12916d0b52edSRichard Henderson /* Hoist the loads of the most common arguments. */ 12926d0b52edSRichard Henderson a0 = args[0]; 12936d0b52edSRichard Henderson a1 = args[1]; 12946d0b52edSRichard Henderson a2 = args[2]; 12956d0b52edSRichard Henderson c2 = const_args[2]; 12966d0b52edSRichard Henderson 12976d0b52edSRichard Henderson switch (opc) { 12986d0b52edSRichard Henderson case INDEX_op_goto_ptr: 12996d0b52edSRichard Henderson tcg_out_arithi(s, TCG_REG_G0, a0, 0, JMPL); 13006d0b52edSRichard Henderson tcg_out_mov_delay(s, TCG_REG_TB, a0); 13016d0b52edSRichard Henderson break; 13026d0b52edSRichard Henderson case INDEX_op_br: 13036d0b52edSRichard Henderson tcg_out_bpcc(s, COND_A, BPCC_PT, arg_label(a0)); 13046d0b52edSRichard Henderson tcg_out_nop(s); 13056d0b52edSRichard Henderson break; 13066d0b52edSRichard Henderson 13076d0b52edSRichard Henderson#define OP_32_64(x) \ 13086d0b52edSRichard Henderson glue(glue(case INDEX_op_, x), _i32): \ 13096d0b52edSRichard Henderson glue(glue(case INDEX_op_, x), _i64) 13106d0b52edSRichard Henderson 13116d0b52edSRichard Henderson OP_32_64(ld8u): 13126d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, LDUB); 13136d0b52edSRichard Henderson break; 13146d0b52edSRichard Henderson OP_32_64(ld8s): 13156d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, LDSB); 13166d0b52edSRichard Henderson break; 13176d0b52edSRichard Henderson OP_32_64(ld16u): 13186d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, LDUH); 13196d0b52edSRichard Henderson break; 13206d0b52edSRichard Henderson OP_32_64(ld16s): 13216d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, LDSH); 13226d0b52edSRichard Henderson break; 13236d0b52edSRichard Henderson case INDEX_op_ld_i32: 13246d0b52edSRichard Henderson case INDEX_op_ld32u_i64: 13256d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, LDUW); 13266d0b52edSRichard Henderson break; 13276d0b52edSRichard Henderson OP_32_64(st8): 13286d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, STB); 13296d0b52edSRichard Henderson break; 13306d0b52edSRichard Henderson OP_32_64(st16): 13316d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, STH); 13326d0b52edSRichard Henderson break; 13336d0b52edSRichard Henderson case INDEX_op_st_i32: 13346d0b52edSRichard Henderson case INDEX_op_st32_i64: 13356d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, STW); 13366d0b52edSRichard Henderson break; 13376d0b52edSRichard Henderson OP_32_64(add): 13386d0b52edSRichard Henderson c = ARITH_ADD; 13396d0b52edSRichard Henderson goto gen_arith; 13406d0b52edSRichard Henderson OP_32_64(sub): 13416d0b52edSRichard Henderson c = ARITH_SUB; 13426d0b52edSRichard Henderson goto gen_arith; 13436d0b52edSRichard Henderson OP_32_64(and): 13446d0b52edSRichard Henderson c = ARITH_AND; 13456d0b52edSRichard Henderson goto gen_arith; 13466d0b52edSRichard Henderson OP_32_64(andc): 13476d0b52edSRichard Henderson c = ARITH_ANDN; 13486d0b52edSRichard Henderson goto gen_arith; 13496d0b52edSRichard Henderson OP_32_64(or): 13506d0b52edSRichard Henderson c = ARITH_OR; 13516d0b52edSRichard Henderson goto gen_arith; 13526d0b52edSRichard Henderson OP_32_64(orc): 13536d0b52edSRichard Henderson c = ARITH_ORN; 13546d0b52edSRichard Henderson goto gen_arith; 13556d0b52edSRichard Henderson OP_32_64(xor): 13566d0b52edSRichard Henderson c = ARITH_XOR; 13576d0b52edSRichard Henderson goto gen_arith; 13586d0b52edSRichard Henderson case INDEX_op_shl_i32: 13596d0b52edSRichard Henderson c = SHIFT_SLL; 13606d0b52edSRichard Henderson do_shift32: 13616d0b52edSRichard Henderson /* Limit immediate shift count lest we create an illegal insn. */ 13626d0b52edSRichard Henderson tcg_out_arithc(s, a0, a1, a2 & 31, c2, c); 13636d0b52edSRichard Henderson break; 13646d0b52edSRichard Henderson case INDEX_op_shr_i32: 13656d0b52edSRichard Henderson c = SHIFT_SRL; 13666d0b52edSRichard Henderson goto do_shift32; 13676d0b52edSRichard Henderson case INDEX_op_sar_i32: 13686d0b52edSRichard Henderson c = SHIFT_SRA; 13696d0b52edSRichard Henderson goto do_shift32; 13706d0b52edSRichard Henderson case INDEX_op_mul_i32: 13716d0b52edSRichard Henderson c = ARITH_UMUL; 13726d0b52edSRichard Henderson goto gen_arith; 13736d0b52edSRichard Henderson 13746d0b52edSRichard Henderson OP_32_64(neg): 13756d0b52edSRichard Henderson c = ARITH_SUB; 13766d0b52edSRichard Henderson goto gen_arith1; 13776d0b52edSRichard Henderson OP_32_64(not): 13786d0b52edSRichard Henderson c = ARITH_ORN; 13796d0b52edSRichard Henderson goto gen_arith1; 13806d0b52edSRichard Henderson 13816d0b52edSRichard Henderson case INDEX_op_div_i32: 13826d0b52edSRichard Henderson tcg_out_div32(s, a0, a1, a2, c2, 0); 13836d0b52edSRichard Henderson break; 13846d0b52edSRichard Henderson case INDEX_op_divu_i32: 13856d0b52edSRichard Henderson tcg_out_div32(s, a0, a1, a2, c2, 1); 13866d0b52edSRichard Henderson break; 13876d0b52edSRichard Henderson 13886d0b52edSRichard Henderson case INDEX_op_brcond_i32: 13896d0b52edSRichard Henderson tcg_out_brcond_i32(s, a2, a0, a1, const_args[1], arg_label(args[3])); 13906d0b52edSRichard Henderson break; 13916d0b52edSRichard Henderson case INDEX_op_setcond_i32: 1392a0fdd7c9SRichard Henderson tcg_out_setcond_i32(s, args[3], a0, a1, a2, c2, false); 1393a0fdd7c9SRichard Henderson break; 1394a0fdd7c9SRichard Henderson case INDEX_op_negsetcond_i32: 1395a0fdd7c9SRichard Henderson tcg_out_setcond_i32(s, args[3], a0, a1, a2, c2, true); 13966d0b52edSRichard Henderson break; 13976d0b52edSRichard Henderson case INDEX_op_movcond_i32: 13986d0b52edSRichard Henderson tcg_out_movcond_i32(s, args[5], a0, a1, a2, c2, args[3], const_args[3]); 13996d0b52edSRichard Henderson break; 14006d0b52edSRichard Henderson 14016d0b52edSRichard Henderson case INDEX_op_add2_i32: 14026d0b52edSRichard Henderson tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3], 14036d0b52edSRichard Henderson args[4], const_args[4], args[5], const_args[5], 14046d0b52edSRichard Henderson ARITH_ADDCC, ARITH_ADDC); 14056d0b52edSRichard Henderson break; 14066d0b52edSRichard Henderson case INDEX_op_sub2_i32: 14076d0b52edSRichard Henderson tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3], 14086d0b52edSRichard Henderson args[4], const_args[4], args[5], const_args[5], 14096d0b52edSRichard Henderson ARITH_SUBCC, ARITH_SUBC); 14106d0b52edSRichard Henderson break; 14116d0b52edSRichard Henderson case INDEX_op_mulu2_i32: 14126d0b52edSRichard Henderson c = ARITH_UMUL; 14136d0b52edSRichard Henderson goto do_mul2; 14146d0b52edSRichard Henderson case INDEX_op_muls2_i32: 14156d0b52edSRichard Henderson c = ARITH_SMUL; 14166d0b52edSRichard Henderson do_mul2: 14176d0b52edSRichard Henderson /* The 32-bit multiply insns produce a full 64-bit result. */ 14186d0b52edSRichard Henderson tcg_out_arithc(s, a0, a2, args[3], const_args[3], c); 14196d0b52edSRichard Henderson tcg_out_arithi(s, a1, a0, 32, SHIFT_SRLX); 14206d0b52edSRichard Henderson break; 14216d0b52edSRichard Henderson 1422fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 1423fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 1424e2adae3fSRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); 14256d0b52edSRichard Henderson break; 1426fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 1427fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 1428e2adae3fSRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64); 14296d0b52edSRichard Henderson break; 1430fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 1431fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 1432b3dfd5fcSRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32); 1433b3dfd5fcSRichard Henderson break; 1434fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 1435fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 1436b3dfd5fcSRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64); 14376d0b52edSRichard Henderson break; 14386d0b52edSRichard Henderson 14396d0b52edSRichard Henderson case INDEX_op_ld32s_i64: 14406d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, LDSW); 14416d0b52edSRichard Henderson break; 14426d0b52edSRichard Henderson case INDEX_op_ld_i64: 14436d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, LDX); 14446d0b52edSRichard Henderson break; 14456d0b52edSRichard Henderson case INDEX_op_st_i64: 14466d0b52edSRichard Henderson tcg_out_ldst(s, a0, a1, a2, STX); 14476d0b52edSRichard Henderson break; 14486d0b52edSRichard Henderson case INDEX_op_shl_i64: 14496d0b52edSRichard Henderson c = SHIFT_SLLX; 14506d0b52edSRichard Henderson do_shift64: 14516d0b52edSRichard Henderson /* Limit immediate shift count lest we create an illegal insn. */ 14526d0b52edSRichard Henderson tcg_out_arithc(s, a0, a1, a2 & 63, c2, c); 14536d0b52edSRichard Henderson break; 14546d0b52edSRichard Henderson case INDEX_op_shr_i64: 14556d0b52edSRichard Henderson c = SHIFT_SRLX; 14566d0b52edSRichard Henderson goto do_shift64; 14576d0b52edSRichard Henderson case INDEX_op_sar_i64: 14586d0b52edSRichard Henderson c = SHIFT_SRAX; 14596d0b52edSRichard Henderson goto do_shift64; 14606d0b52edSRichard Henderson case INDEX_op_mul_i64: 14616d0b52edSRichard Henderson c = ARITH_MULX; 14626d0b52edSRichard Henderson goto gen_arith; 14636d0b52edSRichard Henderson case INDEX_op_div_i64: 14646d0b52edSRichard Henderson c = ARITH_SDIVX; 14656d0b52edSRichard Henderson goto gen_arith; 14666d0b52edSRichard Henderson case INDEX_op_divu_i64: 14676d0b52edSRichard Henderson c = ARITH_UDIVX; 14686d0b52edSRichard Henderson goto gen_arith; 14696d0b52edSRichard Henderson 14706d0b52edSRichard Henderson case INDEX_op_brcond_i64: 14716d0b52edSRichard Henderson tcg_out_brcond_i64(s, a2, a0, a1, const_args[1], arg_label(args[3])); 14726d0b52edSRichard Henderson break; 14736d0b52edSRichard Henderson case INDEX_op_setcond_i64: 1474a0fdd7c9SRichard Henderson tcg_out_setcond_i64(s, args[3], a0, a1, a2, c2, false); 1475a0fdd7c9SRichard Henderson break; 1476a0fdd7c9SRichard Henderson case INDEX_op_negsetcond_i64: 1477a0fdd7c9SRichard Henderson tcg_out_setcond_i64(s, args[3], a0, a1, a2, c2, true); 14786d0b52edSRichard Henderson break; 14796d0b52edSRichard Henderson case INDEX_op_movcond_i64: 14806d0b52edSRichard Henderson tcg_out_movcond_i64(s, args[5], a0, a1, a2, c2, args[3], const_args[3]); 14816d0b52edSRichard Henderson break; 14826d0b52edSRichard Henderson case INDEX_op_add2_i64: 14836d0b52edSRichard Henderson tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4], 14846d0b52edSRichard Henderson const_args[4], args[5], const_args[5], false); 14856d0b52edSRichard Henderson break; 14866d0b52edSRichard Henderson case INDEX_op_sub2_i64: 14876d0b52edSRichard Henderson tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4], 14886d0b52edSRichard Henderson const_args[4], args[5], const_args[5], true); 14896d0b52edSRichard Henderson break; 14906d0b52edSRichard Henderson case INDEX_op_muluh_i64: 14916d0b52edSRichard Henderson tcg_out_arith(s, args[0], args[1], args[2], ARITH_UMULXHI); 14926d0b52edSRichard Henderson break; 14936d0b52edSRichard Henderson 14946d0b52edSRichard Henderson gen_arith: 14956d0b52edSRichard Henderson tcg_out_arithc(s, a0, a1, a2, c2, c); 14966d0b52edSRichard Henderson break; 14976d0b52edSRichard Henderson 14986d0b52edSRichard Henderson gen_arith1: 14996d0b52edSRichard Henderson tcg_out_arithc(s, a0, TCG_REG_G0, a1, const_args[1], c); 15006d0b52edSRichard Henderson break; 15016d0b52edSRichard Henderson 15026d0b52edSRichard Henderson case INDEX_op_mb: 15036d0b52edSRichard Henderson tcg_out_mb(s, a0); 15046d0b52edSRichard Henderson break; 15056d0b52edSRichard Henderson 15066d0b52edSRichard Henderson case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ 15076d0b52edSRichard Henderson case INDEX_op_mov_i64: 15086d0b52edSRichard Henderson case INDEX_op_call: /* Always emitted via tcg_out_call. */ 1509b55a8d9dSRichard Henderson case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ 1510cf7d6b8eSRichard Henderson case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ 1511678155b2SRichard Henderson case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */ 1512678155b2SRichard Henderson case INDEX_op_ext8s_i64: 1513d0e66c89SRichard Henderson case INDEX_op_ext8u_i32: 1514d0e66c89SRichard Henderson case INDEX_op_ext8u_i64: 1515753e42eaSRichard Henderson case INDEX_op_ext16s_i32: 1516753e42eaSRichard Henderson case INDEX_op_ext16s_i64: 1517379afdffSRichard Henderson case INDEX_op_ext16u_i32: 1518379afdffSRichard Henderson case INDEX_op_ext16u_i64: 151952bf3398SRichard Henderson case INDEX_op_ext32s_i64: 15209ecf5f61SRichard Henderson case INDEX_op_ext32u_i64: 15219c6aa274SRichard Henderson case INDEX_op_ext_i32_i64: 1522b9bfe000SRichard Henderson case INDEX_op_extu_i32_i64: 15236d0b52edSRichard Henderson default: 1524732e89f4SRichard Henderson g_assert_not_reached(); 15256d0b52edSRichard Henderson } 15266d0b52edSRichard Henderson} 15276d0b52edSRichard Henderson 15286d0b52edSRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) 15296d0b52edSRichard Henderson{ 15306d0b52edSRichard Henderson switch (op) { 15316d0b52edSRichard Henderson case INDEX_op_goto_ptr: 15326d0b52edSRichard Henderson return C_O0_I1(r); 15336d0b52edSRichard Henderson 15346d0b52edSRichard Henderson case INDEX_op_ld8u_i32: 1535a59a2931SRichard Henderson case INDEX_op_ld8u_i64: 15366d0b52edSRichard Henderson case INDEX_op_ld8s_i32: 1537a59a2931SRichard Henderson case INDEX_op_ld8s_i64: 15386d0b52edSRichard Henderson case INDEX_op_ld16u_i32: 1539a59a2931SRichard Henderson case INDEX_op_ld16u_i64: 15406d0b52edSRichard Henderson case INDEX_op_ld16s_i32: 1541a59a2931SRichard Henderson case INDEX_op_ld16s_i64: 15426d0b52edSRichard Henderson case INDEX_op_ld_i32: 1543a59a2931SRichard Henderson case INDEX_op_ld32u_i64: 1544a59a2931SRichard Henderson case INDEX_op_ld32s_i64: 1545a59a2931SRichard Henderson case INDEX_op_ld_i64: 15466d0b52edSRichard Henderson case INDEX_op_neg_i32: 1547a59a2931SRichard Henderson case INDEX_op_neg_i64: 15486d0b52edSRichard Henderson case INDEX_op_not_i32: 1549a59a2931SRichard Henderson case INDEX_op_not_i64: 1550a59a2931SRichard Henderson case INDEX_op_ext32s_i64: 1551a59a2931SRichard Henderson case INDEX_op_ext32u_i64: 1552a59a2931SRichard Henderson case INDEX_op_ext_i32_i64: 1553a59a2931SRichard Henderson case INDEX_op_extu_i32_i64: 1554fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 1555fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 1556fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 1557fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 15586d0b52edSRichard Henderson return C_O1_I1(r, r); 15596d0b52edSRichard Henderson 15606d0b52edSRichard Henderson case INDEX_op_st8_i32: 1561a59a2931SRichard Henderson case INDEX_op_st8_i64: 15626d0b52edSRichard Henderson case INDEX_op_st16_i32: 1563a59a2931SRichard Henderson case INDEX_op_st16_i64: 15646d0b52edSRichard Henderson case INDEX_op_st_i32: 1565a59a2931SRichard Henderson case INDEX_op_st32_i64: 1566a59a2931SRichard Henderson case INDEX_op_st_i64: 1567fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 1568fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 1569fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 1570fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 15716d0b52edSRichard Henderson return C_O0_I2(rZ, r); 15726d0b52edSRichard Henderson 15736d0b52edSRichard Henderson case INDEX_op_add_i32: 1574a59a2931SRichard Henderson case INDEX_op_add_i64: 15756d0b52edSRichard Henderson case INDEX_op_mul_i32: 1576a59a2931SRichard Henderson case INDEX_op_mul_i64: 15776d0b52edSRichard Henderson case INDEX_op_div_i32: 1578a59a2931SRichard Henderson case INDEX_op_div_i64: 15796d0b52edSRichard Henderson case INDEX_op_divu_i32: 1580a59a2931SRichard Henderson case INDEX_op_divu_i64: 15816d0b52edSRichard Henderson case INDEX_op_sub_i32: 1582a59a2931SRichard Henderson case INDEX_op_sub_i64: 15836d0b52edSRichard Henderson case INDEX_op_and_i32: 1584a59a2931SRichard Henderson case INDEX_op_and_i64: 15856d0b52edSRichard Henderson case INDEX_op_andc_i32: 1586a59a2931SRichard Henderson case INDEX_op_andc_i64: 15876d0b52edSRichard Henderson case INDEX_op_or_i32: 1588a59a2931SRichard Henderson case INDEX_op_or_i64: 15896d0b52edSRichard Henderson case INDEX_op_orc_i32: 1590a59a2931SRichard Henderson case INDEX_op_orc_i64: 15916d0b52edSRichard Henderson case INDEX_op_xor_i32: 1592a59a2931SRichard Henderson case INDEX_op_xor_i64: 15936d0b52edSRichard Henderson case INDEX_op_shl_i32: 1594a59a2931SRichard Henderson case INDEX_op_shl_i64: 15956d0b52edSRichard Henderson case INDEX_op_shr_i32: 1596a59a2931SRichard Henderson case INDEX_op_shr_i64: 15976d0b52edSRichard Henderson case INDEX_op_sar_i32: 1598a59a2931SRichard Henderson case INDEX_op_sar_i64: 15996d0b52edSRichard Henderson case INDEX_op_setcond_i32: 1600a59a2931SRichard Henderson case INDEX_op_setcond_i64: 1601a0fdd7c9SRichard Henderson case INDEX_op_negsetcond_i32: 1602a0fdd7c9SRichard Henderson case INDEX_op_negsetcond_i64: 16036d0b52edSRichard Henderson return C_O1_I2(r, rZ, rJ); 16046d0b52edSRichard Henderson 16056d0b52edSRichard Henderson case INDEX_op_brcond_i32: 1606a59a2931SRichard Henderson case INDEX_op_brcond_i64: 16076d0b52edSRichard Henderson return C_O0_I2(rZ, rJ); 16086d0b52edSRichard Henderson case INDEX_op_movcond_i32: 1609a59a2931SRichard Henderson case INDEX_op_movcond_i64: 16106d0b52edSRichard Henderson return C_O1_I4(r, rZ, rJ, rI, 0); 16116d0b52edSRichard Henderson case INDEX_op_add2_i32: 1612a59a2931SRichard Henderson case INDEX_op_add2_i64: 16136d0b52edSRichard Henderson case INDEX_op_sub2_i32: 1614a59a2931SRichard Henderson case INDEX_op_sub2_i64: 16156d0b52edSRichard Henderson return C_O2_I4(r, r, rZ, rZ, rJ, rJ); 16166d0b52edSRichard Henderson case INDEX_op_mulu2_i32: 16176d0b52edSRichard Henderson case INDEX_op_muls2_i32: 16186d0b52edSRichard Henderson return C_O2_I2(r, r, rZ, rJ); 16196d0b52edSRichard Henderson case INDEX_op_muluh_i64: 1620a59a2931SRichard Henderson return C_O1_I2(r, r, r); 16216d0b52edSRichard Henderson 16226d0b52edSRichard Henderson default: 16236d0b52edSRichard Henderson g_assert_not_reached(); 16246d0b52edSRichard Henderson } 16256d0b52edSRichard Henderson} 16266d0b52edSRichard Henderson 16276d0b52edSRichard Hendersonstatic void tcg_target_init(TCGContext *s) 16286d0b52edSRichard Henderson{ 16296d0b52edSRichard Henderson /* 16306d0b52edSRichard Henderson * Only probe for the platform and capabilities if we haven't already 16316d0b52edSRichard Henderson * determined maximum values at compile time. 16326d0b52edSRichard Henderson */ 16336d0b52edSRichard Henderson#ifndef use_vis3_instructions 16346d0b52edSRichard Henderson { 16356d0b52edSRichard Henderson unsigned long hwcap = qemu_getauxval(AT_HWCAP); 16366d0b52edSRichard Henderson use_vis3_instructions = (hwcap & HWCAP_SPARC_VIS3) != 0; 16376d0b52edSRichard Henderson } 16386d0b52edSRichard Henderson#endif 16396d0b52edSRichard Henderson 16406d0b52edSRichard Henderson tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; 1641a59a2931SRichard Henderson tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS; 16426d0b52edSRichard Henderson 16436d0b52edSRichard Henderson tcg_target_call_clobber_regs = 0; 16446d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G1); 16456d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G2); 16466d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G3); 16476d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G4); 16486d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G5); 16496d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G6); 16506d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G7); 16516d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O0); 16526d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O1); 16536d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O2); 16546d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O3); 16556d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O4); 16566d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O5); 16576d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O6); 16586d0b52edSRichard Henderson tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_O7); 16596d0b52edSRichard Henderson 16606d0b52edSRichard Henderson s->reserved_regs = 0; 16616d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_G0); /* zero */ 16626d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_G6); /* reserved for os */ 16636d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_G7); /* thread pointer */ 16646d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_I6); /* frame pointer */ 16656d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_I7); /* return address */ 16666d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_O6); /* stack pointer */ 16676d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_T1); /* for internal use */ 16686d0b52edSRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_T2); /* for internal use */ 166933982b89SRichard Henderson tcg_regset_set_reg(s->reserved_regs, TCG_REG_T3); /* for internal use */ 16706d0b52edSRichard Henderson} 16716d0b52edSRichard Henderson 16726d0b52edSRichard Henderson#define ELF_HOST_MACHINE EM_SPARCV9 16736d0b52edSRichard Henderson 16746d0b52edSRichard Hendersontypedef struct { 16756d0b52edSRichard Henderson DebugFrameHeader h; 16766d0b52edSRichard Henderson uint8_t fde_def_cfa[4]; 16776d0b52edSRichard Henderson uint8_t fde_win_save; 16786d0b52edSRichard Henderson uint8_t fde_ret_save[3]; 16796d0b52edSRichard Henderson} DebugFrame; 16806d0b52edSRichard Henderson 16816d0b52edSRichard Hendersonstatic const DebugFrame debug_frame = { 16826d0b52edSRichard Henderson .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */ 16836d0b52edSRichard Henderson .h.cie.id = -1, 16846d0b52edSRichard Henderson .h.cie.version = 1, 16856d0b52edSRichard Henderson .h.cie.code_align = 1, 16866d0b52edSRichard Henderson .h.cie.data_align = -sizeof(void *) & 0x7f, 16876d0b52edSRichard Henderson .h.cie.return_column = 15, /* o7 */ 16886d0b52edSRichard Henderson 16896d0b52edSRichard Henderson /* Total FDE size does not include the "len" member. */ 16906d0b52edSRichard Henderson .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), 16916d0b52edSRichard Henderson 16926d0b52edSRichard Henderson .fde_def_cfa = { 16936d0b52edSRichard Henderson 12, 30, /* DW_CFA_def_cfa i6, 2047 */ 16946d0b52edSRichard Henderson (2047 & 0x7f) | 0x80, (2047 >> 7) 16956d0b52edSRichard Henderson }, 16966d0b52edSRichard Henderson .fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */ 16976d0b52edSRichard Henderson .fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */ 16986d0b52edSRichard Henderson}; 16996d0b52edSRichard Henderson 17006d0b52edSRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size) 17016d0b52edSRichard Henderson{ 17026d0b52edSRichard Henderson tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); 17036d0b52edSRichard Henderson} 1704