1139c1837SPaolo Bonzini/* 2139c1837SPaolo Bonzini * Tiny Code Generator for QEMU 3139c1837SPaolo Bonzini * 4139c1837SPaolo Bonzini * Copyright (c) 2018 SiFive, Inc 5139c1837SPaolo Bonzini * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org> 6139c1837SPaolo Bonzini * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net> 7139c1837SPaolo Bonzini * Copyright (c) 2008 Fabrice Bellard 8139c1837SPaolo Bonzini * 9139c1837SPaolo Bonzini * Based on i386/tcg-target.c and mips/tcg-target.c 10139c1837SPaolo Bonzini * 11139c1837SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 12139c1837SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 13139c1837SPaolo Bonzini * in the Software without restriction, including without limitation the rights 14139c1837SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15139c1837SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 16139c1837SPaolo Bonzini * furnished to do so, subject to the following conditions: 17139c1837SPaolo Bonzini * 18139c1837SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 19139c1837SPaolo Bonzini * all copies or substantial portions of the Software. 20139c1837SPaolo Bonzini * 21139c1837SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22139c1837SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23139c1837SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24139c1837SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25139c1837SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26139c1837SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27139c1837SPaolo Bonzini * THE SOFTWARE. 28139c1837SPaolo Bonzini */ 29139c1837SPaolo Bonzini 30a3fb7c99SRichard Henderson#include "../tcg-ldst.c.inc" 31139c1837SPaolo Bonzini#include "../tcg-pool.c.inc" 32139c1837SPaolo Bonzini 33139c1837SPaolo Bonzini#ifdef CONFIG_DEBUG_TCG 34139c1837SPaolo Bonzinistatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { 35f63e7089SHuang Shiyuan "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", 36f63e7089SHuang Shiyuan "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", 37f63e7089SHuang Shiyuan "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", 38f63e7089SHuang Shiyuan "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", 39f63e7089SHuang Shiyuan "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 40f63e7089SHuang Shiyuan "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 41f63e7089SHuang Shiyuan "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 42f63e7089SHuang Shiyuan "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 43139c1837SPaolo Bonzini}; 44139c1837SPaolo Bonzini#endif 45139c1837SPaolo Bonzini 46139c1837SPaolo Bonzinistatic const int tcg_target_reg_alloc_order[] = { 47139c1837SPaolo Bonzini /* Call saved registers */ 484daad8d9SMichael Tokarev /* TCG_REG_S0 reserved for TCG_AREG0 */ 49139c1837SPaolo Bonzini TCG_REG_S1, 50139c1837SPaolo Bonzini TCG_REG_S2, 51139c1837SPaolo Bonzini TCG_REG_S3, 52139c1837SPaolo Bonzini TCG_REG_S4, 53139c1837SPaolo Bonzini TCG_REG_S5, 54139c1837SPaolo Bonzini TCG_REG_S6, 55139c1837SPaolo Bonzini TCG_REG_S7, 56139c1837SPaolo Bonzini TCG_REG_S8, 57139c1837SPaolo Bonzini TCG_REG_S9, 58139c1837SPaolo Bonzini TCG_REG_S10, 59139c1837SPaolo Bonzini TCG_REG_S11, 60139c1837SPaolo Bonzini 61139c1837SPaolo Bonzini /* Call clobbered registers */ 62139c1837SPaolo Bonzini TCG_REG_T0, 63139c1837SPaolo Bonzini TCG_REG_T1, 64139c1837SPaolo Bonzini TCG_REG_T2, 65139c1837SPaolo Bonzini TCG_REG_T3, 66139c1837SPaolo Bonzini TCG_REG_T4, 67139c1837SPaolo Bonzini TCG_REG_T5, 68139c1837SPaolo Bonzini TCG_REG_T6, 69139c1837SPaolo Bonzini 70139c1837SPaolo Bonzini /* Argument registers */ 71139c1837SPaolo Bonzini TCG_REG_A0, 72139c1837SPaolo Bonzini TCG_REG_A1, 73139c1837SPaolo Bonzini TCG_REG_A2, 74139c1837SPaolo Bonzini TCG_REG_A3, 75139c1837SPaolo Bonzini TCG_REG_A4, 76139c1837SPaolo Bonzini TCG_REG_A5, 77139c1837SPaolo Bonzini TCG_REG_A6, 78139c1837SPaolo Bonzini TCG_REG_A7, 79f63e7089SHuang Shiyuan 80f63e7089SHuang Shiyuan /* Vector registers and TCG_REG_V0 reserved for mask. */ 81f63e7089SHuang Shiyuan TCG_REG_V1, TCG_REG_V2, TCG_REG_V3, TCG_REG_V4, 82f63e7089SHuang Shiyuan TCG_REG_V5, TCG_REG_V6, TCG_REG_V7, TCG_REG_V8, 83f63e7089SHuang Shiyuan TCG_REG_V9, TCG_REG_V10, TCG_REG_V11, TCG_REG_V12, 84f63e7089SHuang Shiyuan TCG_REG_V13, TCG_REG_V14, TCG_REG_V15, TCG_REG_V16, 85f63e7089SHuang Shiyuan TCG_REG_V17, TCG_REG_V18, TCG_REG_V19, TCG_REG_V20, 86f63e7089SHuang Shiyuan TCG_REG_V21, TCG_REG_V22, TCG_REG_V23, TCG_REG_V24, 87f63e7089SHuang Shiyuan TCG_REG_V25, TCG_REG_V26, TCG_REG_V27, TCG_REG_V28, 88f63e7089SHuang Shiyuan TCG_REG_V29, TCG_REG_V30, TCG_REG_V31, 89139c1837SPaolo Bonzini}; 90139c1837SPaolo Bonzini 91139c1837SPaolo Bonzinistatic const int tcg_target_call_iarg_regs[] = { 92139c1837SPaolo Bonzini TCG_REG_A0, 93139c1837SPaolo Bonzini TCG_REG_A1, 94139c1837SPaolo Bonzini TCG_REG_A2, 95139c1837SPaolo Bonzini TCG_REG_A3, 96139c1837SPaolo Bonzini TCG_REG_A4, 97139c1837SPaolo Bonzini TCG_REG_A5, 98139c1837SPaolo Bonzini TCG_REG_A6, 99139c1837SPaolo Bonzini TCG_REG_A7, 100139c1837SPaolo Bonzini}; 101139c1837SPaolo Bonzini 1025e3d0c19SRichard Hendersonstatic TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) 1035e3d0c19SRichard Henderson{ 1045e3d0c19SRichard Henderson tcg_debug_assert(kind == TCG_CALL_RET_NORMAL); 1055e3d0c19SRichard Henderson tcg_debug_assert(slot >= 0 && slot <= 1); 1065e3d0c19SRichard Henderson return TCG_REG_A0 + slot; 1075e3d0c19SRichard Henderson} 108139c1837SPaolo Bonzini 109139c1837SPaolo Bonzini#define TCG_CT_CONST_ZERO 0x100 110139c1837SPaolo Bonzini#define TCG_CT_CONST_S12 0x200 111139c1837SPaolo Bonzini#define TCG_CT_CONST_N12 0x400 112139c1837SPaolo Bonzini#define TCG_CT_CONST_M12 0x800 11399f4ec6eSRichard Henderson#define TCG_CT_CONST_J12 0x1000 114*5a63f599STANG Tiancheng#define TCG_CT_CONST_S5 0x2000 115139c1837SPaolo Bonzini 116fc63a4c5SRichard Henderson#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) 117f63e7089SHuang Shiyuan#define ALL_VECTOR_REGS MAKE_64BIT_MASK(32, 32) 118f63e7089SHuang Shiyuan#define ALL_DVECTOR_REG_GROUPS 0x5555555500000000 119f63e7089SHuang Shiyuan#define ALL_QVECTOR_REG_GROUPS 0x1111111100000000 120fc63a4c5SRichard Henderson 121aeb6326eSRichard Henderson#define sextreg sextract64 122139c1837SPaolo Bonzini 123139c1837SPaolo Bonzini/* test if a constant matches the constraint */ 12421e9a8aeSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct, 12521e9a8aeSRichard Henderson TCGType type, TCGCond cond, int vece) 126139c1837SPaolo Bonzini{ 127139c1837SPaolo Bonzini if (ct & TCG_CT_CONST) { 128139c1837SPaolo Bonzini return 1; 129139c1837SPaolo Bonzini } 130139c1837SPaolo Bonzini if ((ct & TCG_CT_CONST_ZERO) && val == 0) { 131139c1837SPaolo Bonzini return 1; 132139c1837SPaolo Bonzini } 133*5a63f599STANG Tiancheng if (type >= TCG_TYPE_V64) { 134*5a63f599STANG Tiancheng /* Val is replicated by VECE; extract the highest element. */ 135*5a63f599STANG Tiancheng val >>= (-8 << vece) & 63; 136*5a63f599STANG Tiancheng } 13762722763SRichard Henderson /* 13862722763SRichard Henderson * Sign extended from 12 bits: [-0x800, 0x7ff]. 13962722763SRichard Henderson * Used for most arithmetic, as this is the isa field. 14062722763SRichard Henderson */ 14162722763SRichard Henderson if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) { 142139c1837SPaolo Bonzini return 1; 143139c1837SPaolo Bonzini } 14462722763SRichard Henderson /* 14562722763SRichard Henderson * Sign extended from 12 bits, negated: [-0x7ff, 0x800]. 14662722763SRichard Henderson * Used for subtraction, where a constant must be handled by ADDI. 14762722763SRichard Henderson */ 14862722763SRichard Henderson if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) { 149139c1837SPaolo Bonzini return 1; 150139c1837SPaolo Bonzini } 15162722763SRichard Henderson /* 15262722763SRichard Henderson * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff]. 153a18d783eSRichard Henderson * Used by addsub2 and movcond, which may need the negative value, 15462722763SRichard Henderson * and requires the modified constant to be representable. 15562722763SRichard Henderson */ 15662722763SRichard Henderson if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) { 157139c1837SPaolo Bonzini return 1; 158139c1837SPaolo Bonzini } 15999f4ec6eSRichard Henderson /* 16099f4ec6eSRichard Henderson * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff]. 16199f4ec6eSRichard Henderson * Used to map ANDN back to ANDI, etc. 16299f4ec6eSRichard Henderson */ 16399f4ec6eSRichard Henderson if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) { 16499f4ec6eSRichard Henderson return 1; 16599f4ec6eSRichard Henderson } 166*5a63f599STANG Tiancheng /* 167*5a63f599STANG Tiancheng * Sign extended from 5 bits: [-0x10, 0x0f]. 168*5a63f599STANG Tiancheng * Used for vector-immediate. 169*5a63f599STANG Tiancheng */ 170*5a63f599STANG Tiancheng if ((ct & TCG_CT_CONST_S5) && val >= -0x10 && val <= 0x0f) { 171*5a63f599STANG Tiancheng return 1; 172*5a63f599STANG Tiancheng } 173139c1837SPaolo Bonzini return 0; 174139c1837SPaolo Bonzini} 175139c1837SPaolo Bonzini 176139c1837SPaolo Bonzini/* 177139c1837SPaolo Bonzini * RISC-V Base ISA opcodes (IM) 178139c1837SPaolo Bonzini */ 179139c1837SPaolo Bonzini 180f63e7089SHuang Shiyuan#define V_OPIVV (0x0 << 12) 181f63e7089SHuang Shiyuan#define V_OPFVV (0x1 << 12) 182f63e7089SHuang Shiyuan#define V_OPMVV (0x2 << 12) 183f63e7089SHuang Shiyuan#define V_OPIVI (0x3 << 12) 184f63e7089SHuang Shiyuan#define V_OPIVX (0x4 << 12) 185f63e7089SHuang Shiyuan#define V_OPFVF (0x5 << 12) 186f63e7089SHuang Shiyuan#define V_OPMVX (0x6 << 12) 187f63e7089SHuang Shiyuan#define V_OPCFG (0x7 << 12) 188f63e7089SHuang Shiyuan 189f63e7089SHuang Shiyuan/* NF <= 7 && NF >= 0 */ 190f63e7089SHuang Shiyuan#define V_NF(x) (x << 29) 191f63e7089SHuang Shiyuan#define V_UNIT_STRIDE (0x0 << 20) 192f63e7089SHuang Shiyuan#define V_UNIT_STRIDE_WHOLE_REG (0x8 << 20) 193f63e7089SHuang Shiyuan 194f63e7089SHuang Shiyuantypedef enum { 195f63e7089SHuang Shiyuan VLMUL_M1 = 0, /* LMUL=1 */ 196f63e7089SHuang Shiyuan VLMUL_M2, /* LMUL=2 */ 197f63e7089SHuang Shiyuan VLMUL_M4, /* LMUL=4 */ 198f63e7089SHuang Shiyuan VLMUL_M8, /* LMUL=8 */ 199f63e7089SHuang Shiyuan VLMUL_RESERVED, 200f63e7089SHuang Shiyuan VLMUL_MF8, /* LMUL=1/8 */ 201f63e7089SHuang Shiyuan VLMUL_MF4, /* LMUL=1/4 */ 202f63e7089SHuang Shiyuan VLMUL_MF2, /* LMUL=1/2 */ 203f63e7089SHuang Shiyuan} RISCVVlmul; 204f63e7089SHuang Shiyuan 205139c1837SPaolo Bonzinitypedef enum { 206139c1837SPaolo Bonzini OPC_ADD = 0x33, 207139c1837SPaolo Bonzini OPC_ADDI = 0x13, 208139c1837SPaolo Bonzini OPC_AND = 0x7033, 209139c1837SPaolo Bonzini OPC_ANDI = 0x7013, 210139c1837SPaolo Bonzini OPC_AUIPC = 0x17, 211139c1837SPaolo Bonzini OPC_BEQ = 0x63, 212139c1837SPaolo Bonzini OPC_BGE = 0x5063, 213139c1837SPaolo Bonzini OPC_BGEU = 0x7063, 214139c1837SPaolo Bonzini OPC_BLT = 0x4063, 215139c1837SPaolo Bonzini OPC_BLTU = 0x6063, 216139c1837SPaolo Bonzini OPC_BNE = 0x1063, 217139c1837SPaolo Bonzini OPC_DIV = 0x2004033, 218139c1837SPaolo Bonzini OPC_DIVU = 0x2005033, 219139c1837SPaolo Bonzini OPC_JAL = 0x6f, 220139c1837SPaolo Bonzini OPC_JALR = 0x67, 221139c1837SPaolo Bonzini OPC_LB = 0x3, 222139c1837SPaolo Bonzini OPC_LBU = 0x4003, 223139c1837SPaolo Bonzini OPC_LD = 0x3003, 224139c1837SPaolo Bonzini OPC_LH = 0x1003, 225139c1837SPaolo Bonzini OPC_LHU = 0x5003, 226139c1837SPaolo Bonzini OPC_LUI = 0x37, 227139c1837SPaolo Bonzini OPC_LW = 0x2003, 228139c1837SPaolo Bonzini OPC_LWU = 0x6003, 229139c1837SPaolo Bonzini OPC_MUL = 0x2000033, 230139c1837SPaolo Bonzini OPC_MULH = 0x2001033, 231139c1837SPaolo Bonzini OPC_MULHSU = 0x2002033, 232139c1837SPaolo Bonzini OPC_MULHU = 0x2003033, 233139c1837SPaolo Bonzini OPC_OR = 0x6033, 234139c1837SPaolo Bonzini OPC_ORI = 0x6013, 235139c1837SPaolo Bonzini OPC_REM = 0x2006033, 236139c1837SPaolo Bonzini OPC_REMU = 0x2007033, 237139c1837SPaolo Bonzini OPC_SB = 0x23, 238139c1837SPaolo Bonzini OPC_SD = 0x3023, 239139c1837SPaolo Bonzini OPC_SH = 0x1023, 240139c1837SPaolo Bonzini OPC_SLL = 0x1033, 241139c1837SPaolo Bonzini OPC_SLLI = 0x1013, 242139c1837SPaolo Bonzini OPC_SLT = 0x2033, 243139c1837SPaolo Bonzini OPC_SLTI = 0x2013, 244139c1837SPaolo Bonzini OPC_SLTIU = 0x3013, 245139c1837SPaolo Bonzini OPC_SLTU = 0x3033, 246139c1837SPaolo Bonzini OPC_SRA = 0x40005033, 247139c1837SPaolo Bonzini OPC_SRAI = 0x40005013, 248139c1837SPaolo Bonzini OPC_SRL = 0x5033, 249139c1837SPaolo Bonzini OPC_SRLI = 0x5013, 250139c1837SPaolo Bonzini OPC_SUB = 0x40000033, 251139c1837SPaolo Bonzini OPC_SW = 0x2023, 252139c1837SPaolo Bonzini OPC_XOR = 0x4033, 253139c1837SPaolo Bonzini OPC_XORI = 0x4013, 254139c1837SPaolo Bonzini 255139c1837SPaolo Bonzini OPC_ADDIW = 0x1b, 256139c1837SPaolo Bonzini OPC_ADDW = 0x3b, 257139c1837SPaolo Bonzini OPC_DIVUW = 0x200503b, 258139c1837SPaolo Bonzini OPC_DIVW = 0x200403b, 259139c1837SPaolo Bonzini OPC_MULW = 0x200003b, 260139c1837SPaolo Bonzini OPC_REMUW = 0x200703b, 261139c1837SPaolo Bonzini OPC_REMW = 0x200603b, 262139c1837SPaolo Bonzini OPC_SLLIW = 0x101b, 263139c1837SPaolo Bonzini OPC_SLLW = 0x103b, 264139c1837SPaolo Bonzini OPC_SRAIW = 0x4000501b, 265139c1837SPaolo Bonzini OPC_SRAW = 0x4000503b, 266139c1837SPaolo Bonzini OPC_SRLIW = 0x501b, 267139c1837SPaolo Bonzini OPC_SRLW = 0x503b, 268139c1837SPaolo Bonzini OPC_SUBW = 0x4000003b, 269139c1837SPaolo Bonzini 270139c1837SPaolo Bonzini OPC_FENCE = 0x0000000f, 2719ae958e4SRichard Henderson OPC_NOP = OPC_ADDI, /* nop = addi r0,r0,0 */ 2729e3e0bc6SRichard Henderson 2739e3e0bc6SRichard Henderson /* Zba: Bit manipulation extension, address generation */ 2749e3e0bc6SRichard Henderson OPC_ADD_UW = 0x0800003b, 2759e3e0bc6SRichard Henderson 2764daad8d9SMichael Tokarev /* Zbb: Bit manipulation extension, basic bit manipulation */ 2779e3e0bc6SRichard Henderson OPC_ANDN = 0x40007033, 2789e3e0bc6SRichard Henderson OPC_CLZ = 0x60001013, 2799e3e0bc6SRichard Henderson OPC_CLZW = 0x6000101b, 2809e3e0bc6SRichard Henderson OPC_CPOP = 0x60201013, 2819e3e0bc6SRichard Henderson OPC_CPOPW = 0x6020101b, 2829e3e0bc6SRichard Henderson OPC_CTZ = 0x60101013, 2839e3e0bc6SRichard Henderson OPC_CTZW = 0x6010101b, 2849e3e0bc6SRichard Henderson OPC_ORN = 0x40006033, 2859e3e0bc6SRichard Henderson OPC_REV8 = 0x6b805013, 2869e3e0bc6SRichard Henderson OPC_ROL = 0x60001033, 2879e3e0bc6SRichard Henderson OPC_ROLW = 0x6000103b, 2889e3e0bc6SRichard Henderson OPC_ROR = 0x60005033, 2899e3e0bc6SRichard Henderson OPC_RORW = 0x6000503b, 2909e3e0bc6SRichard Henderson OPC_RORI = 0x60005013, 2919e3e0bc6SRichard Henderson OPC_RORIW = 0x6000501b, 2929e3e0bc6SRichard Henderson OPC_SEXT_B = 0x60401013, 2939e3e0bc6SRichard Henderson OPC_SEXT_H = 0x60501013, 2949e3e0bc6SRichard Henderson OPC_XNOR = 0x40004033, 2959e3e0bc6SRichard Henderson OPC_ZEXT_H = 0x0800403b, 2969e3e0bc6SRichard Henderson 2979e3e0bc6SRichard Henderson /* Zicond: integer conditional operations */ 2989e3e0bc6SRichard Henderson OPC_CZERO_EQZ = 0x0e005033, 2999e3e0bc6SRichard Henderson OPC_CZERO_NEZ = 0x0e007033, 300f63e7089SHuang Shiyuan 301f63e7089SHuang Shiyuan /* V: Vector extension 1.0 */ 302f63e7089SHuang Shiyuan OPC_VSETVLI = 0x57 | V_OPCFG, 303f63e7089SHuang Shiyuan OPC_VSETIVLI = 0xc0000057 | V_OPCFG, 304f63e7089SHuang Shiyuan OPC_VSETVL = 0x80000057 | V_OPCFG, 305f63e7089SHuang Shiyuan 306f63e7089SHuang Shiyuan OPC_VLE8_V = 0x7 | V_UNIT_STRIDE, 307f63e7089SHuang Shiyuan OPC_VLE16_V = 0x5007 | V_UNIT_STRIDE, 308f63e7089SHuang Shiyuan OPC_VLE32_V = 0x6007 | V_UNIT_STRIDE, 309f63e7089SHuang Shiyuan OPC_VLE64_V = 0x7007 | V_UNIT_STRIDE, 310f63e7089SHuang Shiyuan OPC_VSE8_V = 0x27 | V_UNIT_STRIDE, 311f63e7089SHuang Shiyuan OPC_VSE16_V = 0x5027 | V_UNIT_STRIDE, 312f63e7089SHuang Shiyuan OPC_VSE32_V = 0x6027 | V_UNIT_STRIDE, 313f63e7089SHuang Shiyuan OPC_VSE64_V = 0x7027 | V_UNIT_STRIDE, 314f63e7089SHuang Shiyuan 315f63e7089SHuang Shiyuan OPC_VL1RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0), 316f63e7089SHuang Shiyuan OPC_VL2RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1), 317f63e7089SHuang Shiyuan OPC_VL4RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3), 318f63e7089SHuang Shiyuan OPC_VL8RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7), 319f63e7089SHuang Shiyuan 320f63e7089SHuang Shiyuan OPC_VS1R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0), 321f63e7089SHuang Shiyuan OPC_VS2R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1), 322f63e7089SHuang Shiyuan OPC_VS4R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3), 323f63e7089SHuang Shiyuan OPC_VS8R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7), 324d4be6ee1STANG Tiancheng 325*5a63f599STANG Tiancheng OPC_VADD_VV = 0x57 | V_OPIVV, 326*5a63f599STANG Tiancheng OPC_VADD_VI = 0x57 | V_OPIVI, 327*5a63f599STANG Tiancheng OPC_VSUB_VV = 0x8000057 | V_OPIVV, 328*5a63f599STANG Tiancheng OPC_VAND_VV = 0x24000057 | V_OPIVV, 329*5a63f599STANG Tiancheng OPC_VAND_VI = 0x24000057 | V_OPIVI, 330*5a63f599STANG Tiancheng OPC_VOR_VV = 0x28000057 | V_OPIVV, 331*5a63f599STANG Tiancheng OPC_VOR_VI = 0x28000057 | V_OPIVI, 332*5a63f599STANG Tiancheng OPC_VXOR_VV = 0x2c000057 | V_OPIVV, 333*5a63f599STANG Tiancheng OPC_VXOR_VI = 0x2c000057 | V_OPIVI, 334*5a63f599STANG Tiancheng 335d4be6ee1STANG Tiancheng OPC_VMV_V_V = 0x5e000057 | V_OPIVV, 336d4be6ee1STANG Tiancheng OPC_VMV_V_I = 0x5e000057 | V_OPIVI, 337d4be6ee1STANG Tiancheng OPC_VMV_V_X = 0x5e000057 | V_OPIVX, 338d4be6ee1STANG Tiancheng 339d4be6ee1STANG Tiancheng OPC_VMVNR_V = 0x9e000057 | V_OPIVI, 340139c1837SPaolo Bonzini} RISCVInsn; 341139c1837SPaolo Bonzini 342139c1837SPaolo Bonzini/* 343139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC) 344139c1837SPaolo Bonzini */ 345139c1837SPaolo Bonzini 346139c1837SPaolo Bonzini/* Type-R */ 347139c1837SPaolo Bonzini 348139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2) 349139c1837SPaolo Bonzini{ 350139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20; 351139c1837SPaolo Bonzini} 352139c1837SPaolo Bonzini 353139c1837SPaolo Bonzini/* Type-I */ 354139c1837SPaolo Bonzini 355139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm) 356139c1837SPaolo Bonzini{ 357139c1837SPaolo Bonzini return (imm & 0xfff) << 20; 358139c1837SPaolo Bonzini} 359139c1837SPaolo Bonzini 360139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm) 361139c1837SPaolo Bonzini{ 362139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm); 363139c1837SPaolo Bonzini} 364139c1837SPaolo Bonzini 365139c1837SPaolo Bonzini/* Type-S */ 366139c1837SPaolo Bonzini 367139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm) 368139c1837SPaolo Bonzini{ 369139c1837SPaolo Bonzini int32_t ret = 0; 370139c1837SPaolo Bonzini 371139c1837SPaolo Bonzini ret |= (imm & 0xFE0) << 20; 372139c1837SPaolo Bonzini ret |= (imm & 0x1F) << 7; 373139c1837SPaolo Bonzini 374139c1837SPaolo Bonzini return ret; 375139c1837SPaolo Bonzini} 376139c1837SPaolo Bonzini 377139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) 378139c1837SPaolo Bonzini{ 379139c1837SPaolo Bonzini return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm); 380139c1837SPaolo Bonzini} 381139c1837SPaolo Bonzini 382139c1837SPaolo Bonzini/* Type-SB */ 383139c1837SPaolo Bonzini 384139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm) 385139c1837SPaolo Bonzini{ 386139c1837SPaolo Bonzini int32_t ret = 0; 387139c1837SPaolo Bonzini 388139c1837SPaolo Bonzini ret |= (imm & 0x1000) << 19; 389139c1837SPaolo Bonzini ret |= (imm & 0x7e0) << 20; 390139c1837SPaolo Bonzini ret |= (imm & 0x1e) << 7; 391139c1837SPaolo Bonzini ret |= (imm & 0x800) >> 4; 392139c1837SPaolo Bonzini 393139c1837SPaolo Bonzini return ret; 394139c1837SPaolo Bonzini} 395139c1837SPaolo Bonzini 396139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) 397139c1837SPaolo Bonzini{ 398139c1837SPaolo Bonzini return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm); 399139c1837SPaolo Bonzini} 400139c1837SPaolo Bonzini 401139c1837SPaolo Bonzini/* Type-U */ 402139c1837SPaolo Bonzini 403139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm) 404139c1837SPaolo Bonzini{ 405139c1837SPaolo Bonzini return imm & 0xfffff000; 406139c1837SPaolo Bonzini} 407139c1837SPaolo Bonzini 408139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm) 409139c1837SPaolo Bonzini{ 410139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | encode_uimm20(imm); 411139c1837SPaolo Bonzini} 412139c1837SPaolo Bonzini 413139c1837SPaolo Bonzini/* Type-UJ */ 414139c1837SPaolo Bonzini 415139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm) 416139c1837SPaolo Bonzini{ 417139c1837SPaolo Bonzini int32_t ret = 0; 418139c1837SPaolo Bonzini 419139c1837SPaolo Bonzini ret |= (imm & 0x0007fe) << (21 - 1); 420139c1837SPaolo Bonzini ret |= (imm & 0x000800) << (20 - 11); 421139c1837SPaolo Bonzini ret |= (imm & 0x0ff000) << (12 - 12); 422139c1837SPaolo Bonzini ret |= (imm & 0x100000) << (31 - 20); 423139c1837SPaolo Bonzini 424139c1837SPaolo Bonzini return ret; 425139c1837SPaolo Bonzini} 426139c1837SPaolo Bonzini 427139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm) 428139c1837SPaolo Bonzini{ 429139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm); 430139c1837SPaolo Bonzini} 431139c1837SPaolo Bonzini 432d4be6ee1STANG Tiancheng 433d4be6ee1STANG Tiancheng/* Type-OPIVI */ 434d4be6ee1STANG Tiancheng 435d4be6ee1STANG Tianchengstatic int32_t encode_vi(RISCVInsn opc, TCGReg rd, int32_t imm, 436d4be6ee1STANG Tiancheng TCGReg vs2, bool vm) 437d4be6ee1STANG Tiancheng{ 438d4be6ee1STANG Tiancheng return opc | (rd & 0x1f) << 7 | (imm & 0x1f) << 15 | 439d4be6ee1STANG Tiancheng (vs2 & 0x1f) << 20 | (vm << 25); 440d4be6ee1STANG Tiancheng} 441d4be6ee1STANG Tiancheng 442f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */ 443f63e7089SHuang Shiyuan 444f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1, 445f63e7089SHuang Shiyuan TCGReg s2, bool vm) 446f63e7089SHuang Shiyuan{ 447f63e7089SHuang Shiyuan return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 | 448f63e7089SHuang Shiyuan (s2 & 0x1f) << 20 | (vm << 25); 449f63e7089SHuang Shiyuan} 450f63e7089SHuang Shiyuan 451f63e7089SHuang Shiyuan/* Vector vtype */ 452f63e7089SHuang Shiyuan 453f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma, 454f63e7089SHuang Shiyuan MemOp vsew, RISCVVlmul vlmul) 455f63e7089SHuang Shiyuan{ 456f63e7089SHuang Shiyuan return vma << 7 | vta << 6 | vsew << 3 | vlmul; 457f63e7089SHuang Shiyuan} 458f63e7089SHuang Shiyuan 459f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd, 460f63e7089SHuang Shiyuan TCGArg rs1, uint32_t vtype) 461f63e7089SHuang Shiyuan{ 462f63e7089SHuang Shiyuan return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20; 463f63e7089SHuang Shiyuan} 464f63e7089SHuang Shiyuan 465f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd, 466f63e7089SHuang Shiyuan uint32_t uimm, uint32_t vtype) 467f63e7089SHuang Shiyuan{ 468f63e7089SHuang Shiyuan return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20; 469f63e7089SHuang Shiyuan} 470f63e7089SHuang Shiyuan 471139c1837SPaolo Bonzini/* 472139c1837SPaolo Bonzini * RISC-V instruction emitters 473139c1837SPaolo Bonzini */ 474139c1837SPaolo Bonzini 475139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc, 476139c1837SPaolo Bonzini TCGReg rd, TCGReg rs1, TCGReg rs2) 477139c1837SPaolo Bonzini{ 478139c1837SPaolo Bonzini tcg_out32(s, encode_r(opc, rd, rs1, rs2)); 479139c1837SPaolo Bonzini} 480139c1837SPaolo Bonzini 481139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc, 482139c1837SPaolo Bonzini TCGReg rd, TCGReg rs1, TCGArg imm) 483139c1837SPaolo Bonzini{ 484139c1837SPaolo Bonzini tcg_out32(s, encode_i(opc, rd, rs1, imm)); 485139c1837SPaolo Bonzini} 486139c1837SPaolo Bonzini 487139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc, 488139c1837SPaolo Bonzini TCGReg rs1, TCGReg rs2, uint32_t imm) 489139c1837SPaolo Bonzini{ 490139c1837SPaolo Bonzini tcg_out32(s, encode_s(opc, rs1, rs2, imm)); 491139c1837SPaolo Bonzini} 492139c1837SPaolo Bonzini 493139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc, 494139c1837SPaolo Bonzini TCGReg rs1, TCGReg rs2, uint32_t imm) 495139c1837SPaolo Bonzini{ 496139c1837SPaolo Bonzini tcg_out32(s, encode_sb(opc, rs1, rs2, imm)); 497139c1837SPaolo Bonzini} 498139c1837SPaolo Bonzini 499139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc, 500139c1837SPaolo Bonzini TCGReg rd, uint32_t imm) 501139c1837SPaolo Bonzini{ 502139c1837SPaolo Bonzini tcg_out32(s, encode_u(opc, rd, imm)); 503139c1837SPaolo Bonzini} 504139c1837SPaolo Bonzini 505139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc, 506139c1837SPaolo Bonzini TCGReg rd, uint32_t imm) 507139c1837SPaolo Bonzini{ 508139c1837SPaolo Bonzini tcg_out32(s, encode_uj(opc, rd, imm)); 509139c1837SPaolo Bonzini} 510139c1837SPaolo Bonzini 511139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count) 512139c1837SPaolo Bonzini{ 513139c1837SPaolo Bonzini int i; 514139c1837SPaolo Bonzini for (i = 0; i < count; ++i) { 5159ae958e4SRichard Henderson p[i] = OPC_NOP; 516139c1837SPaolo Bonzini } 517139c1837SPaolo Bonzini} 518139c1837SPaolo Bonzini 519139c1837SPaolo Bonzini/* 520139c1837SPaolo Bonzini * Relocations 521139c1837SPaolo Bonzini */ 522139c1837SPaolo Bonzini 523793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 524139c1837SPaolo Bonzini{ 525793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 526793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 527139c1837SPaolo Bonzini 528844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 529844d0442SRichard Henderson if (offset == sextreg(offset, 0, 12)) { 530793f7381SRichard Henderson *src_rw |= encode_sbimm12(offset); 531139c1837SPaolo Bonzini return true; 532139c1837SPaolo Bonzini } 533139c1837SPaolo Bonzini 534139c1837SPaolo Bonzini return false; 535139c1837SPaolo Bonzini} 536139c1837SPaolo Bonzini 537793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 538139c1837SPaolo Bonzini{ 539793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 540793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 541139c1837SPaolo Bonzini 542844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 543844d0442SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 544793f7381SRichard Henderson *src_rw |= encode_ujimm20(offset); 545139c1837SPaolo Bonzini return true; 546139c1837SPaolo Bonzini } 547139c1837SPaolo Bonzini 548139c1837SPaolo Bonzini return false; 549139c1837SPaolo Bonzini} 550139c1837SPaolo Bonzini 551793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 552139c1837SPaolo Bonzini{ 553793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 554793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 555139c1837SPaolo Bonzini int32_t lo = sextreg(offset, 0, 12); 556139c1837SPaolo Bonzini int32_t hi = offset - lo; 557139c1837SPaolo Bonzini 558139c1837SPaolo Bonzini if (offset == hi + lo) { 559793f7381SRichard Henderson src_rw[0] |= encode_uimm20(hi); 560793f7381SRichard Henderson src_rw[1] |= encode_imm12(lo); 561139c1837SPaolo Bonzini return true; 562139c1837SPaolo Bonzini } 563139c1837SPaolo Bonzini 564139c1837SPaolo Bonzini return false; 565139c1837SPaolo Bonzini} 566139c1837SPaolo Bonzini 567139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type, 568139c1837SPaolo Bonzini intptr_t value, intptr_t addend) 569139c1837SPaolo Bonzini{ 570139c1837SPaolo Bonzini tcg_debug_assert(addend == 0); 571139c1837SPaolo Bonzini switch (type) { 572139c1837SPaolo Bonzini case R_RISCV_BRANCH: 573139c1837SPaolo Bonzini return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value); 574139c1837SPaolo Bonzini case R_RISCV_JAL: 575139c1837SPaolo Bonzini return reloc_jimm20(code_ptr, (tcg_insn_unit *)value); 576139c1837SPaolo Bonzini case R_RISCV_CALL: 577139c1837SPaolo Bonzini return reloc_call(code_ptr, (tcg_insn_unit *)value); 578139c1837SPaolo Bonzini default: 5794b6a52d0SRichard Henderson g_assert_not_reached(); 580139c1837SPaolo Bonzini } 581139c1837SPaolo Bonzini} 582139c1837SPaolo Bonzini 583139c1837SPaolo Bonzini/* 584f63e7089SHuang Shiyuan * RISC-V vector instruction emitters 585f63e7089SHuang Shiyuan */ 586f63e7089SHuang Shiyuan 587d4be6ee1STANG Tiancheng/* 588d4be6ee1STANG Tiancheng * Vector registers uses the same 5 lower bits as GPR registers, 589d4be6ee1STANG Tiancheng * and vm=0 (vm = false) means vector masking ENABLED. 590d4be6ee1STANG Tiancheng * With RVV 1.0, vs2 is the first operand, while rs1/imm is the 591d4be6ee1STANG Tiancheng * second operand. 592d4be6ee1STANG Tiancheng */ 593*5a63f599STANG Tianchengstatic void tcg_out_opc_vv(TCGContext *s, RISCVInsn opc, 594*5a63f599STANG Tiancheng TCGReg vd, TCGReg vs2, TCGReg vs1) 595*5a63f599STANG Tiancheng{ 596*5a63f599STANG Tiancheng tcg_out32(s, encode_v(opc, vd, vs1, vs2, true)); 597*5a63f599STANG Tiancheng} 598*5a63f599STANG Tiancheng 599d4be6ee1STANG Tianchengstatic void tcg_out_opc_vx(TCGContext *s, RISCVInsn opc, 600d4be6ee1STANG Tiancheng TCGReg vd, TCGReg vs2, TCGReg rs1) 601d4be6ee1STANG Tiancheng{ 602d4be6ee1STANG Tiancheng tcg_out32(s, encode_v(opc, vd, rs1, vs2, true)); 603d4be6ee1STANG Tiancheng} 604d4be6ee1STANG Tiancheng 605d4be6ee1STANG Tianchengstatic void tcg_out_opc_vi(TCGContext *s, RISCVInsn opc, 606d4be6ee1STANG Tiancheng TCGReg vd, TCGReg vs2, int32_t imm) 607d4be6ee1STANG Tiancheng{ 608d4be6ee1STANG Tiancheng tcg_out32(s, encode_vi(opc, vd, imm, vs2, true)); 609d4be6ee1STANG Tiancheng} 610d4be6ee1STANG Tiancheng 611*5a63f599STANG Tianchengstatic void tcg_out_opc_vv_vi(TCGContext *s, RISCVInsn o_vv, RISCVInsn o_vi, 612*5a63f599STANG Tiancheng TCGReg vd, TCGReg vs2, TCGArg vi1, int c_vi1) 613*5a63f599STANG Tiancheng{ 614*5a63f599STANG Tiancheng if (c_vi1) { 615*5a63f599STANG Tiancheng tcg_out_opc_vi(s, o_vi, vd, vs2, vi1); 616*5a63f599STANG Tiancheng } else { 617*5a63f599STANG Tiancheng tcg_out_opc_vv(s, o_vv, vd, vs2, vi1); 618*5a63f599STANG Tiancheng } 619*5a63f599STANG Tiancheng} 620*5a63f599STANG Tiancheng 621f63e7089SHuang Shiyuantypedef struct VsetCache { 622f63e7089SHuang Shiyuan uint32_t movi_insn; 623f63e7089SHuang Shiyuan uint32_t vset_insn; 624f63e7089SHuang Shiyuan} VsetCache; 625f63e7089SHuang Shiyuan 626f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4]; 627f63e7089SHuang Shiyuan 628f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew) 629f63e7089SHuang Shiyuan{ 630f63e7089SHuang Shiyuan const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew]; 631f63e7089SHuang Shiyuan 632f63e7089SHuang Shiyuan s->riscv_cur_type = type; 633f63e7089SHuang Shiyuan s->riscv_cur_vsew = vsew; 634f63e7089SHuang Shiyuan 635f63e7089SHuang Shiyuan if (p->movi_insn) { 636f63e7089SHuang Shiyuan tcg_out32(s, p->movi_insn); 637f63e7089SHuang Shiyuan } 638f63e7089SHuang Shiyuan tcg_out32(s, p->vset_insn); 639f63e7089SHuang Shiyuan} 640f63e7089SHuang Shiyuan 641f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type) 642f63e7089SHuang Shiyuan{ 643f63e7089SHuang Shiyuan if (type != s->riscv_cur_type) { 644f63e7089SHuang Shiyuan set_vtype(s, type, MO_64); 645f63e7089SHuang Shiyuan } 646f63e7089SHuang Shiyuan return s->riscv_cur_vsew; 647f63e7089SHuang Shiyuan} 648f63e7089SHuang Shiyuan 649d4be6ee1STANG Tianchengstatic void set_vtype_len_sew(TCGContext *s, TCGType type, MemOp vsew) 650d4be6ee1STANG Tiancheng{ 651d4be6ee1STANG Tiancheng if (type != s->riscv_cur_type || vsew != s->riscv_cur_vsew) { 652d4be6ee1STANG Tiancheng set_vtype(s, type, vsew); 653d4be6ee1STANG Tiancheng } 654d4be6ee1STANG Tiancheng} 655d4be6ee1STANG Tiancheng 656f63e7089SHuang Shiyuan/* 657139c1837SPaolo Bonzini * TCG intrinsics 658139c1837SPaolo Bonzini */ 659139c1837SPaolo Bonzini 660139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 661139c1837SPaolo Bonzini{ 662139c1837SPaolo Bonzini if (ret == arg) { 663139c1837SPaolo Bonzini return true; 664139c1837SPaolo Bonzini } 665139c1837SPaolo Bonzini switch (type) { 666139c1837SPaolo Bonzini case TCG_TYPE_I32: 667139c1837SPaolo Bonzini case TCG_TYPE_I64: 668139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0); 669139c1837SPaolo Bonzini break; 670d4be6ee1STANG Tiancheng case TCG_TYPE_V64: 671d4be6ee1STANG Tiancheng case TCG_TYPE_V128: 672d4be6ee1STANG Tiancheng case TCG_TYPE_V256: 673d4be6ee1STANG Tiancheng { 674d4be6ee1STANG Tiancheng int lmul = type - riscv_lg2_vlenb; 675d4be6ee1STANG Tiancheng int nf = 1 << MAX(lmul, 0); 676d4be6ee1STANG Tiancheng tcg_out_opc_vi(s, OPC_VMVNR_V, ret, arg, nf - 1); 677d4be6ee1STANG Tiancheng } 678d4be6ee1STANG Tiancheng break; 679139c1837SPaolo Bonzini default: 680139c1837SPaolo Bonzini g_assert_not_reached(); 681139c1837SPaolo Bonzini } 682139c1837SPaolo Bonzini return true; 683139c1837SPaolo Bonzini} 684139c1837SPaolo Bonzini 685139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, 686139c1837SPaolo Bonzini tcg_target_long val) 687139c1837SPaolo Bonzini{ 688139c1837SPaolo Bonzini tcg_target_long lo, hi, tmp; 689139c1837SPaolo Bonzini int shift, ret; 690139c1837SPaolo Bonzini 691aeb6326eSRichard Henderson if (type == TCG_TYPE_I32) { 692139c1837SPaolo Bonzini val = (int32_t)val; 693139c1837SPaolo Bonzini } 694139c1837SPaolo Bonzini 695139c1837SPaolo Bonzini lo = sextreg(val, 0, 12); 696139c1837SPaolo Bonzini if (val == lo) { 697139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo); 698139c1837SPaolo Bonzini return; 699139c1837SPaolo Bonzini } 700139c1837SPaolo Bonzini 701139c1837SPaolo Bonzini hi = val - lo; 702aeb6326eSRichard Henderson if (val == (int32_t)val) { 703139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, hi); 704139c1837SPaolo Bonzini if (lo != 0) { 705139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo); 706139c1837SPaolo Bonzini } 707139c1837SPaolo Bonzini return; 708139c1837SPaolo Bonzini } 709139c1837SPaolo Bonzini 710139c1837SPaolo Bonzini tmp = tcg_pcrel_diff(s, (void *)val); 711139c1837SPaolo Bonzini if (tmp == (int32_t)tmp) { 712139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); 713139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0); 714793f7381SRichard Henderson ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val); 715139c1837SPaolo Bonzini tcg_debug_assert(ret == true); 716139c1837SPaolo Bonzini return; 717139c1837SPaolo Bonzini } 718139c1837SPaolo Bonzini 719139c1837SPaolo Bonzini /* Look for a single 20-bit section. */ 720139c1837SPaolo Bonzini shift = ctz64(val); 721139c1837SPaolo Bonzini tmp = val >> shift; 722139c1837SPaolo Bonzini if (tmp == sextreg(tmp, 0, 20)) { 723139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12); 724139c1837SPaolo Bonzini if (shift > 12) { 725139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12); 726139c1837SPaolo Bonzini } else { 727139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift); 728139c1837SPaolo Bonzini } 729139c1837SPaolo Bonzini return; 730139c1837SPaolo Bonzini } 731139c1837SPaolo Bonzini 732139c1837SPaolo Bonzini /* Look for a few high zero bits, with lots of bits set in the middle. */ 733139c1837SPaolo Bonzini shift = clz64(val); 734139c1837SPaolo Bonzini tmp = val << shift; 735139c1837SPaolo Bonzini if (tmp == sextreg(tmp, 12, 20) << 12) { 736139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, tmp); 737139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift); 738139c1837SPaolo Bonzini return; 739139c1837SPaolo Bonzini } else if (tmp == sextreg(tmp, 0, 12)) { 740139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp); 741139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift); 742139c1837SPaolo Bonzini return; 743139c1837SPaolo Bonzini } 744139c1837SPaolo Bonzini 745139c1837SPaolo Bonzini /* Drop into the constant pool. */ 746139c1837SPaolo Bonzini new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0); 747139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); 748139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_LD, rd, rd, 0); 749139c1837SPaolo Bonzini} 750139c1837SPaolo Bonzini 751767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2) 752767c2503SRichard Henderson{ 753767c2503SRichard Henderson return false; 754767c2503SRichard Henderson} 755767c2503SRichard Henderson 7566a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs, 7576a6d772eSRichard Henderson tcg_target_long imm) 7586a6d772eSRichard Henderson{ 7596a6d772eSRichard Henderson /* This function is only used for passing structs by reference. */ 7606a6d772eSRichard Henderson g_assert_not_reached(); 7616a6d772eSRichard Henderson} 7626a6d772eSRichard Henderson 763139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) 764139c1837SPaolo Bonzini{ 765139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff); 766139c1837SPaolo Bonzini} 767139c1837SPaolo Bonzini 768139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) 769139c1837SPaolo Bonzini{ 770b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 771d1c3f4e9SRichard Henderson tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO); 772d1c3f4e9SRichard Henderson } else { 773139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); 774139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16); 775139c1837SPaolo Bonzini } 776d1c3f4e9SRichard Henderson} 777139c1837SPaolo Bonzini 778139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) 779139c1837SPaolo Bonzini{ 780b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBA) { 781d1c3f4e9SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO); 782d1c3f4e9SRichard Henderson } else { 783139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32); 784139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32); 785139c1837SPaolo Bonzini } 786d1c3f4e9SRichard Henderson} 787139c1837SPaolo Bonzini 788678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 789139c1837SPaolo Bonzini{ 790b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 791d1c3f4e9SRichard Henderson tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0); 792d1c3f4e9SRichard Henderson } else { 793139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24); 794139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24); 795139c1837SPaolo Bonzini } 796d1c3f4e9SRichard Henderson} 797139c1837SPaolo Bonzini 798753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 799139c1837SPaolo Bonzini{ 800b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 801d1c3f4e9SRichard Henderson tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0); 802d1c3f4e9SRichard Henderson } else { 803139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); 804139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16); 805139c1837SPaolo Bonzini } 806d1c3f4e9SRichard Henderson} 807139c1837SPaolo Bonzini 808139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) 809139c1837SPaolo Bonzini{ 810139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0); 811139c1837SPaolo Bonzini} 812139c1837SPaolo Bonzini 8139c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg) 8149c6aa274SRichard Henderson{ 8153ea9be33SRichard Henderson if (ret != arg) { 8169c6aa274SRichard Henderson tcg_out_ext32s(s, ret, arg); 8179c6aa274SRichard Henderson } 8183ea9be33SRichard Henderson} 8199c6aa274SRichard Henderson 820b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg) 821b9bfe000SRichard Henderson{ 822b9bfe000SRichard Henderson tcg_out_ext32u(s, ret, arg); 823b9bfe000SRichard Henderson} 824b9bfe000SRichard Henderson 825b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg) 826b8b94ac6SRichard Henderson{ 827b8b94ac6SRichard Henderson tcg_out_ext32s(s, ret, arg); 828b8b94ac6SRichard Henderson} 829b8b94ac6SRichard Henderson 830139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, 831139c1837SPaolo Bonzini TCGReg addr, intptr_t offset) 832139c1837SPaolo Bonzini{ 833139c1837SPaolo Bonzini intptr_t imm12 = sextreg(offset, 0, 12); 834139c1837SPaolo Bonzini 835139c1837SPaolo Bonzini if (offset != imm12) { 8369d9db413SRichard Henderson intptr_t diff = tcg_pcrel_diff(s, (void *)offset); 837139c1837SPaolo Bonzini 838139c1837SPaolo Bonzini if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { 839139c1837SPaolo Bonzini imm12 = sextreg(diff, 0, 12); 840139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12); 841139c1837SPaolo Bonzini } else { 842139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); 843139c1837SPaolo Bonzini if (addr != TCG_REG_ZERO) { 844139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr); 845139c1837SPaolo Bonzini } 846139c1837SPaolo Bonzini } 847139c1837SPaolo Bonzini addr = TCG_REG_TMP2; 848139c1837SPaolo Bonzini } 849139c1837SPaolo Bonzini 850139c1837SPaolo Bonzini switch (opc) { 851139c1837SPaolo Bonzini case OPC_SB: 852139c1837SPaolo Bonzini case OPC_SH: 853139c1837SPaolo Bonzini case OPC_SW: 854139c1837SPaolo Bonzini case OPC_SD: 855139c1837SPaolo Bonzini tcg_out_opc_store(s, opc, addr, data, imm12); 856139c1837SPaolo Bonzini break; 857139c1837SPaolo Bonzini case OPC_LB: 858139c1837SPaolo Bonzini case OPC_LBU: 859139c1837SPaolo Bonzini case OPC_LH: 860139c1837SPaolo Bonzini case OPC_LHU: 861139c1837SPaolo Bonzini case OPC_LW: 862139c1837SPaolo Bonzini case OPC_LWU: 863139c1837SPaolo Bonzini case OPC_LD: 864139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc, data, addr, imm12); 865139c1837SPaolo Bonzini break; 866139c1837SPaolo Bonzini default: 867139c1837SPaolo Bonzini g_assert_not_reached(); 868139c1837SPaolo Bonzini } 869139c1837SPaolo Bonzini} 870139c1837SPaolo Bonzini 871f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, 872f63e7089SHuang Shiyuan TCGReg addr, intptr_t offset) 873f63e7089SHuang Shiyuan{ 874f63e7089SHuang Shiyuan tcg_debug_assert(data >= TCG_REG_V0); 875f63e7089SHuang Shiyuan tcg_debug_assert(addr < TCG_REG_V0); 876f63e7089SHuang Shiyuan 877f63e7089SHuang Shiyuan if (offset) { 878f63e7089SHuang Shiyuan tcg_debug_assert(addr != TCG_REG_ZERO); 879f63e7089SHuang Shiyuan if (offset == sextreg(offset, 0, 12)) { 880f63e7089SHuang Shiyuan tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset); 881f63e7089SHuang Shiyuan } else { 882f63e7089SHuang Shiyuan tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset); 883f63e7089SHuang Shiyuan tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr); 884f63e7089SHuang Shiyuan } 885f63e7089SHuang Shiyuan addr = TCG_REG_TMP0; 886f63e7089SHuang Shiyuan } 887f63e7089SHuang Shiyuan tcg_out32(s, encode_v(opc, data, addr, 0, true)); 888f63e7089SHuang Shiyuan} 889f63e7089SHuang Shiyuan 890139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, 891139c1837SPaolo Bonzini TCGReg arg1, intptr_t arg2) 892139c1837SPaolo Bonzini{ 893f63e7089SHuang Shiyuan RISCVInsn insn; 894f63e7089SHuang Shiyuan 895f63e7089SHuang Shiyuan switch (type) { 896f63e7089SHuang Shiyuan case TCG_TYPE_I32: 897f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_LW, arg, arg1, arg2); 898f63e7089SHuang Shiyuan break; 899f63e7089SHuang Shiyuan case TCG_TYPE_I64: 900f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_LD, arg, arg1, arg2); 901f63e7089SHuang Shiyuan break; 902f63e7089SHuang Shiyuan case TCG_TYPE_V64: 903f63e7089SHuang Shiyuan case TCG_TYPE_V128: 904f63e7089SHuang Shiyuan case TCG_TYPE_V256: 905f63e7089SHuang Shiyuan if (type >= riscv_lg2_vlenb) { 906f63e7089SHuang Shiyuan static const RISCVInsn whole_reg_ld[] = { 907f63e7089SHuang Shiyuan OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V 908f63e7089SHuang Shiyuan }; 909f63e7089SHuang Shiyuan unsigned idx = type - riscv_lg2_vlenb; 910f63e7089SHuang Shiyuan 911f63e7089SHuang Shiyuan tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld)); 912f63e7089SHuang Shiyuan insn = whole_reg_ld[idx]; 913f63e7089SHuang Shiyuan } else { 914f63e7089SHuang Shiyuan static const RISCVInsn unit_stride_ld[] = { 915f63e7089SHuang Shiyuan OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V 916f63e7089SHuang Shiyuan }; 917f63e7089SHuang Shiyuan MemOp prev_vsew = set_vtype_len(s, type); 918f63e7089SHuang Shiyuan 919f63e7089SHuang Shiyuan tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld)); 920f63e7089SHuang Shiyuan insn = unit_stride_ld[prev_vsew]; 921f63e7089SHuang Shiyuan } 922f63e7089SHuang Shiyuan tcg_out_vec_ldst(s, insn, arg, arg1, arg2); 923f63e7089SHuang Shiyuan break; 924f63e7089SHuang Shiyuan default: 925f63e7089SHuang Shiyuan g_assert_not_reached(); 926f63e7089SHuang Shiyuan } 927139c1837SPaolo Bonzini} 928139c1837SPaolo Bonzini 929139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, 930139c1837SPaolo Bonzini TCGReg arg1, intptr_t arg2) 931139c1837SPaolo Bonzini{ 932f63e7089SHuang Shiyuan RISCVInsn insn; 933f63e7089SHuang Shiyuan 934f63e7089SHuang Shiyuan switch (type) { 935f63e7089SHuang Shiyuan case TCG_TYPE_I32: 936f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_SW, arg, arg1, arg2); 937f63e7089SHuang Shiyuan break; 938f63e7089SHuang Shiyuan case TCG_TYPE_I64: 939f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_SD, arg, arg1, arg2); 940f63e7089SHuang Shiyuan break; 941f63e7089SHuang Shiyuan case TCG_TYPE_V64: 942f63e7089SHuang Shiyuan case TCG_TYPE_V128: 943f63e7089SHuang Shiyuan case TCG_TYPE_V256: 944f63e7089SHuang Shiyuan if (type >= riscv_lg2_vlenb) { 945f63e7089SHuang Shiyuan static const RISCVInsn whole_reg_st[] = { 946f63e7089SHuang Shiyuan OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V 947f63e7089SHuang Shiyuan }; 948f63e7089SHuang Shiyuan unsigned idx = type - riscv_lg2_vlenb; 949f63e7089SHuang Shiyuan 950f63e7089SHuang Shiyuan tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st)); 951f63e7089SHuang Shiyuan insn = whole_reg_st[idx]; 952f63e7089SHuang Shiyuan } else { 953f63e7089SHuang Shiyuan static const RISCVInsn unit_stride_st[] = { 954f63e7089SHuang Shiyuan OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V 955f63e7089SHuang Shiyuan }; 956f63e7089SHuang Shiyuan MemOp prev_vsew = set_vtype_len(s, type); 957f63e7089SHuang Shiyuan 958f63e7089SHuang Shiyuan tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st)); 959f63e7089SHuang Shiyuan insn = unit_stride_st[prev_vsew]; 960f63e7089SHuang Shiyuan } 961f63e7089SHuang Shiyuan tcg_out_vec_ldst(s, insn, arg, arg1, arg2); 962f63e7089SHuang Shiyuan break; 963f63e7089SHuang Shiyuan default: 964f63e7089SHuang Shiyuan g_assert_not_reached(); 965f63e7089SHuang Shiyuan } 966139c1837SPaolo Bonzini} 967139c1837SPaolo Bonzini 968139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, 969139c1837SPaolo Bonzini TCGReg base, intptr_t ofs) 970139c1837SPaolo Bonzini{ 971139c1837SPaolo Bonzini if (val == 0) { 972139c1837SPaolo Bonzini tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); 973139c1837SPaolo Bonzini return true; 974139c1837SPaolo Bonzini } 975139c1837SPaolo Bonzini return false; 976139c1837SPaolo Bonzini} 977139c1837SPaolo Bonzini 978139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s, 979139c1837SPaolo Bonzini TCGReg rl, TCGReg rh, 980139c1837SPaolo Bonzini TCGReg al, TCGReg ah, 981139c1837SPaolo Bonzini TCGArg bl, TCGArg bh, 982139c1837SPaolo Bonzini bool cbl, bool cbh, bool is_sub, bool is32bit) 983139c1837SPaolo Bonzini{ 984139c1837SPaolo Bonzini const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD; 985139c1837SPaolo Bonzini const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI; 986139c1837SPaolo Bonzini const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB; 987139c1837SPaolo Bonzini TCGReg th = TCG_REG_TMP1; 988139c1837SPaolo Bonzini 989139c1837SPaolo Bonzini /* If we have a negative constant such that negating it would 990139c1837SPaolo Bonzini make the high part zero, we can (usually) eliminate one insn. */ 991139c1837SPaolo Bonzini if (cbl && cbh && bh == -1 && bl != 0) { 992139c1837SPaolo Bonzini bl = -bl; 993139c1837SPaolo Bonzini bh = 0; 994139c1837SPaolo Bonzini is_sub = !is_sub; 995139c1837SPaolo Bonzini } 996139c1837SPaolo Bonzini 997139c1837SPaolo Bonzini /* By operating on the high part first, we get to use the final 998139c1837SPaolo Bonzini carry operation to move back from the temporary. */ 999139c1837SPaolo Bonzini if (!cbh) { 1000139c1837SPaolo Bonzini tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh); 1001139c1837SPaolo Bonzini } else if (bh != 0 || ah == rl) { 1002139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh)); 1003139c1837SPaolo Bonzini } else { 1004139c1837SPaolo Bonzini th = ah; 1005139c1837SPaolo Bonzini } 1006139c1837SPaolo Bonzini 1007139c1837SPaolo Bonzini /* Note that tcg optimization should eliminate the bl == 0 case. */ 1008139c1837SPaolo Bonzini if (is_sub) { 1009139c1837SPaolo Bonzini if (cbl) { 1010139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl); 1011139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, rl, al, -bl); 1012139c1837SPaolo Bonzini } else { 1013139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl); 1014139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_sub, rl, al, bl); 1015139c1837SPaolo Bonzini } 1016139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0); 1017139c1837SPaolo Bonzini } else { 1018139c1837SPaolo Bonzini if (cbl) { 1019139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, rl, al, bl); 1020139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl); 10219b246685SRichard Henderson } else if (al == bl) { 10229b246685SRichard Henderson /* 10239b246685SRichard Henderson * If the input regs overlap, this is a simple doubling 10249b246685SRichard Henderson * and carry-out is the input msb. This special case is 10259b246685SRichard Henderson * required when the output reg overlaps the input, 10269b246685SRichard Henderson * but we might as well use it always. 10279b246685SRichard Henderson */ 1028139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0); 10299b246685SRichard Henderson tcg_out_opc_reg(s, opc_add, rl, al, al); 1030139c1837SPaolo Bonzini } else { 1031139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_add, rl, al, bl); 1032139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, 1033139c1837SPaolo Bonzini rl, (rl == bl ? al : bl)); 1034139c1837SPaolo Bonzini } 1035139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0); 1036139c1837SPaolo Bonzini } 1037139c1837SPaolo Bonzini} 1038139c1837SPaolo Bonzini 1039f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece, 1040f63e7089SHuang Shiyuan TCGReg dst, TCGReg src) 1041f63e7089SHuang Shiyuan{ 1042d4be6ee1STANG Tiancheng set_vtype_len_sew(s, type, vece); 1043d4be6ee1STANG Tiancheng tcg_out_opc_vx(s, OPC_VMV_V_X, dst, 0, src); 1044d4be6ee1STANG Tiancheng return true; 1045f63e7089SHuang Shiyuan} 1046f63e7089SHuang Shiyuan 1047f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece, 1048f63e7089SHuang Shiyuan TCGReg dst, TCGReg base, intptr_t offset) 1049f63e7089SHuang Shiyuan{ 1050d4be6ee1STANG Tiancheng tcg_out_ld(s, TCG_TYPE_REG, TCG_REG_TMP0, base, offset); 1051d4be6ee1STANG Tiancheng return tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0); 1052f63e7089SHuang Shiyuan} 1053f63e7089SHuang Shiyuan 1054f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece, 1055f63e7089SHuang Shiyuan TCGReg dst, int64_t arg) 1056f63e7089SHuang Shiyuan{ 1057d4be6ee1STANG Tiancheng /* Arg is replicated by VECE; extract the highest element. */ 1058d4be6ee1STANG Tiancheng arg >>= (-8 << vece) & 63; 1059d4be6ee1STANG Tiancheng 1060d4be6ee1STANG Tiancheng if (arg >= -16 && arg < 16) { 1061d4be6ee1STANG Tiancheng if (arg == 0 || arg == -1) { 1062d4be6ee1STANG Tiancheng set_vtype_len(s, type); 1063d4be6ee1STANG Tiancheng } else { 1064d4be6ee1STANG Tiancheng set_vtype_len_sew(s, type, vece); 1065d4be6ee1STANG Tiancheng } 1066d4be6ee1STANG Tiancheng tcg_out_opc_vi(s, OPC_VMV_V_I, dst, 0, arg); 1067d4be6ee1STANG Tiancheng return; 1068d4be6ee1STANG Tiancheng } 1069d4be6ee1STANG Tiancheng tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, arg); 1070d4be6ee1STANG Tiancheng tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0); 1071f63e7089SHuang Shiyuan} 1072f63e7089SHuang Shiyuan 1073139c1837SPaolo Bonzinistatic const struct { 1074139c1837SPaolo Bonzini RISCVInsn op; 1075139c1837SPaolo Bonzini bool swap; 1076139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = { 1077139c1837SPaolo Bonzini [TCG_COND_EQ] = { OPC_BEQ, false }, 1078139c1837SPaolo Bonzini [TCG_COND_NE] = { OPC_BNE, false }, 1079139c1837SPaolo Bonzini [TCG_COND_LT] = { OPC_BLT, false }, 1080139c1837SPaolo Bonzini [TCG_COND_GE] = { OPC_BGE, false }, 1081139c1837SPaolo Bonzini [TCG_COND_LE] = { OPC_BGE, true }, 1082139c1837SPaolo Bonzini [TCG_COND_GT] = { OPC_BLT, true }, 1083139c1837SPaolo Bonzini [TCG_COND_LTU] = { OPC_BLTU, false }, 1084139c1837SPaolo Bonzini [TCG_COND_GEU] = { OPC_BGEU, false }, 1085139c1837SPaolo Bonzini [TCG_COND_LEU] = { OPC_BGEU, true }, 1086139c1837SPaolo Bonzini [TCG_COND_GTU] = { OPC_BLTU, true } 1087139c1837SPaolo Bonzini}; 1088139c1837SPaolo Bonzini 1089139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, 1090139c1837SPaolo Bonzini TCGReg arg2, TCGLabel *l) 1091139c1837SPaolo Bonzini{ 1092139c1837SPaolo Bonzini RISCVInsn op = tcg_brcond_to_riscv[cond].op; 1093139c1837SPaolo Bonzini 1094139c1837SPaolo Bonzini tcg_debug_assert(op != 0); 1095139c1837SPaolo Bonzini 1096139c1837SPaolo Bonzini if (tcg_brcond_to_riscv[cond].swap) { 1097139c1837SPaolo Bonzini TCGReg t = arg1; 1098139c1837SPaolo Bonzini arg1 = arg2; 1099139c1837SPaolo Bonzini arg2 = t; 1100139c1837SPaolo Bonzini } 1101139c1837SPaolo Bonzini 1102139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0); 1103139c1837SPaolo Bonzini tcg_out_opc_branch(s, op, arg1, arg2, 0); 1104139c1837SPaolo Bonzini} 1105139c1837SPaolo Bonzini 1106f6453695SRichard Henderson#define SETCOND_INV TCG_TARGET_NB_REGS 1107f6453695SRichard Henderson#define SETCOND_NEZ (SETCOND_INV << 1) 1108f6453695SRichard Henderson#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ) 1109f6453695SRichard Henderson 1110f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret, 1111f6453695SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 1112139c1837SPaolo Bonzini{ 1113f6453695SRichard Henderson int flags = 0; 1114f6453695SRichard Henderson 1115139c1837SPaolo Bonzini switch (cond) { 1116f6453695SRichard Henderson case TCG_COND_EQ: /* -> NE */ 1117f6453695SRichard Henderson case TCG_COND_GE: /* -> LT */ 1118f6453695SRichard Henderson case TCG_COND_GEU: /* -> LTU */ 1119f6453695SRichard Henderson case TCG_COND_GT: /* -> LE */ 1120f6453695SRichard Henderson case TCG_COND_GTU: /* -> LEU */ 1121f6453695SRichard Henderson cond = tcg_invert_cond(cond); 1122f6453695SRichard Henderson flags ^= SETCOND_INV; 1123139c1837SPaolo Bonzini break; 1124f6453695SRichard Henderson default: 1125139c1837SPaolo Bonzini break; 1126f6453695SRichard Henderson } 1127f6453695SRichard Henderson 1128f6453695SRichard Henderson switch (cond) { 1129139c1837SPaolo Bonzini case TCG_COND_LE: 1130139c1837SPaolo Bonzini case TCG_COND_LEU: 1131f6453695SRichard Henderson /* 1132f6453695SRichard Henderson * If we have a constant input, the most efficient way to implement 1133f6453695SRichard Henderson * LE is by adding 1 and using LT. Watch out for wrap around for LEU. 1134f6453695SRichard Henderson * We don't need to care for this for LE because the constant input 1135f6453695SRichard Henderson * is constrained to signed 12-bit, and 0x800 is representable in the 1136f6453695SRichard Henderson * temporary register. 1137f6453695SRichard Henderson */ 1138f6453695SRichard Henderson if (c2) { 1139f6453695SRichard Henderson if (cond == TCG_COND_LEU) { 1140f6453695SRichard Henderson /* unsigned <= -1 is true */ 1141f6453695SRichard Henderson if (arg2 == -1) { 1142f6453695SRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV)); 1143f6453695SRichard Henderson return ret; 1144f6453695SRichard Henderson } 1145f6453695SRichard Henderson cond = TCG_COND_LTU; 1146f6453695SRichard Henderson } else { 1147f6453695SRichard Henderson cond = TCG_COND_LT; 1148f6453695SRichard Henderson } 1149f6453695SRichard Henderson tcg_debug_assert(arg2 <= 0x7ff); 1150f6453695SRichard Henderson if (++arg2 == 0x800) { 1151f6453695SRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2); 1152f6453695SRichard Henderson arg2 = TCG_REG_TMP0; 1153f6453695SRichard Henderson c2 = false; 1154f6453695SRichard Henderson } 1155f6453695SRichard Henderson } else { 1156f6453695SRichard Henderson TCGReg tmp = arg2; 1157f6453695SRichard Henderson arg2 = arg1; 1158f6453695SRichard Henderson arg1 = tmp; 1159f6453695SRichard Henderson cond = tcg_swap_cond(cond); /* LE -> GE */ 1160f6453695SRichard Henderson cond = tcg_invert_cond(cond); /* GE -> LT */ 1161f6453695SRichard Henderson flags ^= SETCOND_INV; 1162f6453695SRichard Henderson } 1163139c1837SPaolo Bonzini break; 1164f6453695SRichard Henderson default: 1165f6453695SRichard Henderson break; 1166f6453695SRichard Henderson } 1167f6453695SRichard Henderson 1168f6453695SRichard Henderson switch (cond) { 1169f6453695SRichard Henderson case TCG_COND_NE: 1170f6453695SRichard Henderson flags |= SETCOND_NEZ; 1171f6453695SRichard Henderson if (!c2) { 1172f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2); 1173f6453695SRichard Henderson } else if (arg2 == 0) { 1174f6453695SRichard Henderson ret = arg1; 1175f6453695SRichard Henderson } else { 1176f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2); 1177f6453695SRichard Henderson } 1178f6453695SRichard Henderson break; 1179f6453695SRichard Henderson 1180f6453695SRichard Henderson case TCG_COND_LT: 1181f6453695SRichard Henderson if (c2) { 1182f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2); 1183f6453695SRichard Henderson } else { 1184f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); 1185f6453695SRichard Henderson } 1186f6453695SRichard Henderson break; 1187f6453695SRichard Henderson 1188f6453695SRichard Henderson case TCG_COND_LTU: 1189f6453695SRichard Henderson if (c2) { 1190f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2); 1191f6453695SRichard Henderson } else { 1192f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); 1193f6453695SRichard Henderson } 1194f6453695SRichard Henderson break; 1195f6453695SRichard Henderson 1196f6453695SRichard Henderson default: 1197f6453695SRichard Henderson g_assert_not_reached(); 1198f6453695SRichard Henderson } 1199f6453695SRichard Henderson 1200f6453695SRichard Henderson return ret | flags; 1201f6453695SRichard Henderson} 1202f6453695SRichard Henderson 1203f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, 1204f6453695SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 1205f6453695SRichard Henderson{ 1206f6453695SRichard Henderson int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); 1207f6453695SRichard Henderson 1208f6453695SRichard Henderson if (tmpflags != ret) { 1209f6453695SRichard Henderson TCGReg tmp = tmpflags & ~SETCOND_FLAGS; 1210f6453695SRichard Henderson 1211f6453695SRichard Henderson switch (tmpflags & SETCOND_FLAGS) { 1212f6453695SRichard Henderson case SETCOND_INV: 1213f6453695SRichard Henderson /* Intermediate result is boolean: simply invert. */ 1214f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1); 1215f6453695SRichard Henderson break; 1216f6453695SRichard Henderson case SETCOND_NEZ: 1217f6453695SRichard Henderson /* Intermediate result is zero/non-zero: test != 0. */ 1218f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp); 1219f6453695SRichard Henderson break; 1220f6453695SRichard Henderson case SETCOND_NEZ | SETCOND_INV: 1221f6453695SRichard Henderson /* Intermediate result is zero/non-zero: test == 0. */ 1222f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1); 1223139c1837SPaolo Bonzini break; 1224139c1837SPaolo Bonzini default: 1225139c1837SPaolo Bonzini g_assert_not_reached(); 1226f6453695SRichard Henderson } 1227139c1837SPaolo Bonzini } 1228139c1837SPaolo Bonzini} 1229139c1837SPaolo Bonzini 123041e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret, 123141e4c0a9SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 123241e4c0a9SRichard Henderson{ 123341e4c0a9SRichard Henderson int tmpflags; 123441e4c0a9SRichard Henderson TCGReg tmp; 123541e4c0a9SRichard Henderson 123641e4c0a9SRichard Henderson /* For LT/GE comparison against 0, replicate the sign bit. */ 123741e4c0a9SRichard Henderson if (c2 && arg2 == 0) { 123841e4c0a9SRichard Henderson switch (cond) { 123941e4c0a9SRichard Henderson case TCG_COND_GE: 124041e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1); 124141e4c0a9SRichard Henderson arg1 = ret; 124241e4c0a9SRichard Henderson /* fall through */ 124341e4c0a9SRichard Henderson case TCG_COND_LT: 124441e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1); 124541e4c0a9SRichard Henderson return; 124641e4c0a9SRichard Henderson default: 124741e4c0a9SRichard Henderson break; 124841e4c0a9SRichard Henderson } 124941e4c0a9SRichard Henderson } 125041e4c0a9SRichard Henderson 125141e4c0a9SRichard Henderson tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); 125241e4c0a9SRichard Henderson tmp = tmpflags & ~SETCOND_FLAGS; 125341e4c0a9SRichard Henderson 125441e4c0a9SRichard Henderson /* If intermediate result is zero/non-zero: test != 0. */ 125541e4c0a9SRichard Henderson if (tmpflags & SETCOND_NEZ) { 125641e4c0a9SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp); 125741e4c0a9SRichard Henderson tmp = ret; 125841e4c0a9SRichard Henderson } 125941e4c0a9SRichard Henderson 126041e4c0a9SRichard Henderson /* Produce the 0/-1 result. */ 126141e4c0a9SRichard Henderson if (tmpflags & SETCOND_INV) { 126241e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1); 126341e4c0a9SRichard Henderson } else { 126441e4c0a9SRichard Henderson tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp); 126541e4c0a9SRichard Henderson } 126641e4c0a9SRichard Henderson} 126741e4c0a9SRichard Henderson 1268a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne, 1269a18d783eSRichard Henderson int val1, bool c_val1, 1270a18d783eSRichard Henderson int val2, bool c_val2) 1271a18d783eSRichard Henderson{ 1272a18d783eSRichard Henderson if (val1 == 0) { 1273a18d783eSRichard Henderson if (c_val2) { 1274a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2); 1275a18d783eSRichard Henderson val2 = TCG_REG_TMP1; 1276a18d783eSRichard Henderson } 1277a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne); 1278a18d783eSRichard Henderson return; 1279a18d783eSRichard Henderson } 1280a18d783eSRichard Henderson 1281a18d783eSRichard Henderson if (val2 == 0) { 1282a18d783eSRichard Henderson if (c_val1) { 1283a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1); 1284a18d783eSRichard Henderson val1 = TCG_REG_TMP1; 1285a18d783eSRichard Henderson } 1286a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne); 1287a18d783eSRichard Henderson return; 1288a18d783eSRichard Henderson } 1289a18d783eSRichard Henderson 1290a18d783eSRichard Henderson if (c_val2) { 1291a18d783eSRichard Henderson if (c_val1) { 1292a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2); 1293a18d783eSRichard Henderson } else { 1294a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2); 1295a18d783eSRichard Henderson } 1296a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne); 1297a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2); 1298a18d783eSRichard Henderson return; 1299a18d783eSRichard Henderson } 1300a18d783eSRichard Henderson 1301a18d783eSRichard Henderson if (c_val1) { 1302a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1); 1303a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne); 1304a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1); 1305a18d783eSRichard Henderson return; 1306a18d783eSRichard Henderson } 1307a18d783eSRichard Henderson 1308a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne); 1309a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne); 1310a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1); 1311a18d783eSRichard Henderson} 1312a18d783eSRichard Henderson 1313a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret, 1314a18d783eSRichard Henderson TCGReg cmp1, TCGReg cmp2, 1315a18d783eSRichard Henderson int val, bool c_val) 1316a18d783eSRichard Henderson{ 1317a18d783eSRichard Henderson RISCVInsn op; 1318a18d783eSRichard Henderson int disp = 8; 1319a18d783eSRichard Henderson 1320a18d783eSRichard Henderson tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv)); 1321a18d783eSRichard Henderson op = tcg_brcond_to_riscv[cond].op; 1322a18d783eSRichard Henderson tcg_debug_assert(op != 0); 1323a18d783eSRichard Henderson 1324a18d783eSRichard Henderson if (tcg_brcond_to_riscv[cond].swap) { 1325a18d783eSRichard Henderson tcg_out_opc_branch(s, op, cmp2, cmp1, disp); 1326a18d783eSRichard Henderson } else { 1327a18d783eSRichard Henderson tcg_out_opc_branch(s, op, cmp1, cmp2, disp); 1328a18d783eSRichard Henderson } 1329a18d783eSRichard Henderson if (c_val) { 1330a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val); 1331a18d783eSRichard Henderson } else { 1332a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0); 1333a18d783eSRichard Henderson } 1334a18d783eSRichard Henderson} 1335a18d783eSRichard Henderson 1336a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret, 1337a18d783eSRichard Henderson TCGReg cmp1, TCGReg cmp2, 1338a18d783eSRichard Henderson int val1, bool c_val1, 1339a18d783eSRichard Henderson int val2, bool c_val2) 1340a18d783eSRichard Henderson{ 1341a18d783eSRichard Henderson TCGReg tmp; 1342a18d783eSRichard Henderson 1343a18d783eSRichard Henderson /* TCG optimizer reorders to prefer ret matching val2. */ 1344a18d783eSRichard Henderson if (!c_val2 && ret == val2) { 1345a18d783eSRichard Henderson cond = tcg_invert_cond(cond); 1346a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1); 1347a18d783eSRichard Henderson return; 1348a18d783eSRichard Henderson } 1349a18d783eSRichard Henderson 1350a18d783eSRichard Henderson if (!c_val1 && ret == val1) { 1351a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2); 1352a18d783eSRichard Henderson return; 1353a18d783eSRichard Henderson } 1354a18d783eSRichard Henderson 1355a18d783eSRichard Henderson tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret); 1356a18d783eSRichard Henderson if (c_val1) { 1357a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, tmp, val1); 1358a18d783eSRichard Henderson } else { 1359a18d783eSRichard Henderson tcg_out_mov(s, TCG_TYPE_REG, tmp, val1); 1360a18d783eSRichard Henderson } 1361a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2); 1362a18d783eSRichard Henderson tcg_out_mov(s, TCG_TYPE_REG, ret, tmp); 1363a18d783eSRichard Henderson} 1364a18d783eSRichard Henderson 1365a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, 1366a18d783eSRichard Henderson TCGReg cmp1, int cmp2, bool c_cmp2, 1367a18d783eSRichard Henderson TCGReg val1, bool c_val1, 1368a18d783eSRichard Henderson TCGReg val2, bool c_val2) 1369a18d783eSRichard Henderson{ 1370a18d783eSRichard Henderson int tmpflags; 1371a18d783eSRichard Henderson TCGReg t; 1372a18d783eSRichard Henderson 1373b86c6ba6SRichard Henderson if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) { 1374a18d783eSRichard Henderson tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2, 1375a18d783eSRichard Henderson val1, c_val1, val2, c_val2); 1376a18d783eSRichard Henderson return; 1377a18d783eSRichard Henderson } 1378a18d783eSRichard Henderson 1379a18d783eSRichard Henderson tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2); 1380a18d783eSRichard Henderson t = tmpflags & ~SETCOND_FLAGS; 1381a18d783eSRichard Henderson 1382b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZICOND) { 1383a18d783eSRichard Henderson if (tmpflags & SETCOND_INV) { 1384a18d783eSRichard Henderson tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1); 1385a18d783eSRichard Henderson } else { 1386a18d783eSRichard Henderson tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2); 1387a18d783eSRichard Henderson } 1388a18d783eSRichard Henderson } else { 1389a18d783eSRichard Henderson cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE; 1390a18d783eSRichard Henderson tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO, 1391a18d783eSRichard Henderson val1, c_val1, val2, c_val2); 1392a18d783eSRichard Henderson } 1393a18d783eSRichard Henderson} 1394a18d783eSRichard Henderson 1395a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn, 1396a30498fcSRichard Henderson TCGReg ret, TCGReg src1, int src2, bool c_src2) 1397a30498fcSRichard Henderson{ 1398a30498fcSRichard Henderson tcg_out_opc_imm(s, insn, ret, src1, 0); 1399a30498fcSRichard Henderson 1400a30498fcSRichard Henderson if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) { 1401a30498fcSRichard Henderson /* 1402a30498fcSRichard Henderson * The requested zero result does not match the insn, so adjust. 1403a30498fcSRichard Henderson * Note that constraints put 'ret' in a new register, so the 1404a30498fcSRichard Henderson * computation above did not clobber either 'src1' or 'src2'. 1405a30498fcSRichard Henderson */ 1406a30498fcSRichard Henderson tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true, 1407a30498fcSRichard Henderson src2, c_src2, ret, false); 1408a30498fcSRichard Henderson } 1409a30498fcSRichard Henderson} 1410a30498fcSRichard Henderson 1411f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s) 1412f63e7089SHuang Shiyuan{ 1413f63e7089SHuang Shiyuan s->riscv_cur_type = TCG_TYPE_COUNT; 1414f63e7089SHuang Shiyuan} 1415f63e7089SHuang Shiyuan 14162be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) 1417139c1837SPaolo Bonzini{ 1418139c1837SPaolo Bonzini TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; 1419139c1837SPaolo Bonzini ptrdiff_t offset = tcg_pcrel_diff(s, arg); 1420139c1837SPaolo Bonzini int ret; 1421139c1837SPaolo Bonzini 1422f63e7089SHuang Shiyuan init_setting_vtype(s); 1423f63e7089SHuang Shiyuan 1424844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 1425844d0442SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 1426139c1837SPaolo Bonzini /* short jump: -2097150 to 2097152 */ 1427139c1837SPaolo Bonzini tcg_out_opc_jump(s, OPC_JAL, link, offset); 1428aeb6326eSRichard Henderson } else if (offset == (int32_t)offset) { 1429139c1837SPaolo Bonzini /* long jump: -2147483646 to 2147483648 */ 1430139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0); 1431139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0); 1432844d0442SRichard Henderson ret = reloc_call(s->code_ptr - 2, arg); 1433139c1837SPaolo Bonzini tcg_debug_assert(ret == true); 1434aeb6326eSRichard Henderson } else { 1435139c1837SPaolo Bonzini /* far jump: 64-bit */ 1436139c1837SPaolo Bonzini tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12); 1437139c1837SPaolo Bonzini tcg_target_long base = (tcg_target_long)arg - imm; 1438139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base); 1439139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm); 1440139c1837SPaolo Bonzini } 1441139c1837SPaolo Bonzini} 1442139c1837SPaolo Bonzini 1443cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg, 1444cee44b03SRichard Henderson const TCGHelperInfo *info) 1445139c1837SPaolo Bonzini{ 1446139c1837SPaolo Bonzini tcg_out_call_int(s, arg, false); 1447139c1837SPaolo Bonzini} 1448139c1837SPaolo Bonzini 1449139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0) 1450139c1837SPaolo Bonzini{ 1451139c1837SPaolo Bonzini tcg_insn_unit insn = OPC_FENCE; 1452139c1837SPaolo Bonzini 1453139c1837SPaolo Bonzini if (a0 & TCG_MO_LD_LD) { 1454139c1837SPaolo Bonzini insn |= 0x02200000; 1455139c1837SPaolo Bonzini } 1456139c1837SPaolo Bonzini if (a0 & TCG_MO_ST_LD) { 1457139c1837SPaolo Bonzini insn |= 0x01200000; 1458139c1837SPaolo Bonzini } 1459139c1837SPaolo Bonzini if (a0 & TCG_MO_LD_ST) { 1460139c1837SPaolo Bonzini insn |= 0x02100000; 1461139c1837SPaolo Bonzini } 1462139c1837SPaolo Bonzini if (a0 & TCG_MO_ST_ST) { 1463139c1837SPaolo Bonzini insn |= 0x02200000; 1464139c1837SPaolo Bonzini } 1465139c1837SPaolo Bonzini tcg_out32(s, insn); 1466139c1837SPaolo Bonzini} 1467139c1837SPaolo Bonzini 1468139c1837SPaolo Bonzini/* 1469139c1837SPaolo Bonzini * Load/store and TLB 1470139c1837SPaolo Bonzini */ 1471139c1837SPaolo Bonzini 1472793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) 1473844d0442SRichard Henderson{ 1474844d0442SRichard Henderson tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0); 1475844d0442SRichard Henderson bool ok = reloc_jimm20(s->code_ptr - 1, target); 1476844d0442SRichard Henderson tcg_debug_assert(ok); 1477844d0442SRichard Henderson} 1478844d0442SRichard Henderson 14797b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop) 14807b880107SRichard Henderson{ 14817b880107SRichard Henderson return false; 14827b880107SRichard Henderson} 14837b880107SRichard Henderson 148461b6daafSRichard Henderson/* We have three temps, we might as well expose them. */ 148561b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = { 148661b6daafSRichard Henderson .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 } 148761b6daafSRichard Henderson}; 148861b6daafSRichard Henderson 1489139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1490139c1837SPaolo Bonzini{ 149161b6daafSRichard Henderson MemOp opc = get_memop(l->oi); 1492139c1837SPaolo Bonzini 1493139c1837SPaolo Bonzini /* resolve label address */ 1494793f7381SRichard Henderson if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1495139c1837SPaolo Bonzini return false; 1496139c1837SPaolo Bonzini } 1497139c1837SPaolo Bonzini 1498139c1837SPaolo Bonzini /* call load helper */ 149961b6daafSRichard Henderson tcg_out_ld_helper_args(s, l, &ldst_helper_param); 1500cee44b03SRichard Henderson tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false); 150161b6daafSRichard Henderson tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param); 1502139c1837SPaolo Bonzini 1503139c1837SPaolo Bonzini tcg_out_goto(s, l->raddr); 1504139c1837SPaolo Bonzini return true; 1505139c1837SPaolo Bonzini} 1506139c1837SPaolo Bonzini 1507139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1508139c1837SPaolo Bonzini{ 150961b6daafSRichard Henderson MemOp opc = get_memop(l->oi); 1510139c1837SPaolo Bonzini 1511139c1837SPaolo Bonzini /* resolve label address */ 1512793f7381SRichard Henderson if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1513139c1837SPaolo Bonzini return false; 1514139c1837SPaolo Bonzini } 1515139c1837SPaolo Bonzini 1516139c1837SPaolo Bonzini /* call store helper */ 151761b6daafSRichard Henderson tcg_out_st_helper_args(s, l, &ldst_helper_param); 1518cee44b03SRichard Henderson tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false); 1519139c1837SPaolo Bonzini 1520139c1837SPaolo Bonzini tcg_out_goto(s, l->raddr); 1521139c1837SPaolo Bonzini return true; 1522139c1837SPaolo Bonzini} 1523139c1837SPaolo Bonzini 1524d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV. */ 1525d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS -(1 << 11) 1526d0a9bb5eSRichard Henderson 1527001dddfeSRichard Henderson/* 15287893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare. 15297893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests. 1530001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path 1531001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path. 1532001dddfeSRichard Henderson */ 1533001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase, 1534001dddfeSRichard Henderson TCGReg addr_reg, MemOpIdx oi, 1535001dddfeSRichard Henderson bool is_ld) 1536001dddfeSRichard Henderson{ 15378aefe1fbSRichard Henderson TCGType addr_type = s->addr_type; 1538001dddfeSRichard Henderson TCGLabelQemuLdst *ldst = NULL; 1539001dddfeSRichard Henderson MemOp opc = get_memop(oi); 154037e523f0SRichard Henderson TCGAtomAlign aa; 154137e523f0SRichard Henderson unsigned a_mask; 154237e523f0SRichard Henderson 154337e523f0SRichard Henderson aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false); 154437e523f0SRichard Henderson a_mask = (1u << aa.align) - 1; 1545001dddfeSRichard Henderson 15464944d359SRichard Henderson if (tcg_use_softmmu) { 1547001dddfeSRichard Henderson unsigned s_bits = opc & MO_SIZE; 1548933b331bSRichard Henderson unsigned s_mask = (1u << s_bits) - 1; 1549001dddfeSRichard Henderson int mem_index = get_mmuidx(oi); 1550d0a9bb5eSRichard Henderson int fast_ofs = tlb_mask_table_ofs(s, mem_index); 1551001dddfeSRichard Henderson int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); 1552001dddfeSRichard Henderson int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); 1553933b331bSRichard Henderson int compare_mask; 1554933b331bSRichard Henderson TCGReg addr_adj; 1555001dddfeSRichard Henderson 1556001dddfeSRichard Henderson ldst = new_ldst_label(s); 1557001dddfeSRichard Henderson ldst->is_ld = is_ld; 1558001dddfeSRichard Henderson ldst->oi = oi; 1559001dddfeSRichard Henderson ldst->addrlo_reg = addr_reg; 1560001dddfeSRichard Henderson 1561f63e7089SHuang Shiyuan init_setting_vtype(s); 1562f63e7089SHuang Shiyuan 1563933b331bSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); 1564933b331bSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); 1565001dddfeSRichard Henderson 1566001dddfeSRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg, 1567aece72b7SRichard Henderson s->page_bits - CPU_TLB_ENTRY_BITS); 1568001dddfeSRichard Henderson tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); 1569001dddfeSRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); 1570001dddfeSRichard Henderson 1571933b331bSRichard Henderson /* 15724944d359SRichard Henderson * For aligned accesses, we check the first byte and include the 15734944d359SRichard Henderson * alignment bits within the address. For unaligned access, we 15744944d359SRichard Henderson * check that we don't cross pages using the address of the last 15754944d359SRichard Henderson * byte of the access. 1576933b331bSRichard Henderson */ 1577933b331bSRichard Henderson addr_adj = addr_reg; 157837e523f0SRichard Henderson if (a_mask < s_mask) { 1579933b331bSRichard Henderson addr_adj = TCG_REG_TMP0; 15808aefe1fbSRichard Henderson tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI, 1581933b331bSRichard Henderson addr_adj, addr_reg, s_mask - a_mask); 1582933b331bSRichard Henderson } 1583aece72b7SRichard Henderson compare_mask = s->page_mask | a_mask; 1584933b331bSRichard Henderson if (compare_mask == sextreg(compare_mask, 0, 12)) { 1585933b331bSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask); 1586933b331bSRichard Henderson } else { 15878aefe1fbSRichard Henderson tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask); 1588933b331bSRichard Henderson tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj); 1589933b331bSRichard Henderson } 1590933b331bSRichard Henderson 1591001dddfeSRichard Henderson /* Load the tlb comparator and the addend. */ 1592238f4380SRichard Henderson QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN); 15938aefe1fbSRichard Henderson tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2, 1594001dddfeSRichard Henderson is_ld ? offsetof(CPUTLBEntry, addr_read) 1595001dddfeSRichard Henderson : offsetof(CPUTLBEntry, addr_write)); 1596001dddfeSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, 1597001dddfeSRichard Henderson offsetof(CPUTLBEntry, addend)); 1598001dddfeSRichard Henderson 1599001dddfeSRichard Henderson /* Compare masked address with the TLB entry. */ 1600001dddfeSRichard Henderson ldst->label_ptr[0] = s->code_ptr; 1601001dddfeSRichard Henderson tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0); 1602001dddfeSRichard Henderson 1603001dddfeSRichard Henderson /* TLB Hit - translate address using addend. */ 16048aefe1fbSRichard Henderson if (addr_type != TCG_TYPE_I32) { 1605eda15159SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2); 1606b86c6ba6SRichard Henderson } else if (cpuinfo & CPUINFO_ZBA) { 16074944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, 16084944d359SRichard Henderson addr_reg, TCG_REG_TMP2); 1609eda15159SRichard Henderson } else { 1610eda15159SRichard Henderson tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg); 16114944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, 16124944d359SRichard Henderson TCG_REG_TMP0, TCG_REG_TMP2); 1613001dddfeSRichard Henderson } 1614001dddfeSRichard Henderson *pbase = TCG_REG_TMP0; 16154944d359SRichard Henderson } else { 1616eda15159SRichard Henderson TCGReg base; 1617eda15159SRichard Henderson 1618001dddfeSRichard Henderson if (a_mask) { 1619001dddfeSRichard Henderson ldst = new_ldst_label(s); 1620001dddfeSRichard Henderson ldst->is_ld = is_ld; 1621001dddfeSRichard Henderson ldst->oi = oi; 1622001dddfeSRichard Henderson ldst->addrlo_reg = addr_reg; 1623001dddfeSRichard Henderson 1624f63e7089SHuang Shiyuan init_setting_vtype(s); 1625f63e7089SHuang Shiyuan 162637e523f0SRichard Henderson /* We are expecting alignment max 7, so we can always use andi. */ 162737e523f0SRichard Henderson tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12)); 1628001dddfeSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask); 1629001dddfeSRichard Henderson 1630001dddfeSRichard Henderson ldst->label_ptr[0] = s->code_ptr; 1631001dddfeSRichard Henderson tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0); 1632001dddfeSRichard Henderson } 1633001dddfeSRichard Henderson 1634001dddfeSRichard Henderson if (guest_base != 0) { 1635001dddfeSRichard Henderson base = TCG_REG_TMP0; 16368aefe1fbSRichard Henderson if (addr_type != TCG_TYPE_I32) { 16374944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, 16384944d359SRichard Henderson TCG_GUEST_BASE_REG); 1639b86c6ba6SRichard Henderson } else if (cpuinfo & CPUINFO_ZBA) { 16404944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, 16414944d359SRichard Henderson TCG_GUEST_BASE_REG); 1642eda15159SRichard Henderson } else { 1643eda15159SRichard Henderson tcg_out_ext32u(s, base, addr_reg); 1644eda15159SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG); 1645eda15159SRichard Henderson } 16468aefe1fbSRichard Henderson } else if (addr_type != TCG_TYPE_I32) { 1647eda15159SRichard Henderson base = addr_reg; 1648eda15159SRichard Henderson } else { 1649eda15159SRichard Henderson base = TCG_REG_TMP0; 1650eda15159SRichard Henderson tcg_out_ext32u(s, base, addr_reg); 1651001dddfeSRichard Henderson } 1652001dddfeSRichard Henderson *pbase = base; 16534944d359SRichard Henderson } 1654001dddfeSRichard Henderson 1655001dddfeSRichard Henderson return ldst; 1656001dddfeSRichard Henderson} 1657001dddfeSRichard Henderson 1658aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val, 1659f7041977SRichard Henderson TCGReg base, MemOp opc, TCGType type) 1660139c1837SPaolo Bonzini{ 1661c86bd2dcSRichard Henderson /* Byte swapping is left to middle-end expansion. */ 1662c86bd2dcSRichard Henderson tcg_debug_assert((opc & MO_BSWAP) == 0); 1663139c1837SPaolo Bonzini 1664139c1837SPaolo Bonzini switch (opc & (MO_SSIZE)) { 1665139c1837SPaolo Bonzini case MO_UB: 1666aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LBU, val, base, 0); 1667139c1837SPaolo Bonzini break; 1668139c1837SPaolo Bonzini case MO_SB: 1669aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LB, val, base, 0); 1670139c1837SPaolo Bonzini break; 1671139c1837SPaolo Bonzini case MO_UW: 1672aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LHU, val, base, 0); 1673139c1837SPaolo Bonzini break; 1674139c1837SPaolo Bonzini case MO_SW: 1675aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LH, val, base, 0); 1676139c1837SPaolo Bonzini break; 1677139c1837SPaolo Bonzini case MO_UL: 1678f7041977SRichard Henderson if (type == TCG_TYPE_I64) { 1679aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LWU, val, base, 0); 1680139c1837SPaolo Bonzini break; 1681139c1837SPaolo Bonzini } 1682139c1837SPaolo Bonzini /* FALLTHRU */ 1683139c1837SPaolo Bonzini case MO_SL: 1684aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LW, val, base, 0); 1685139c1837SPaolo Bonzini break; 1686fc313c64SFrédéric Pétrot case MO_UQ: 1687aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LD, val, base, 0); 1688139c1837SPaolo Bonzini break; 1689139c1837SPaolo Bonzini default: 1690139c1837SPaolo Bonzini g_assert_not_reached(); 1691139c1837SPaolo Bonzini } 1692139c1837SPaolo Bonzini} 1693139c1837SPaolo Bonzini 1694f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1695f7041977SRichard Henderson MemOpIdx oi, TCGType data_type) 1696139c1837SPaolo Bonzini{ 1697001dddfeSRichard Henderson TCGLabelQemuLdst *ldst; 16982e3a933aSRichard Henderson TCGReg base; 1699139c1837SPaolo Bonzini 1700001dddfeSRichard Henderson ldst = prepare_host_addr(s, &base, addr_reg, oi, true); 1701001dddfeSRichard Henderson tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type); 1702f7041977SRichard Henderson 1703001dddfeSRichard Henderson if (ldst) { 1704001dddfeSRichard Henderson ldst->type = data_type; 1705001dddfeSRichard Henderson ldst->datalo_reg = data_reg; 1706001dddfeSRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1707a3fb7c99SRichard Henderson } 1708139c1837SPaolo Bonzini} 1709139c1837SPaolo Bonzini 1710aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val, 1711139c1837SPaolo Bonzini TCGReg base, MemOp opc) 1712139c1837SPaolo Bonzini{ 1713c86bd2dcSRichard Henderson /* Byte swapping is left to middle-end expansion. */ 1714c86bd2dcSRichard Henderson tcg_debug_assert((opc & MO_BSWAP) == 0); 1715139c1837SPaolo Bonzini 1716139c1837SPaolo Bonzini switch (opc & (MO_SSIZE)) { 1717139c1837SPaolo Bonzini case MO_8: 1718aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SB, base, val, 0); 1719139c1837SPaolo Bonzini break; 1720139c1837SPaolo Bonzini case MO_16: 1721aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SH, base, val, 0); 1722139c1837SPaolo Bonzini break; 1723139c1837SPaolo Bonzini case MO_32: 1724aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SW, base, val, 0); 1725139c1837SPaolo Bonzini break; 1726139c1837SPaolo Bonzini case MO_64: 1727aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SD, base, val, 0); 1728139c1837SPaolo Bonzini break; 1729139c1837SPaolo Bonzini default: 1730139c1837SPaolo Bonzini g_assert_not_reached(); 1731139c1837SPaolo Bonzini } 1732139c1837SPaolo Bonzini} 1733139c1837SPaolo Bonzini 1734f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1735f7041977SRichard Henderson MemOpIdx oi, TCGType data_type) 1736139c1837SPaolo Bonzini{ 1737001dddfeSRichard Henderson TCGLabelQemuLdst *ldst; 17382e3a933aSRichard Henderson TCGReg base; 1739139c1837SPaolo Bonzini 1740001dddfeSRichard Henderson ldst = prepare_host_addr(s, &base, addr_reg, oi, false); 1741001dddfeSRichard Henderson tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi)); 1742f7041977SRichard Henderson 1743001dddfeSRichard Henderson if (ldst) { 1744001dddfeSRichard Henderson ldst->type = data_type; 1745001dddfeSRichard Henderson ldst->datalo_reg = data_reg; 1746001dddfeSRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1747a3fb7c99SRichard Henderson } 1748139c1837SPaolo Bonzini} 1749139c1837SPaolo Bonzini 1750793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr; 1751139c1837SPaolo Bonzini 1752b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) 1753b55a8d9dSRichard Henderson{ 1754b55a8d9dSRichard Henderson /* Reuse the zeroing that exists for goto_ptr. */ 1755b55a8d9dSRichard Henderson if (a0 == 0) { 1756b55a8d9dSRichard Henderson tcg_out_call_int(s, tcg_code_gen_epilogue, true); 1757b55a8d9dSRichard Henderson } else { 1758b55a8d9dSRichard Henderson tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); 1759b55a8d9dSRichard Henderson tcg_out_call_int(s, tb_ret_addr, true); 1760b55a8d9dSRichard Henderson } 1761b55a8d9dSRichard Henderson} 1762b55a8d9dSRichard Henderson 1763cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which) 1764cf7d6b8eSRichard Henderson{ 1765493c9b19SRichard Henderson /* Direct branch will be patched by tb_target_set_jmp_target. */ 1766493c9b19SRichard Henderson set_jmp_insn_offset(s, which); 1767493c9b19SRichard Henderson tcg_out32(s, OPC_JAL); 1768493c9b19SRichard Henderson 1769493c9b19SRichard Henderson /* When branch is out of range, fall through to indirect. */ 1770cf7d6b8eSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, 1771cf7d6b8eSRichard Henderson get_jmp_target_addr(s, which)); 1772cf7d6b8eSRichard Henderson tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); 1773cf7d6b8eSRichard Henderson set_jmp_reset_offset(s, which); 1774cf7d6b8eSRichard Henderson} 1775cf7d6b8eSRichard Henderson 177690c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n, 177790c0fee3SRichard Henderson uintptr_t jmp_rx, uintptr_t jmp_rw) 177890c0fee3SRichard Henderson{ 1779493c9b19SRichard Henderson uintptr_t addr = tb->jmp_target_addr[n]; 1780493c9b19SRichard Henderson ptrdiff_t offset = addr - jmp_rx; 1781493c9b19SRichard Henderson tcg_insn_unit insn; 1782493c9b19SRichard Henderson 1783493c9b19SRichard Henderson /* Either directly branch, or fall through to indirect branch. */ 1784493c9b19SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 1785493c9b19SRichard Henderson insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset); 1786493c9b19SRichard Henderson } else { 1787493c9b19SRichard Henderson insn = OPC_NOP; 1788493c9b19SRichard Henderson } 1789493c9b19SRichard Henderson qatomic_set((uint32_t *)jmp_rw, insn); 1790493c9b19SRichard Henderson flush_idcache_range(jmp_rx, jmp_rw, 4); 179190c0fee3SRichard Henderson} 179290c0fee3SRichard Henderson 1793139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc, 17945e8892dbSMiroslav Rezanina const TCGArg args[TCG_MAX_OP_ARGS], 17955e8892dbSMiroslav Rezanina const int const_args[TCG_MAX_OP_ARGS]) 1796139c1837SPaolo Bonzini{ 1797139c1837SPaolo Bonzini TCGArg a0 = args[0]; 1798139c1837SPaolo Bonzini TCGArg a1 = args[1]; 1799139c1837SPaolo Bonzini TCGArg a2 = args[2]; 1800139c1837SPaolo Bonzini int c2 = const_args[2]; 1801139c1837SPaolo Bonzini 1802139c1837SPaolo Bonzini switch (opc) { 1803139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 1804139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0); 1805139c1837SPaolo Bonzini break; 1806139c1837SPaolo Bonzini 1807139c1837SPaolo Bonzini case INDEX_op_br: 1808139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0); 1809139c1837SPaolo Bonzini tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0); 1810139c1837SPaolo Bonzini break; 1811139c1837SPaolo Bonzini 1812139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 1813139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 1814139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LBU, a0, a1, a2); 1815139c1837SPaolo Bonzini break; 1816139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 1817139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 1818139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LB, a0, a1, a2); 1819139c1837SPaolo Bonzini break; 1820139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 1821139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 1822139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LHU, a0, a1, a2); 1823139c1837SPaolo Bonzini break; 1824139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 1825139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 1826139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LH, a0, a1, a2); 1827139c1837SPaolo Bonzini break; 1828139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 1829139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LWU, a0, a1, a2); 1830139c1837SPaolo Bonzini break; 1831139c1837SPaolo Bonzini case INDEX_op_ld_i32: 1832139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 1833139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LW, a0, a1, a2); 1834139c1837SPaolo Bonzini break; 1835139c1837SPaolo Bonzini case INDEX_op_ld_i64: 1836139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LD, a0, a1, a2); 1837139c1837SPaolo Bonzini break; 1838139c1837SPaolo Bonzini 1839139c1837SPaolo Bonzini case INDEX_op_st8_i32: 1840139c1837SPaolo Bonzini case INDEX_op_st8_i64: 1841139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SB, a0, a1, a2); 1842139c1837SPaolo Bonzini break; 1843139c1837SPaolo Bonzini case INDEX_op_st16_i32: 1844139c1837SPaolo Bonzini case INDEX_op_st16_i64: 1845139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SH, a0, a1, a2); 1846139c1837SPaolo Bonzini break; 1847139c1837SPaolo Bonzini case INDEX_op_st_i32: 1848139c1837SPaolo Bonzini case INDEX_op_st32_i64: 1849139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SW, a0, a1, a2); 1850139c1837SPaolo Bonzini break; 1851139c1837SPaolo Bonzini case INDEX_op_st_i64: 1852139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SD, a0, a1, a2); 1853139c1837SPaolo Bonzini break; 1854139c1837SPaolo Bonzini 1855139c1837SPaolo Bonzini case INDEX_op_add_i32: 1856139c1837SPaolo Bonzini if (c2) { 1857139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2); 1858139c1837SPaolo Bonzini } else { 1859139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2); 1860139c1837SPaolo Bonzini } 1861139c1837SPaolo Bonzini break; 1862139c1837SPaolo Bonzini case INDEX_op_add_i64: 1863139c1837SPaolo Bonzini if (c2) { 1864139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2); 1865139c1837SPaolo Bonzini } else { 1866139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2); 1867139c1837SPaolo Bonzini } 1868139c1837SPaolo Bonzini break; 1869139c1837SPaolo Bonzini 1870139c1837SPaolo Bonzini case INDEX_op_sub_i32: 1871139c1837SPaolo Bonzini if (c2) { 1872139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2); 1873139c1837SPaolo Bonzini } else { 1874139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2); 1875139c1837SPaolo Bonzini } 1876139c1837SPaolo Bonzini break; 1877139c1837SPaolo Bonzini case INDEX_op_sub_i64: 1878139c1837SPaolo Bonzini if (c2) { 1879139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2); 1880139c1837SPaolo Bonzini } else { 1881139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2); 1882139c1837SPaolo Bonzini } 1883139c1837SPaolo Bonzini break; 1884139c1837SPaolo Bonzini 1885139c1837SPaolo Bonzini case INDEX_op_and_i32: 1886139c1837SPaolo Bonzini case INDEX_op_and_i64: 1887139c1837SPaolo Bonzini if (c2) { 1888139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2); 1889139c1837SPaolo Bonzini } else { 1890139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_AND, a0, a1, a2); 1891139c1837SPaolo Bonzini } 1892139c1837SPaolo Bonzini break; 1893139c1837SPaolo Bonzini 1894139c1837SPaolo Bonzini case INDEX_op_or_i32: 1895139c1837SPaolo Bonzini case INDEX_op_or_i64: 1896139c1837SPaolo Bonzini if (c2) { 1897139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2); 1898139c1837SPaolo Bonzini } else { 1899139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_OR, a0, a1, a2); 1900139c1837SPaolo Bonzini } 1901139c1837SPaolo Bonzini break; 1902139c1837SPaolo Bonzini 1903139c1837SPaolo Bonzini case INDEX_op_xor_i32: 1904139c1837SPaolo Bonzini case INDEX_op_xor_i64: 1905139c1837SPaolo Bonzini if (c2) { 1906139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2); 1907139c1837SPaolo Bonzini } else { 1908139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2); 1909139c1837SPaolo Bonzini } 1910139c1837SPaolo Bonzini break; 1911139c1837SPaolo Bonzini 191299f4ec6eSRichard Henderson case INDEX_op_andc_i32: 191399f4ec6eSRichard Henderson case INDEX_op_andc_i64: 191499f4ec6eSRichard Henderson if (c2) { 191599f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2); 191699f4ec6eSRichard Henderson } else { 191799f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2); 191899f4ec6eSRichard Henderson } 191999f4ec6eSRichard Henderson break; 192099f4ec6eSRichard Henderson case INDEX_op_orc_i32: 192199f4ec6eSRichard Henderson case INDEX_op_orc_i64: 192299f4ec6eSRichard Henderson if (c2) { 192399f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2); 192499f4ec6eSRichard Henderson } else { 192599f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2); 192699f4ec6eSRichard Henderson } 192799f4ec6eSRichard Henderson break; 192899f4ec6eSRichard Henderson case INDEX_op_eqv_i32: 192999f4ec6eSRichard Henderson case INDEX_op_eqv_i64: 193099f4ec6eSRichard Henderson if (c2) { 193199f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2); 193299f4ec6eSRichard Henderson } else { 193399f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2); 193499f4ec6eSRichard Henderson } 193599f4ec6eSRichard Henderson break; 193699f4ec6eSRichard Henderson 1937139c1837SPaolo Bonzini case INDEX_op_not_i32: 1938139c1837SPaolo Bonzini case INDEX_op_not_i64: 1939139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1); 1940139c1837SPaolo Bonzini break; 1941139c1837SPaolo Bonzini 1942139c1837SPaolo Bonzini case INDEX_op_neg_i32: 1943139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1); 1944139c1837SPaolo Bonzini break; 1945139c1837SPaolo Bonzini case INDEX_op_neg_i64: 1946139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1); 1947139c1837SPaolo Bonzini break; 1948139c1837SPaolo Bonzini 1949139c1837SPaolo Bonzini case INDEX_op_mul_i32: 1950139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2); 1951139c1837SPaolo Bonzini break; 1952139c1837SPaolo Bonzini case INDEX_op_mul_i64: 1953139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2); 1954139c1837SPaolo Bonzini break; 1955139c1837SPaolo Bonzini 1956139c1837SPaolo Bonzini case INDEX_op_div_i32: 1957139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2); 1958139c1837SPaolo Bonzini break; 1959139c1837SPaolo Bonzini case INDEX_op_div_i64: 1960139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2); 1961139c1837SPaolo Bonzini break; 1962139c1837SPaolo Bonzini 1963139c1837SPaolo Bonzini case INDEX_op_divu_i32: 1964139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2); 1965139c1837SPaolo Bonzini break; 1966139c1837SPaolo Bonzini case INDEX_op_divu_i64: 1967139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2); 1968139c1837SPaolo Bonzini break; 1969139c1837SPaolo Bonzini 1970139c1837SPaolo Bonzini case INDEX_op_rem_i32: 1971139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2); 1972139c1837SPaolo Bonzini break; 1973139c1837SPaolo Bonzini case INDEX_op_rem_i64: 1974139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REM, a0, a1, a2); 1975139c1837SPaolo Bonzini break; 1976139c1837SPaolo Bonzini 1977139c1837SPaolo Bonzini case INDEX_op_remu_i32: 1978139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2); 1979139c1837SPaolo Bonzini break; 1980139c1837SPaolo Bonzini case INDEX_op_remu_i64: 1981139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2); 1982139c1837SPaolo Bonzini break; 1983139c1837SPaolo Bonzini 1984139c1837SPaolo Bonzini case INDEX_op_shl_i32: 1985139c1837SPaolo Bonzini if (c2) { 1986d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f); 1987139c1837SPaolo Bonzini } else { 1988139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2); 1989139c1837SPaolo Bonzini } 1990139c1837SPaolo Bonzini break; 1991139c1837SPaolo Bonzini case INDEX_op_shl_i64: 1992139c1837SPaolo Bonzini if (c2) { 1993d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f); 1994139c1837SPaolo Bonzini } else { 1995139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2); 1996139c1837SPaolo Bonzini } 1997139c1837SPaolo Bonzini break; 1998139c1837SPaolo Bonzini 1999139c1837SPaolo Bonzini case INDEX_op_shr_i32: 2000139c1837SPaolo Bonzini if (c2) { 2001d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f); 2002139c1837SPaolo Bonzini } else { 2003139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2); 2004139c1837SPaolo Bonzini } 2005139c1837SPaolo Bonzini break; 2006139c1837SPaolo Bonzini case INDEX_op_shr_i64: 2007139c1837SPaolo Bonzini if (c2) { 2008d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f); 2009139c1837SPaolo Bonzini } else { 2010139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2); 2011139c1837SPaolo Bonzini } 2012139c1837SPaolo Bonzini break; 2013139c1837SPaolo Bonzini 2014139c1837SPaolo Bonzini case INDEX_op_sar_i32: 2015139c1837SPaolo Bonzini if (c2) { 2016d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f); 2017139c1837SPaolo Bonzini } else { 2018139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2); 2019139c1837SPaolo Bonzini } 2020139c1837SPaolo Bonzini break; 2021139c1837SPaolo Bonzini case INDEX_op_sar_i64: 2022139c1837SPaolo Bonzini if (c2) { 2023d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f); 2024139c1837SPaolo Bonzini } else { 2025139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2); 2026139c1837SPaolo Bonzini } 2027139c1837SPaolo Bonzini break; 2028139c1837SPaolo Bonzini 202919d016adSRichard Henderson case INDEX_op_rotl_i32: 203019d016adSRichard Henderson if (c2) { 203119d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f); 203219d016adSRichard Henderson } else { 203319d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2); 203419d016adSRichard Henderson } 203519d016adSRichard Henderson break; 203619d016adSRichard Henderson case INDEX_op_rotl_i64: 203719d016adSRichard Henderson if (c2) { 203819d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f); 203919d016adSRichard Henderson } else { 204019d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2); 204119d016adSRichard Henderson } 204219d016adSRichard Henderson break; 204319d016adSRichard Henderson 204419d016adSRichard Henderson case INDEX_op_rotr_i32: 204519d016adSRichard Henderson if (c2) { 204619d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f); 204719d016adSRichard Henderson } else { 204819d016adSRichard Henderson tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2); 204919d016adSRichard Henderson } 205019d016adSRichard Henderson break; 205119d016adSRichard Henderson case INDEX_op_rotr_i64: 205219d016adSRichard Henderson if (c2) { 205319d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f); 205419d016adSRichard Henderson } else { 205519d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2); 205619d016adSRichard Henderson } 205719d016adSRichard Henderson break; 205819d016adSRichard Henderson 20597b4d5274SRichard Henderson case INDEX_op_bswap64_i64: 20607b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 20617b4d5274SRichard Henderson break; 20627b4d5274SRichard Henderson case INDEX_op_bswap32_i32: 20637b4d5274SRichard Henderson a2 = 0; 20647b4d5274SRichard Henderson /* fall through */ 20657b4d5274SRichard Henderson case INDEX_op_bswap32_i64: 20667b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 20677b4d5274SRichard Henderson if (a2 & TCG_BSWAP_OZ) { 20687b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32); 20697b4d5274SRichard Henderson } else { 20707b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32); 20717b4d5274SRichard Henderson } 20727b4d5274SRichard Henderson break; 20737b4d5274SRichard Henderson case INDEX_op_bswap16_i64: 20747b4d5274SRichard Henderson case INDEX_op_bswap16_i32: 20757b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 20767b4d5274SRichard Henderson if (a2 & TCG_BSWAP_OZ) { 20777b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48); 20787b4d5274SRichard Henderson } else { 20797b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48); 20807b4d5274SRichard Henderson } 20817b4d5274SRichard Henderson break; 20827b4d5274SRichard Henderson 20830956ecdaSRichard Henderson case INDEX_op_ctpop_i32: 20840956ecdaSRichard Henderson tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0); 20850956ecdaSRichard Henderson break; 20860956ecdaSRichard Henderson case INDEX_op_ctpop_i64: 20870956ecdaSRichard Henderson tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0); 20880956ecdaSRichard Henderson break; 20890956ecdaSRichard Henderson 2090a30498fcSRichard Henderson case INDEX_op_clz_i32: 2091a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2); 2092a30498fcSRichard Henderson break; 2093a30498fcSRichard Henderson case INDEX_op_clz_i64: 2094a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2); 2095a30498fcSRichard Henderson break; 2096a30498fcSRichard Henderson case INDEX_op_ctz_i32: 2097a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2); 2098a30498fcSRichard Henderson break; 2099a30498fcSRichard Henderson case INDEX_op_ctz_i64: 2100a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2); 2101a30498fcSRichard Henderson break; 2102a30498fcSRichard Henderson 2103139c1837SPaolo Bonzini case INDEX_op_add2_i32: 2104139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2105139c1837SPaolo Bonzini const_args[4], const_args[5], false, true); 2106139c1837SPaolo Bonzini break; 2107139c1837SPaolo Bonzini case INDEX_op_add2_i64: 2108139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2109139c1837SPaolo Bonzini const_args[4], const_args[5], false, false); 2110139c1837SPaolo Bonzini break; 2111139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 2112139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2113139c1837SPaolo Bonzini const_args[4], const_args[5], true, true); 2114139c1837SPaolo Bonzini break; 2115139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 2116139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2117139c1837SPaolo Bonzini const_args[4], const_args[5], true, false); 2118139c1837SPaolo Bonzini break; 2119139c1837SPaolo Bonzini 2120139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 2121139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 2122139c1837SPaolo Bonzini tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); 2123139c1837SPaolo Bonzini break; 2124139c1837SPaolo Bonzini 2125139c1837SPaolo Bonzini case INDEX_op_setcond_i32: 2126139c1837SPaolo Bonzini case INDEX_op_setcond_i64: 2127f6453695SRichard Henderson tcg_out_setcond(s, args[3], a0, a1, a2, c2); 2128139c1837SPaolo Bonzini break; 2129139c1837SPaolo Bonzini 213041e4c0a9SRichard Henderson case INDEX_op_negsetcond_i32: 213141e4c0a9SRichard Henderson case INDEX_op_negsetcond_i64: 213241e4c0a9SRichard Henderson tcg_out_negsetcond(s, args[3], a0, a1, a2, c2); 213341e4c0a9SRichard Henderson break; 213441e4c0a9SRichard Henderson 2135a18d783eSRichard Henderson case INDEX_op_movcond_i32: 2136a18d783eSRichard Henderson case INDEX_op_movcond_i64: 2137a18d783eSRichard Henderson tcg_out_movcond(s, args[5], a0, a1, a2, c2, 2138a18d783eSRichard Henderson args[3], const_args[3], args[4], const_args[4]); 2139a18d783eSRichard Henderson break; 2140a18d783eSRichard Henderson 2141fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 2142fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 2143f7041977SRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); 2144139c1837SPaolo Bonzini break; 2145fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 2146fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 2147f7041977SRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64); 2148139c1837SPaolo Bonzini break; 2149fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 2150fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 2151f7041977SRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32); 2152139c1837SPaolo Bonzini break; 2153fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 2154fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 2155f7041977SRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64); 2156139c1837SPaolo Bonzini break; 2157139c1837SPaolo Bonzini 2158139c1837SPaolo Bonzini case INDEX_op_extrh_i64_i32: 2159139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32); 2160139c1837SPaolo Bonzini break; 2161139c1837SPaolo Bonzini 2162139c1837SPaolo Bonzini case INDEX_op_mulsh_i32: 2163139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 2164139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2); 2165139c1837SPaolo Bonzini break; 2166139c1837SPaolo Bonzini 2167139c1837SPaolo Bonzini case INDEX_op_muluh_i32: 2168139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 2169139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2); 2170139c1837SPaolo Bonzini break; 2171139c1837SPaolo Bonzini 2172139c1837SPaolo Bonzini case INDEX_op_mb: 2173139c1837SPaolo Bonzini tcg_out_mb(s, a0); 2174139c1837SPaolo Bonzini break; 2175139c1837SPaolo Bonzini 2176139c1837SPaolo Bonzini case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ 2177139c1837SPaolo Bonzini case INDEX_op_mov_i64: 2178139c1837SPaolo Bonzini case INDEX_op_call: /* Always emitted via tcg_out_call. */ 2179b55a8d9dSRichard Henderson case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ 2180cf7d6b8eSRichard Henderson case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ 2181678155b2SRichard Henderson case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */ 2182678155b2SRichard Henderson case INDEX_op_ext8s_i64: 2183d0e66c89SRichard Henderson case INDEX_op_ext8u_i32: 2184d0e66c89SRichard Henderson case INDEX_op_ext8u_i64: 2185753e42eaSRichard Henderson case INDEX_op_ext16s_i32: 2186753e42eaSRichard Henderson case INDEX_op_ext16s_i64: 2187379afdffSRichard Henderson case INDEX_op_ext16u_i32: 2188379afdffSRichard Henderson case INDEX_op_ext16u_i64: 218952bf3398SRichard Henderson case INDEX_op_ext32s_i64: 21909ecf5f61SRichard Henderson case INDEX_op_ext32u_i64: 21919c6aa274SRichard Henderson case INDEX_op_ext_i32_i64: 2192b9bfe000SRichard Henderson case INDEX_op_extu_i32_i64: 2193b8b94ac6SRichard Henderson case INDEX_op_extrl_i64_i32: 2194139c1837SPaolo Bonzini default: 2195139c1837SPaolo Bonzini g_assert_not_reached(); 2196139c1837SPaolo Bonzini } 2197139c1837SPaolo Bonzini} 2198139c1837SPaolo Bonzini 2199f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, 2200f63e7089SHuang Shiyuan unsigned vecl, unsigned vece, 2201f63e7089SHuang Shiyuan const TCGArg args[TCG_MAX_OP_ARGS], 2202f63e7089SHuang Shiyuan const int const_args[TCG_MAX_OP_ARGS]) 2203f63e7089SHuang Shiyuan{ 2204f63e7089SHuang Shiyuan TCGType type = vecl + TCG_TYPE_V64; 2205f63e7089SHuang Shiyuan TCGArg a0, a1, a2; 2206*5a63f599STANG Tiancheng int c2; 2207f63e7089SHuang Shiyuan 2208f63e7089SHuang Shiyuan a0 = args[0]; 2209f63e7089SHuang Shiyuan a1 = args[1]; 2210f63e7089SHuang Shiyuan a2 = args[2]; 2211*5a63f599STANG Tiancheng c2 = const_args[2]; 2212f63e7089SHuang Shiyuan 2213f63e7089SHuang Shiyuan switch (opc) { 2214d4be6ee1STANG Tiancheng case INDEX_op_dupm_vec: 2215d4be6ee1STANG Tiancheng tcg_out_dupm_vec(s, type, vece, a0, a1, a2); 2216d4be6ee1STANG Tiancheng break; 2217f63e7089SHuang Shiyuan case INDEX_op_ld_vec: 2218f63e7089SHuang Shiyuan tcg_out_ld(s, type, a0, a1, a2); 2219f63e7089SHuang Shiyuan break; 2220f63e7089SHuang Shiyuan case INDEX_op_st_vec: 2221f63e7089SHuang Shiyuan tcg_out_st(s, type, a0, a1, a2); 2222f63e7089SHuang Shiyuan break; 2223*5a63f599STANG Tiancheng case INDEX_op_add_vec: 2224*5a63f599STANG Tiancheng set_vtype_len_sew(s, type, vece); 2225*5a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VADD_VV, OPC_VADD_VI, a0, a1, a2, c2); 2226*5a63f599STANG Tiancheng break; 2227*5a63f599STANG Tiancheng case INDEX_op_sub_vec: 2228*5a63f599STANG Tiancheng set_vtype_len_sew(s, type, vece); 2229*5a63f599STANG Tiancheng tcg_out_opc_vv(s, OPC_VSUB_VV, a0, a1, a2); 2230*5a63f599STANG Tiancheng break; 2231*5a63f599STANG Tiancheng case INDEX_op_and_vec: 2232*5a63f599STANG Tiancheng set_vtype_len(s, type); 2233*5a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VAND_VV, OPC_VAND_VI, a0, a1, a2, c2); 2234*5a63f599STANG Tiancheng break; 2235*5a63f599STANG Tiancheng case INDEX_op_or_vec: 2236*5a63f599STANG Tiancheng set_vtype_len(s, type); 2237*5a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VOR_VV, OPC_VOR_VI, a0, a1, a2, c2); 2238*5a63f599STANG Tiancheng break; 2239*5a63f599STANG Tiancheng case INDEX_op_xor_vec: 2240*5a63f599STANG Tiancheng set_vtype_len(s, type); 2241*5a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VXOR_VV, OPC_VXOR_VI, a0, a1, a2, c2); 2242*5a63f599STANG Tiancheng break; 2243*5a63f599STANG Tiancheng case INDEX_op_not_vec: 2244*5a63f599STANG Tiancheng set_vtype_len(s, type); 2245*5a63f599STANG Tiancheng tcg_out_opc_vi(s, OPC_VXOR_VI, a0, a1, -1); 2246*5a63f599STANG Tiancheng break; 2247f63e7089SHuang Shiyuan case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */ 2248f63e7089SHuang Shiyuan case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */ 2249f63e7089SHuang Shiyuan default: 2250f63e7089SHuang Shiyuan g_assert_not_reached(); 2251f63e7089SHuang Shiyuan } 2252f63e7089SHuang Shiyuan} 2253f63e7089SHuang Shiyuan 2254f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, 2255f63e7089SHuang Shiyuan TCGArg a0, ...) 2256f63e7089SHuang Shiyuan{ 2257f63e7089SHuang Shiyuan g_assert_not_reached(); 2258f63e7089SHuang Shiyuan} 2259f63e7089SHuang Shiyuan 2260f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) 2261f63e7089SHuang Shiyuan{ 2262f63e7089SHuang Shiyuan switch (opc) { 2263*5a63f599STANG Tiancheng case INDEX_op_add_vec: 2264*5a63f599STANG Tiancheng case INDEX_op_sub_vec: 2265*5a63f599STANG Tiancheng case INDEX_op_and_vec: 2266*5a63f599STANG Tiancheng case INDEX_op_or_vec: 2267*5a63f599STANG Tiancheng case INDEX_op_xor_vec: 2268*5a63f599STANG Tiancheng case INDEX_op_not_vec: 2269*5a63f599STANG Tiancheng return 1; 2270f63e7089SHuang Shiyuan default: 2271f63e7089SHuang Shiyuan return 0; 2272f63e7089SHuang Shiyuan } 2273f63e7089SHuang Shiyuan} 2274f63e7089SHuang Shiyuan 2275665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) 2276139c1837SPaolo Bonzini{ 2277139c1837SPaolo Bonzini switch (op) { 2278139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 2279665be288SRichard Henderson return C_O0_I1(r); 2280139c1837SPaolo Bonzini 2281139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 2282139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 2283139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 2284139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 2285139c1837SPaolo Bonzini case INDEX_op_ld_i32: 2286139c1837SPaolo Bonzini case INDEX_op_not_i32: 2287139c1837SPaolo Bonzini case INDEX_op_neg_i32: 2288139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 2289139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 2290139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 2291139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 2292139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 2293139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 2294139c1837SPaolo Bonzini case INDEX_op_ld_i64: 2295139c1837SPaolo Bonzini case INDEX_op_not_i64: 2296139c1837SPaolo Bonzini case INDEX_op_neg_i64: 2297139c1837SPaolo Bonzini case INDEX_op_ext8u_i32: 2298139c1837SPaolo Bonzini case INDEX_op_ext8u_i64: 2299139c1837SPaolo Bonzini case INDEX_op_ext16u_i32: 2300139c1837SPaolo Bonzini case INDEX_op_ext16u_i64: 2301139c1837SPaolo Bonzini case INDEX_op_ext32u_i64: 2302139c1837SPaolo Bonzini case INDEX_op_extu_i32_i64: 2303139c1837SPaolo Bonzini case INDEX_op_ext8s_i32: 2304139c1837SPaolo Bonzini case INDEX_op_ext8s_i64: 2305139c1837SPaolo Bonzini case INDEX_op_ext16s_i32: 2306139c1837SPaolo Bonzini case INDEX_op_ext16s_i64: 2307139c1837SPaolo Bonzini case INDEX_op_ext32s_i64: 2308139c1837SPaolo Bonzini case INDEX_op_extrl_i64_i32: 2309139c1837SPaolo Bonzini case INDEX_op_extrh_i64_i32: 2310139c1837SPaolo Bonzini case INDEX_op_ext_i32_i64: 23117b4d5274SRichard Henderson case INDEX_op_bswap16_i32: 23127b4d5274SRichard Henderson case INDEX_op_bswap32_i32: 23137b4d5274SRichard Henderson case INDEX_op_bswap16_i64: 23147b4d5274SRichard Henderson case INDEX_op_bswap32_i64: 23157b4d5274SRichard Henderson case INDEX_op_bswap64_i64: 23160956ecdaSRichard Henderson case INDEX_op_ctpop_i32: 23170956ecdaSRichard Henderson case INDEX_op_ctpop_i64: 2318665be288SRichard Henderson return C_O1_I1(r, r); 2319139c1837SPaolo Bonzini 2320139c1837SPaolo Bonzini case INDEX_op_st8_i32: 2321139c1837SPaolo Bonzini case INDEX_op_st16_i32: 2322139c1837SPaolo Bonzini case INDEX_op_st_i32: 2323139c1837SPaolo Bonzini case INDEX_op_st8_i64: 2324139c1837SPaolo Bonzini case INDEX_op_st16_i64: 2325139c1837SPaolo Bonzini case INDEX_op_st32_i64: 2326139c1837SPaolo Bonzini case INDEX_op_st_i64: 2327665be288SRichard Henderson return C_O0_I2(rZ, r); 2328139c1837SPaolo Bonzini 2329139c1837SPaolo Bonzini case INDEX_op_add_i32: 2330139c1837SPaolo Bonzini case INDEX_op_and_i32: 2331139c1837SPaolo Bonzini case INDEX_op_or_i32: 2332139c1837SPaolo Bonzini case INDEX_op_xor_i32: 2333139c1837SPaolo Bonzini case INDEX_op_add_i64: 2334139c1837SPaolo Bonzini case INDEX_op_and_i64: 2335139c1837SPaolo Bonzini case INDEX_op_or_i64: 2336139c1837SPaolo Bonzini case INDEX_op_xor_i64: 2337f6453695SRichard Henderson case INDEX_op_setcond_i32: 2338f6453695SRichard Henderson case INDEX_op_setcond_i64: 233941e4c0a9SRichard Henderson case INDEX_op_negsetcond_i32: 234041e4c0a9SRichard Henderson case INDEX_op_negsetcond_i64: 2341665be288SRichard Henderson return C_O1_I2(r, r, rI); 2342139c1837SPaolo Bonzini 234399f4ec6eSRichard Henderson case INDEX_op_andc_i32: 234499f4ec6eSRichard Henderson case INDEX_op_andc_i64: 234599f4ec6eSRichard Henderson case INDEX_op_orc_i32: 234699f4ec6eSRichard Henderson case INDEX_op_orc_i64: 234799f4ec6eSRichard Henderson case INDEX_op_eqv_i32: 234899f4ec6eSRichard Henderson case INDEX_op_eqv_i64: 234999f4ec6eSRichard Henderson return C_O1_I2(r, r, rJ); 235099f4ec6eSRichard Henderson 2351139c1837SPaolo Bonzini case INDEX_op_sub_i32: 2352139c1837SPaolo Bonzini case INDEX_op_sub_i64: 2353665be288SRichard Henderson return C_O1_I2(r, rZ, rN); 2354139c1837SPaolo Bonzini 2355139c1837SPaolo Bonzini case INDEX_op_mul_i32: 2356139c1837SPaolo Bonzini case INDEX_op_mulsh_i32: 2357139c1837SPaolo Bonzini case INDEX_op_muluh_i32: 2358139c1837SPaolo Bonzini case INDEX_op_div_i32: 2359139c1837SPaolo Bonzini case INDEX_op_divu_i32: 2360139c1837SPaolo Bonzini case INDEX_op_rem_i32: 2361139c1837SPaolo Bonzini case INDEX_op_remu_i32: 2362139c1837SPaolo Bonzini case INDEX_op_mul_i64: 2363139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 2364139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 2365139c1837SPaolo Bonzini case INDEX_op_div_i64: 2366139c1837SPaolo Bonzini case INDEX_op_divu_i64: 2367139c1837SPaolo Bonzini case INDEX_op_rem_i64: 2368139c1837SPaolo Bonzini case INDEX_op_remu_i64: 2369665be288SRichard Henderson return C_O1_I2(r, rZ, rZ); 2370139c1837SPaolo Bonzini 2371139c1837SPaolo Bonzini case INDEX_op_shl_i32: 2372139c1837SPaolo Bonzini case INDEX_op_shr_i32: 2373139c1837SPaolo Bonzini case INDEX_op_sar_i32: 237419d016adSRichard Henderson case INDEX_op_rotl_i32: 237519d016adSRichard Henderson case INDEX_op_rotr_i32: 2376139c1837SPaolo Bonzini case INDEX_op_shl_i64: 2377139c1837SPaolo Bonzini case INDEX_op_shr_i64: 2378139c1837SPaolo Bonzini case INDEX_op_sar_i64: 237919d016adSRichard Henderson case INDEX_op_rotl_i64: 238019d016adSRichard Henderson case INDEX_op_rotr_i64: 2381665be288SRichard Henderson return C_O1_I2(r, r, ri); 2382139c1837SPaolo Bonzini 2383a30498fcSRichard Henderson case INDEX_op_clz_i32: 2384a30498fcSRichard Henderson case INDEX_op_clz_i64: 2385a30498fcSRichard Henderson case INDEX_op_ctz_i32: 2386a30498fcSRichard Henderson case INDEX_op_ctz_i64: 2387a30498fcSRichard Henderson return C_N1_I2(r, r, rM); 2388a30498fcSRichard Henderson 2389139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 2390139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 2391665be288SRichard Henderson return C_O0_I2(rZ, rZ); 2392139c1837SPaolo Bonzini 2393a18d783eSRichard Henderson case INDEX_op_movcond_i32: 2394a18d783eSRichard Henderson case INDEX_op_movcond_i64: 2395a18d783eSRichard Henderson return C_O1_I4(r, r, rI, rM, rM); 2396a18d783eSRichard Henderson 2397139c1837SPaolo Bonzini case INDEX_op_add2_i32: 2398139c1837SPaolo Bonzini case INDEX_op_add2_i64: 2399139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 2400139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 2401665be288SRichard Henderson return C_O2_I4(r, r, rZ, rZ, rM, rM); 2402139c1837SPaolo Bonzini 2403fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 2404fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 2405fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 2406fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 2407f0f43534SRichard Henderson return C_O1_I1(r, r); 2408fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 2409fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 2410fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 2411fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 2412f0f43534SRichard Henderson return C_O0_I2(rZ, r); 2413139c1837SPaolo Bonzini 2414f63e7089SHuang Shiyuan case INDEX_op_st_vec: 2415f63e7089SHuang Shiyuan return C_O0_I2(v, r); 2416d4be6ee1STANG Tiancheng case INDEX_op_dup_vec: 2417d4be6ee1STANG Tiancheng case INDEX_op_dupm_vec: 2418f63e7089SHuang Shiyuan case INDEX_op_ld_vec: 2419f63e7089SHuang Shiyuan return C_O1_I1(v, r); 2420*5a63f599STANG Tiancheng case INDEX_op_not_vec: 2421*5a63f599STANG Tiancheng return C_O1_I1(v, v); 2422*5a63f599STANG Tiancheng case INDEX_op_add_vec: 2423*5a63f599STANG Tiancheng case INDEX_op_and_vec: 2424*5a63f599STANG Tiancheng case INDEX_op_or_vec: 2425*5a63f599STANG Tiancheng case INDEX_op_xor_vec: 2426*5a63f599STANG Tiancheng return C_O1_I2(v, v, vK); 2427*5a63f599STANG Tiancheng case INDEX_op_sub_vec: 2428*5a63f599STANG Tiancheng return C_O1_I2(v, v, v); 2429139c1837SPaolo Bonzini default: 2430665be288SRichard Henderson g_assert_not_reached(); 2431139c1837SPaolo Bonzini } 2432139c1837SPaolo Bonzini} 2433139c1837SPaolo Bonzini 2434139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = { 2435139c1837SPaolo Bonzini TCG_REG_S0, /* used for the global env (TCG_AREG0) */ 2436139c1837SPaolo Bonzini TCG_REG_S1, 2437139c1837SPaolo Bonzini TCG_REG_S2, 2438139c1837SPaolo Bonzini TCG_REG_S3, 2439139c1837SPaolo Bonzini TCG_REG_S4, 2440139c1837SPaolo Bonzini TCG_REG_S5, 2441139c1837SPaolo Bonzini TCG_REG_S6, 2442139c1837SPaolo Bonzini TCG_REG_S7, 2443139c1837SPaolo Bonzini TCG_REG_S8, 2444139c1837SPaolo Bonzini TCG_REG_S9, 2445139c1837SPaolo Bonzini TCG_REG_S10, 2446139c1837SPaolo Bonzini TCG_REG_S11, 2447139c1837SPaolo Bonzini TCG_REG_RA, /* should be last for ABI compliance */ 2448139c1837SPaolo Bonzini}; 2449139c1837SPaolo Bonzini 2450139c1837SPaolo Bonzini/* Stack frame parameters. */ 2451139c1837SPaolo Bonzini#define REG_SIZE (TCG_TARGET_REG_BITS / 8) 2452139c1837SPaolo Bonzini#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) 2453139c1837SPaolo Bonzini#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) 2454139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ 2455139c1837SPaolo Bonzini + TCG_TARGET_STACK_ALIGN - 1) \ 2456139c1837SPaolo Bonzini & -TCG_TARGET_STACK_ALIGN) 2457139c1837SPaolo Bonzini#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) 2458139c1837SPaolo Bonzini 2459139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation. */ 2460139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); 2461139c1837SPaolo Bonzini 2462139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */ 2463139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s) 2464139c1837SPaolo Bonzini{ 2465139c1837SPaolo Bonzini int i; 2466139c1837SPaolo Bonzini 2467139c1837SPaolo Bonzini tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); 2468139c1837SPaolo Bonzini 2469139c1837SPaolo Bonzini /* TB prologue */ 2470139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); 2471139c1837SPaolo Bonzini for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 2472139c1837SPaolo Bonzini tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 2473139c1837SPaolo Bonzini TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 2474139c1837SPaolo Bonzini } 2475139c1837SPaolo Bonzini 24764944d359SRichard Henderson if (!tcg_use_softmmu && guest_base) { 2477139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); 2478139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); 2479cf0ed30eSRichard Henderson } 2480139c1837SPaolo Bonzini 2481139c1837SPaolo Bonzini /* Call generated code */ 2482139c1837SPaolo Bonzini tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); 2483139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); 2484139c1837SPaolo Bonzini 2485139c1837SPaolo Bonzini /* Return path for goto_ptr. Set return value to 0 */ 2486c8bc1168SRichard Henderson tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); 2487139c1837SPaolo Bonzini tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); 2488139c1837SPaolo Bonzini 2489139c1837SPaolo Bonzini /* TB epilogue */ 2490793f7381SRichard Henderson tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); 2491139c1837SPaolo Bonzini for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 2492139c1837SPaolo Bonzini tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 2493139c1837SPaolo Bonzini TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 2494139c1837SPaolo Bonzini } 2495139c1837SPaolo Bonzini 2496139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); 2497139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0); 2498139c1837SPaolo Bonzini} 2499139c1837SPaolo Bonzini 25009358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s) 25019358fbbfSRichard Henderson{ 2502f63e7089SHuang Shiyuan init_setting_vtype(s); 2503f63e7089SHuang Shiyuan} 2504f63e7089SHuang Shiyuan 2505f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype) 2506f63e7089SHuang Shiyuan{ 2507f63e7089SHuang Shiyuan unsigned long tmp; 2508f63e7089SHuang Shiyuan 2509f63e7089SHuang Shiyuan /* vsetvl tmp, zero, vtype */ 2510f63e7089SHuang Shiyuan asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype)); 2511f63e7089SHuang Shiyuan return tmp != 0; 2512f63e7089SHuang Shiyuan} 2513f63e7089SHuang Shiyuan 2514f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew) 2515f63e7089SHuang Shiyuan{ 2516f63e7089SHuang Shiyuan VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew]; 2517f63e7089SHuang Shiyuan unsigned avl = tcg_type_size(type) >> vsew; 2518f63e7089SHuang Shiyuan int lmul = type - riscv_lg2_vlenb; 2519f63e7089SHuang Shiyuan unsigned vtype = encode_vtype(true, true, vsew, lmul & 7); 2520f63e7089SHuang Shiyuan bool lmul_eq_avl = true; 2521f63e7089SHuang Shiyuan 2522f63e7089SHuang Shiyuan /* Guaranteed by Zve64x. */ 2523f63e7089SHuang Shiyuan assert(lmul < 3); 2524f63e7089SHuang Shiyuan 2525f63e7089SHuang Shiyuan /* 2526f63e7089SHuang Shiyuan * For LMUL < -3, the host vector size is so large that TYPE 2527f63e7089SHuang Shiyuan * is smaller than the minimum 1/8 fraction. 2528f63e7089SHuang Shiyuan * 2529f63e7089SHuang Shiyuan * For other fractional LMUL settings, implementations must 2530f63e7089SHuang Shiyuan * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive. 2531f63e7089SHuang Shiyuan * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32, 2532f63e7089SHuang Shiyuan * but e64 may not be supported. In other words, the hardware only 2533f63e7089SHuang Shiyuan * guarantees SEW_MIN <= SEW <= LMUL * ELEN. Check. 2534f63e7089SHuang Shiyuan */ 2535f63e7089SHuang Shiyuan if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) { 2536f63e7089SHuang Shiyuan vtype = encode_vtype(true, true, vsew, VLMUL_M1); 2537f63e7089SHuang Shiyuan lmul_eq_avl = false; 2538f63e7089SHuang Shiyuan } 2539f63e7089SHuang Shiyuan 2540f63e7089SHuang Shiyuan if (avl < 32) { 2541f63e7089SHuang Shiyuan p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype); 2542f63e7089SHuang Shiyuan } else if (lmul_eq_avl) { 2543f63e7089SHuang Shiyuan /* rd != 0 and rs1 == 0 uses vlmax */ 2544f63e7089SHuang Shiyuan p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype); 2545f63e7089SHuang Shiyuan } else { 2546f63e7089SHuang Shiyuan p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl); 2547f63e7089SHuang Shiyuan p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype); 2548f63e7089SHuang Shiyuan } 2549f63e7089SHuang Shiyuan} 2550f63e7089SHuang Shiyuan 2551f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void) 2552f63e7089SHuang Shiyuan{ 2553f63e7089SHuang Shiyuan /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */ 2554f63e7089SHuang Shiyuan QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3); 2555f63e7089SHuang Shiyuan 2556f63e7089SHuang Shiyuan for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) { 2557f63e7089SHuang Shiyuan for (MemOp e = MO_8; e <= MO_64; e++) { 2558f63e7089SHuang Shiyuan probe_frac_lmul_1(t, e); 2559f63e7089SHuang Shiyuan } 2560f63e7089SHuang Shiyuan } 25619358fbbfSRichard Henderson} 25629358fbbfSRichard Henderson 2563139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s) 2564139c1837SPaolo Bonzini{ 2565139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff; 2566139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff; 2567139c1837SPaolo Bonzini 2568f63e7089SHuang Shiyuan tcg_target_call_clobber_regs = -1; 2569139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); 2570139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); 2571139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); 2572139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); 2573139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); 2574139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); 2575139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); 2576139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); 2577139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); 2578139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); 2579139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10); 2580139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11); 2581139c1837SPaolo Bonzini 2582139c1837SPaolo Bonzini s->reserved_regs = 0; 2583139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); 2584139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); 2585139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); 2586139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); 2587139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); 2588139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); 2589139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); 2590f63e7089SHuang Shiyuan 2591f63e7089SHuang Shiyuan if (cpuinfo & CPUINFO_ZVE64X) { 2592f63e7089SHuang Shiyuan switch (riscv_lg2_vlenb) { 2593f63e7089SHuang Shiyuan case TCG_TYPE_V64: 2594f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2595f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS; 2596f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS; 2597f63e7089SHuang Shiyuan s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS); 2598f63e7089SHuang Shiyuan break; 2599f63e7089SHuang Shiyuan case TCG_TYPE_V128: 2600f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2601f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS; 2602f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS; 2603f63e7089SHuang Shiyuan s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS); 2604f63e7089SHuang Shiyuan break; 2605f63e7089SHuang Shiyuan default: 2606f63e7089SHuang Shiyuan /* Guaranteed by Zve64x. */ 2607f63e7089SHuang Shiyuan tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256); 2608f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2609f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS; 2610f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS; 2611f63e7089SHuang Shiyuan break; 2612f63e7089SHuang Shiyuan } 2613f63e7089SHuang Shiyuan tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0); 2614f63e7089SHuang Shiyuan probe_frac_lmul(); 2615f63e7089SHuang Shiyuan } 2616139c1837SPaolo Bonzini} 2617139c1837SPaolo Bonzini 2618139c1837SPaolo Bonzinitypedef struct { 2619139c1837SPaolo Bonzini DebugFrameHeader h; 2620139c1837SPaolo Bonzini uint8_t fde_def_cfa[4]; 2621139c1837SPaolo Bonzini uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; 2622139c1837SPaolo Bonzini} DebugFrame; 2623139c1837SPaolo Bonzini 2624139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV 2625139c1837SPaolo Bonzini 2626139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = { 2627139c1837SPaolo Bonzini .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ 2628139c1837SPaolo Bonzini .h.cie.id = -1, 2629139c1837SPaolo Bonzini .h.cie.version = 1, 2630139c1837SPaolo Bonzini .h.cie.code_align = 1, 2631139c1837SPaolo Bonzini .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ 2632139c1837SPaolo Bonzini .h.cie.return_column = TCG_REG_RA, 2633139c1837SPaolo Bonzini 2634139c1837SPaolo Bonzini /* Total FDE size does not include the "len" member. */ 2635139c1837SPaolo Bonzini .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), 2636139c1837SPaolo Bonzini 2637139c1837SPaolo Bonzini .fde_def_cfa = { 2638139c1837SPaolo Bonzini 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ 2639139c1837SPaolo Bonzini (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ 2640139c1837SPaolo Bonzini (FRAME_SIZE >> 7) 2641139c1837SPaolo Bonzini }, 2642139c1837SPaolo Bonzini .fde_reg_ofs = { 2643139c1837SPaolo Bonzini 0x80 + 9, 12, /* DW_CFA_offset, s1, -96 */ 2644139c1837SPaolo Bonzini 0x80 + 18, 11, /* DW_CFA_offset, s2, -88 */ 2645139c1837SPaolo Bonzini 0x80 + 19, 10, /* DW_CFA_offset, s3, -80 */ 2646139c1837SPaolo Bonzini 0x80 + 20, 9, /* DW_CFA_offset, s4, -72 */ 2647139c1837SPaolo Bonzini 0x80 + 21, 8, /* DW_CFA_offset, s5, -64 */ 2648139c1837SPaolo Bonzini 0x80 + 22, 7, /* DW_CFA_offset, s6, -56 */ 2649139c1837SPaolo Bonzini 0x80 + 23, 6, /* DW_CFA_offset, s7, -48 */ 2650139c1837SPaolo Bonzini 0x80 + 24, 5, /* DW_CFA_offset, s8, -40 */ 2651139c1837SPaolo Bonzini 0x80 + 25, 4, /* DW_CFA_offset, s9, -32 */ 2652139c1837SPaolo Bonzini 0x80 + 26, 3, /* DW_CFA_offset, s10, -24 */ 2653139c1837SPaolo Bonzini 0x80 + 27, 2, /* DW_CFA_offset, s11, -16 */ 2654139c1837SPaolo Bonzini 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ 2655139c1837SPaolo Bonzini } 2656139c1837SPaolo Bonzini}; 2657139c1837SPaolo Bonzini 2658755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size) 2659139c1837SPaolo Bonzini{ 2660139c1837SPaolo Bonzini tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); 2661139c1837SPaolo Bonzini} 2662