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 1145a63f599STANG Tiancheng#define TCG_CT_CONST_S5 0x2000 115a31768c0STANG Tiancheng#define TCG_CT_CONST_CMP_VI 0x4000 116139c1837SPaolo Bonzini 117fc63a4c5SRichard Henderson#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) 118f63e7089SHuang Shiyuan#define ALL_VECTOR_REGS MAKE_64BIT_MASK(32, 32) 119f63e7089SHuang Shiyuan#define ALL_DVECTOR_REG_GROUPS 0x5555555500000000 120f63e7089SHuang Shiyuan#define ALL_QVECTOR_REG_GROUPS 0x1111111100000000 121fc63a4c5SRichard Henderson 122aeb6326eSRichard Henderson#define sextreg sextract64 123139c1837SPaolo Bonzini 124139c1837SPaolo Bonzini/* 125139c1837SPaolo Bonzini * RISC-V Base ISA opcodes (IM) 126139c1837SPaolo Bonzini */ 127139c1837SPaolo Bonzini 128f63e7089SHuang Shiyuan#define V_OPIVV (0x0 << 12) 129f63e7089SHuang Shiyuan#define V_OPFVV (0x1 << 12) 130f63e7089SHuang Shiyuan#define V_OPMVV (0x2 << 12) 131f63e7089SHuang Shiyuan#define V_OPIVI (0x3 << 12) 132f63e7089SHuang Shiyuan#define V_OPIVX (0x4 << 12) 133f63e7089SHuang Shiyuan#define V_OPFVF (0x5 << 12) 134f63e7089SHuang Shiyuan#define V_OPMVX (0x6 << 12) 135f63e7089SHuang Shiyuan#define V_OPCFG (0x7 << 12) 136f63e7089SHuang Shiyuan 137f63e7089SHuang Shiyuan/* NF <= 7 && NF >= 0 */ 138f63e7089SHuang Shiyuan#define V_NF(x) (x << 29) 139f63e7089SHuang Shiyuan#define V_UNIT_STRIDE (0x0 << 20) 140f63e7089SHuang Shiyuan#define V_UNIT_STRIDE_WHOLE_REG (0x8 << 20) 141f63e7089SHuang Shiyuan 142f63e7089SHuang Shiyuantypedef enum { 143f63e7089SHuang Shiyuan VLMUL_M1 = 0, /* LMUL=1 */ 144f63e7089SHuang Shiyuan VLMUL_M2, /* LMUL=2 */ 145f63e7089SHuang Shiyuan VLMUL_M4, /* LMUL=4 */ 146f63e7089SHuang Shiyuan VLMUL_M8, /* LMUL=8 */ 147f63e7089SHuang Shiyuan VLMUL_RESERVED, 148f63e7089SHuang Shiyuan VLMUL_MF8, /* LMUL=1/8 */ 149f63e7089SHuang Shiyuan VLMUL_MF4, /* LMUL=1/4 */ 150f63e7089SHuang Shiyuan VLMUL_MF2, /* LMUL=1/2 */ 151f63e7089SHuang Shiyuan} RISCVVlmul; 152f63e7089SHuang Shiyuan 153139c1837SPaolo Bonzinitypedef enum { 154139c1837SPaolo Bonzini OPC_ADD = 0x33, 155139c1837SPaolo Bonzini OPC_ADDI = 0x13, 156139c1837SPaolo Bonzini OPC_AND = 0x7033, 157139c1837SPaolo Bonzini OPC_ANDI = 0x7013, 158139c1837SPaolo Bonzini OPC_AUIPC = 0x17, 159139c1837SPaolo Bonzini OPC_BEQ = 0x63, 160139c1837SPaolo Bonzini OPC_BGE = 0x5063, 161139c1837SPaolo Bonzini OPC_BGEU = 0x7063, 162139c1837SPaolo Bonzini OPC_BLT = 0x4063, 163139c1837SPaolo Bonzini OPC_BLTU = 0x6063, 164139c1837SPaolo Bonzini OPC_BNE = 0x1063, 165139c1837SPaolo Bonzini OPC_DIV = 0x2004033, 166139c1837SPaolo Bonzini OPC_DIVU = 0x2005033, 167139c1837SPaolo Bonzini OPC_JAL = 0x6f, 168139c1837SPaolo Bonzini OPC_JALR = 0x67, 169139c1837SPaolo Bonzini OPC_LB = 0x3, 170139c1837SPaolo Bonzini OPC_LBU = 0x4003, 171139c1837SPaolo Bonzini OPC_LD = 0x3003, 172139c1837SPaolo Bonzini OPC_LH = 0x1003, 173139c1837SPaolo Bonzini OPC_LHU = 0x5003, 174139c1837SPaolo Bonzini OPC_LUI = 0x37, 175139c1837SPaolo Bonzini OPC_LW = 0x2003, 176139c1837SPaolo Bonzini OPC_LWU = 0x6003, 177139c1837SPaolo Bonzini OPC_MUL = 0x2000033, 178139c1837SPaolo Bonzini OPC_MULH = 0x2001033, 179139c1837SPaolo Bonzini OPC_MULHSU = 0x2002033, 180139c1837SPaolo Bonzini OPC_MULHU = 0x2003033, 181139c1837SPaolo Bonzini OPC_OR = 0x6033, 182139c1837SPaolo Bonzini OPC_ORI = 0x6013, 183139c1837SPaolo Bonzini OPC_REM = 0x2006033, 184139c1837SPaolo Bonzini OPC_REMU = 0x2007033, 185139c1837SPaolo Bonzini OPC_SB = 0x23, 186139c1837SPaolo Bonzini OPC_SD = 0x3023, 187139c1837SPaolo Bonzini OPC_SH = 0x1023, 188139c1837SPaolo Bonzini OPC_SLL = 0x1033, 189139c1837SPaolo Bonzini OPC_SLLI = 0x1013, 190139c1837SPaolo Bonzini OPC_SLT = 0x2033, 191139c1837SPaolo Bonzini OPC_SLTI = 0x2013, 192139c1837SPaolo Bonzini OPC_SLTIU = 0x3013, 193139c1837SPaolo Bonzini OPC_SLTU = 0x3033, 194139c1837SPaolo Bonzini OPC_SRA = 0x40005033, 195139c1837SPaolo Bonzini OPC_SRAI = 0x40005013, 196139c1837SPaolo Bonzini OPC_SRL = 0x5033, 197139c1837SPaolo Bonzini OPC_SRLI = 0x5013, 198139c1837SPaolo Bonzini OPC_SUB = 0x40000033, 199139c1837SPaolo Bonzini OPC_SW = 0x2023, 200139c1837SPaolo Bonzini OPC_XOR = 0x4033, 201139c1837SPaolo Bonzini OPC_XORI = 0x4013, 202139c1837SPaolo Bonzini 203139c1837SPaolo Bonzini OPC_ADDIW = 0x1b, 204139c1837SPaolo Bonzini OPC_ADDW = 0x3b, 205139c1837SPaolo Bonzini OPC_DIVUW = 0x200503b, 206139c1837SPaolo Bonzini OPC_DIVW = 0x200403b, 207139c1837SPaolo Bonzini OPC_MULW = 0x200003b, 208139c1837SPaolo Bonzini OPC_REMUW = 0x200703b, 209139c1837SPaolo Bonzini OPC_REMW = 0x200603b, 210139c1837SPaolo Bonzini OPC_SLLIW = 0x101b, 211139c1837SPaolo Bonzini OPC_SLLW = 0x103b, 212139c1837SPaolo Bonzini OPC_SRAIW = 0x4000501b, 213139c1837SPaolo Bonzini OPC_SRAW = 0x4000503b, 214139c1837SPaolo Bonzini OPC_SRLIW = 0x501b, 215139c1837SPaolo Bonzini OPC_SRLW = 0x503b, 216139c1837SPaolo Bonzini OPC_SUBW = 0x4000003b, 217139c1837SPaolo Bonzini 218139c1837SPaolo Bonzini OPC_FENCE = 0x0000000f, 2199ae958e4SRichard Henderson OPC_NOP = OPC_ADDI, /* nop = addi r0,r0,0 */ 2209e3e0bc6SRichard Henderson 2219e3e0bc6SRichard Henderson /* Zba: Bit manipulation extension, address generation */ 2229e3e0bc6SRichard Henderson OPC_ADD_UW = 0x0800003b, 2239e3e0bc6SRichard Henderson 2244daad8d9SMichael Tokarev /* Zbb: Bit manipulation extension, basic bit manipulation */ 2259e3e0bc6SRichard Henderson OPC_ANDN = 0x40007033, 2269e3e0bc6SRichard Henderson OPC_CLZ = 0x60001013, 2279e3e0bc6SRichard Henderson OPC_CLZW = 0x6000101b, 2289e3e0bc6SRichard Henderson OPC_CPOP = 0x60201013, 2299e3e0bc6SRichard Henderson OPC_CPOPW = 0x6020101b, 2309e3e0bc6SRichard Henderson OPC_CTZ = 0x60101013, 2319e3e0bc6SRichard Henderson OPC_CTZW = 0x6010101b, 2329e3e0bc6SRichard Henderson OPC_ORN = 0x40006033, 2339e3e0bc6SRichard Henderson OPC_REV8 = 0x6b805013, 2349e3e0bc6SRichard Henderson OPC_ROL = 0x60001033, 2359e3e0bc6SRichard Henderson OPC_ROLW = 0x6000103b, 2369e3e0bc6SRichard Henderson OPC_ROR = 0x60005033, 2379e3e0bc6SRichard Henderson OPC_RORW = 0x6000503b, 2389e3e0bc6SRichard Henderson OPC_RORI = 0x60005013, 2399e3e0bc6SRichard Henderson OPC_RORIW = 0x6000501b, 2409e3e0bc6SRichard Henderson OPC_SEXT_B = 0x60401013, 2419e3e0bc6SRichard Henderson OPC_SEXT_H = 0x60501013, 2429e3e0bc6SRichard Henderson OPC_XNOR = 0x40004033, 2439e3e0bc6SRichard Henderson OPC_ZEXT_H = 0x0800403b, 2449e3e0bc6SRichard Henderson 2459e3e0bc6SRichard Henderson /* Zicond: integer conditional operations */ 2469e3e0bc6SRichard Henderson OPC_CZERO_EQZ = 0x0e005033, 2479e3e0bc6SRichard Henderson OPC_CZERO_NEZ = 0x0e007033, 248f63e7089SHuang Shiyuan 249f63e7089SHuang Shiyuan /* V: Vector extension 1.0 */ 250f63e7089SHuang Shiyuan OPC_VSETVLI = 0x57 | V_OPCFG, 251f63e7089SHuang Shiyuan OPC_VSETIVLI = 0xc0000057 | V_OPCFG, 252f63e7089SHuang Shiyuan OPC_VSETVL = 0x80000057 | V_OPCFG, 253f63e7089SHuang Shiyuan 254f63e7089SHuang Shiyuan OPC_VLE8_V = 0x7 | V_UNIT_STRIDE, 255f63e7089SHuang Shiyuan OPC_VLE16_V = 0x5007 | V_UNIT_STRIDE, 256f63e7089SHuang Shiyuan OPC_VLE32_V = 0x6007 | V_UNIT_STRIDE, 257f63e7089SHuang Shiyuan OPC_VLE64_V = 0x7007 | V_UNIT_STRIDE, 258f63e7089SHuang Shiyuan OPC_VSE8_V = 0x27 | V_UNIT_STRIDE, 259f63e7089SHuang Shiyuan OPC_VSE16_V = 0x5027 | V_UNIT_STRIDE, 260f63e7089SHuang Shiyuan OPC_VSE32_V = 0x6027 | V_UNIT_STRIDE, 261f63e7089SHuang Shiyuan OPC_VSE64_V = 0x7027 | V_UNIT_STRIDE, 262f63e7089SHuang Shiyuan 263f63e7089SHuang Shiyuan OPC_VL1RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0), 264f63e7089SHuang Shiyuan OPC_VL2RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1), 265f63e7089SHuang Shiyuan OPC_VL4RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3), 266f63e7089SHuang Shiyuan OPC_VL8RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7), 267f63e7089SHuang Shiyuan 268f63e7089SHuang Shiyuan OPC_VS1R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0), 269f63e7089SHuang Shiyuan OPC_VS2R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1), 270f63e7089SHuang Shiyuan OPC_VS4R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3), 271f63e7089SHuang Shiyuan OPC_VS8R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7), 272d4be6ee1STANG Tiancheng 273a31768c0STANG Tiancheng OPC_VMERGE_VIM = 0x5c000057 | V_OPIVI, 274a31768c0STANG Tiancheng OPC_VMERGE_VVM = 0x5c000057 | V_OPIVV, 275a31768c0STANG Tiancheng 2765a63f599STANG Tiancheng OPC_VADD_VV = 0x57 | V_OPIVV, 2775a63f599STANG Tiancheng OPC_VADD_VI = 0x57 | V_OPIVI, 2785a63f599STANG Tiancheng OPC_VSUB_VV = 0x8000057 | V_OPIVV, 279*c283c074STANG Tiancheng OPC_VRSUB_VI = 0xc000057 | V_OPIVI, 2805a63f599STANG Tiancheng OPC_VAND_VV = 0x24000057 | V_OPIVV, 2815a63f599STANG Tiancheng OPC_VAND_VI = 0x24000057 | V_OPIVI, 2825a63f599STANG Tiancheng OPC_VOR_VV = 0x28000057 | V_OPIVV, 2835a63f599STANG Tiancheng OPC_VOR_VI = 0x28000057 | V_OPIVI, 2845a63f599STANG Tiancheng OPC_VXOR_VV = 0x2c000057 | V_OPIVV, 2855a63f599STANG Tiancheng OPC_VXOR_VI = 0x2c000057 | V_OPIVI, 2865a63f599STANG Tiancheng 287a31768c0STANG Tiancheng OPC_VMSEQ_VV = 0x60000057 | V_OPIVV, 288a31768c0STANG Tiancheng OPC_VMSEQ_VI = 0x60000057 | V_OPIVI, 289a31768c0STANG Tiancheng OPC_VMSEQ_VX = 0x60000057 | V_OPIVX, 290a31768c0STANG Tiancheng OPC_VMSNE_VV = 0x64000057 | V_OPIVV, 291a31768c0STANG Tiancheng OPC_VMSNE_VI = 0x64000057 | V_OPIVI, 292a31768c0STANG Tiancheng OPC_VMSNE_VX = 0x64000057 | V_OPIVX, 293a31768c0STANG Tiancheng 294a31768c0STANG Tiancheng OPC_VMSLTU_VV = 0x68000057 | V_OPIVV, 295a31768c0STANG Tiancheng OPC_VMSLTU_VX = 0x68000057 | V_OPIVX, 296a31768c0STANG Tiancheng OPC_VMSLT_VV = 0x6c000057 | V_OPIVV, 297a31768c0STANG Tiancheng OPC_VMSLT_VX = 0x6c000057 | V_OPIVX, 298a31768c0STANG Tiancheng OPC_VMSLEU_VV = 0x70000057 | V_OPIVV, 299a31768c0STANG Tiancheng OPC_VMSLEU_VX = 0x70000057 | V_OPIVX, 300a31768c0STANG Tiancheng OPC_VMSLE_VV = 0x74000057 | V_OPIVV, 301a31768c0STANG Tiancheng OPC_VMSLE_VX = 0x74000057 | V_OPIVX, 302a31768c0STANG Tiancheng 303a31768c0STANG Tiancheng OPC_VMSLEU_VI = 0x70000057 | V_OPIVI, 304a31768c0STANG Tiancheng OPC_VMSLE_VI = 0x74000057 | V_OPIVI, 305a31768c0STANG Tiancheng OPC_VMSGTU_VI = 0x78000057 | V_OPIVI, 306a31768c0STANG Tiancheng OPC_VMSGTU_VX = 0x78000057 | V_OPIVX, 307a31768c0STANG Tiancheng OPC_VMSGT_VI = 0x7c000057 | V_OPIVI, 308a31768c0STANG Tiancheng OPC_VMSGT_VX = 0x7c000057 | V_OPIVX, 309a31768c0STANG Tiancheng 310d4be6ee1STANG Tiancheng OPC_VMV_V_V = 0x5e000057 | V_OPIVV, 311d4be6ee1STANG Tiancheng OPC_VMV_V_I = 0x5e000057 | V_OPIVI, 312d4be6ee1STANG Tiancheng OPC_VMV_V_X = 0x5e000057 | V_OPIVX, 313d4be6ee1STANG Tiancheng 314d4be6ee1STANG Tiancheng OPC_VMVNR_V = 0x9e000057 | V_OPIVI, 315139c1837SPaolo Bonzini} RISCVInsn; 316139c1837SPaolo Bonzini 317a31768c0STANG Tianchengstatic const struct { 318a31768c0STANG Tiancheng RISCVInsn op; 319a31768c0STANG Tiancheng bool swap; 320a31768c0STANG Tiancheng} tcg_cmpcond_to_rvv_vv[] = { 321a31768c0STANG Tiancheng [TCG_COND_EQ] = { OPC_VMSEQ_VV, false }, 322a31768c0STANG Tiancheng [TCG_COND_NE] = { OPC_VMSNE_VV, false }, 323a31768c0STANG Tiancheng [TCG_COND_LT] = { OPC_VMSLT_VV, false }, 324a31768c0STANG Tiancheng [TCG_COND_GE] = { OPC_VMSLE_VV, true }, 325a31768c0STANG Tiancheng [TCG_COND_GT] = { OPC_VMSLT_VV, true }, 326a31768c0STANG Tiancheng [TCG_COND_LE] = { OPC_VMSLE_VV, false }, 327a31768c0STANG Tiancheng [TCG_COND_LTU] = { OPC_VMSLTU_VV, false }, 328a31768c0STANG Tiancheng [TCG_COND_GEU] = { OPC_VMSLEU_VV, true }, 329a31768c0STANG Tiancheng [TCG_COND_GTU] = { OPC_VMSLTU_VV, true }, 330a31768c0STANG Tiancheng [TCG_COND_LEU] = { OPC_VMSLEU_VV, false } 331a31768c0STANG Tiancheng}; 332a31768c0STANG Tiancheng 333a31768c0STANG Tianchengstatic const struct { 334a31768c0STANG Tiancheng RISCVInsn op; 335a31768c0STANG Tiancheng int min; 336a31768c0STANG Tiancheng int max; 337a31768c0STANG Tiancheng bool adjust; 338a31768c0STANG Tiancheng} tcg_cmpcond_to_rvv_vi[] = { 339a31768c0STANG Tiancheng [TCG_COND_EQ] = { OPC_VMSEQ_VI, -16, 15, false }, 340a31768c0STANG Tiancheng [TCG_COND_NE] = { OPC_VMSNE_VI, -16, 15, false }, 341a31768c0STANG Tiancheng [TCG_COND_GT] = { OPC_VMSGT_VI, -16, 15, false }, 342a31768c0STANG Tiancheng [TCG_COND_LE] = { OPC_VMSLE_VI, -16, 15, false }, 343a31768c0STANG Tiancheng [TCG_COND_LT] = { OPC_VMSLE_VI, -15, 16, true }, 344a31768c0STANG Tiancheng [TCG_COND_GE] = { OPC_VMSGT_VI, -15, 16, true }, 345a31768c0STANG Tiancheng [TCG_COND_LEU] = { OPC_VMSLEU_VI, 0, 15, false }, 346a31768c0STANG Tiancheng [TCG_COND_GTU] = { OPC_VMSGTU_VI, 0, 15, false }, 347a31768c0STANG Tiancheng [TCG_COND_LTU] = { OPC_VMSLEU_VI, 1, 16, true }, 348a31768c0STANG Tiancheng [TCG_COND_GEU] = { OPC_VMSGTU_VI, 1, 16, true }, 349a31768c0STANG Tiancheng}; 350a31768c0STANG Tiancheng 351a31768c0STANG Tiancheng/* test if a constant matches the constraint */ 352a31768c0STANG Tianchengstatic bool tcg_target_const_match(int64_t val, int ct, 353a31768c0STANG Tiancheng TCGType type, TCGCond cond, int vece) 354a31768c0STANG Tiancheng{ 355a31768c0STANG Tiancheng if (ct & TCG_CT_CONST) { 356a31768c0STANG Tiancheng return 1; 357a31768c0STANG Tiancheng } 358a31768c0STANG Tiancheng if ((ct & TCG_CT_CONST_ZERO) && val == 0) { 359a31768c0STANG Tiancheng return 1; 360a31768c0STANG Tiancheng } 361a31768c0STANG Tiancheng if (type >= TCG_TYPE_V64) { 362a31768c0STANG Tiancheng /* Val is replicated by VECE; extract the highest element. */ 363a31768c0STANG Tiancheng val >>= (-8 << vece) & 63; 364a31768c0STANG Tiancheng } 365a31768c0STANG Tiancheng /* 366a31768c0STANG Tiancheng * Sign extended from 12 bits: [-0x800, 0x7ff]. 367a31768c0STANG Tiancheng * Used for most arithmetic, as this is the isa field. 368a31768c0STANG Tiancheng */ 369a31768c0STANG Tiancheng if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) { 370a31768c0STANG Tiancheng return 1; 371a31768c0STANG Tiancheng } 372a31768c0STANG Tiancheng /* 373a31768c0STANG Tiancheng * Sign extended from 12 bits, negated: [-0x7ff, 0x800]. 374a31768c0STANG Tiancheng * Used for subtraction, where a constant must be handled by ADDI. 375a31768c0STANG Tiancheng */ 376a31768c0STANG Tiancheng if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) { 377a31768c0STANG Tiancheng return 1; 378a31768c0STANG Tiancheng } 379a31768c0STANG Tiancheng /* 380a31768c0STANG Tiancheng * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff]. 381a31768c0STANG Tiancheng * Used by addsub2 and movcond, which may need the negative value, 382a31768c0STANG Tiancheng * and requires the modified constant to be representable. 383a31768c0STANG Tiancheng */ 384a31768c0STANG Tiancheng if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) { 385a31768c0STANG Tiancheng return 1; 386a31768c0STANG Tiancheng } 387a31768c0STANG Tiancheng /* 388a31768c0STANG Tiancheng * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff]. 389a31768c0STANG Tiancheng * Used to map ANDN back to ANDI, etc. 390a31768c0STANG Tiancheng */ 391a31768c0STANG Tiancheng if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) { 392a31768c0STANG Tiancheng return 1; 393a31768c0STANG Tiancheng } 394a31768c0STANG Tiancheng /* 395a31768c0STANG Tiancheng * Sign extended from 5 bits: [-0x10, 0x0f]. 396a31768c0STANG Tiancheng * Used for vector-immediate. 397a31768c0STANG Tiancheng */ 398a31768c0STANG Tiancheng if ((ct & TCG_CT_CONST_S5) && val >= -0x10 && val <= 0x0f) { 399a31768c0STANG Tiancheng return 1; 400a31768c0STANG Tiancheng } 401a31768c0STANG Tiancheng /* 402a31768c0STANG Tiancheng * Used for vector compare OPIVI instructions. 403a31768c0STANG Tiancheng */ 404a31768c0STANG Tiancheng if ((ct & TCG_CT_CONST_CMP_VI) && 405a31768c0STANG Tiancheng val >= tcg_cmpcond_to_rvv_vi[cond].min && 406a31768c0STANG Tiancheng val <= tcg_cmpcond_to_rvv_vi[cond].max) { 407a31768c0STANG Tiancheng return true; 408a31768c0STANG Tiancheng } 409a31768c0STANG Tiancheng return 0; 410a31768c0STANG Tiancheng} 411a31768c0STANG Tiancheng 412139c1837SPaolo Bonzini/* 413139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC) 414139c1837SPaolo Bonzini */ 415139c1837SPaolo Bonzini 416139c1837SPaolo Bonzini/* Type-R */ 417139c1837SPaolo Bonzini 418139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2) 419139c1837SPaolo Bonzini{ 420139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20; 421139c1837SPaolo Bonzini} 422139c1837SPaolo Bonzini 423139c1837SPaolo Bonzini/* Type-I */ 424139c1837SPaolo Bonzini 425139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm) 426139c1837SPaolo Bonzini{ 427139c1837SPaolo Bonzini return (imm & 0xfff) << 20; 428139c1837SPaolo Bonzini} 429139c1837SPaolo Bonzini 430139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm) 431139c1837SPaolo Bonzini{ 432139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm); 433139c1837SPaolo Bonzini} 434139c1837SPaolo Bonzini 435139c1837SPaolo Bonzini/* Type-S */ 436139c1837SPaolo Bonzini 437139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm) 438139c1837SPaolo Bonzini{ 439139c1837SPaolo Bonzini int32_t ret = 0; 440139c1837SPaolo Bonzini 441139c1837SPaolo Bonzini ret |= (imm & 0xFE0) << 20; 442139c1837SPaolo Bonzini ret |= (imm & 0x1F) << 7; 443139c1837SPaolo Bonzini 444139c1837SPaolo Bonzini return ret; 445139c1837SPaolo Bonzini} 446139c1837SPaolo Bonzini 447139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) 448139c1837SPaolo Bonzini{ 449139c1837SPaolo Bonzini return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm); 450139c1837SPaolo Bonzini} 451139c1837SPaolo Bonzini 452139c1837SPaolo Bonzini/* Type-SB */ 453139c1837SPaolo Bonzini 454139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm) 455139c1837SPaolo Bonzini{ 456139c1837SPaolo Bonzini int32_t ret = 0; 457139c1837SPaolo Bonzini 458139c1837SPaolo Bonzini ret |= (imm & 0x1000) << 19; 459139c1837SPaolo Bonzini ret |= (imm & 0x7e0) << 20; 460139c1837SPaolo Bonzini ret |= (imm & 0x1e) << 7; 461139c1837SPaolo Bonzini ret |= (imm & 0x800) >> 4; 462139c1837SPaolo Bonzini 463139c1837SPaolo Bonzini return ret; 464139c1837SPaolo Bonzini} 465139c1837SPaolo Bonzini 466139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) 467139c1837SPaolo Bonzini{ 468139c1837SPaolo Bonzini return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm); 469139c1837SPaolo Bonzini} 470139c1837SPaolo Bonzini 471139c1837SPaolo Bonzini/* Type-U */ 472139c1837SPaolo Bonzini 473139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm) 474139c1837SPaolo Bonzini{ 475139c1837SPaolo Bonzini return imm & 0xfffff000; 476139c1837SPaolo Bonzini} 477139c1837SPaolo Bonzini 478139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm) 479139c1837SPaolo Bonzini{ 480139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | encode_uimm20(imm); 481139c1837SPaolo Bonzini} 482139c1837SPaolo Bonzini 483139c1837SPaolo Bonzini/* Type-UJ */ 484139c1837SPaolo Bonzini 485139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm) 486139c1837SPaolo Bonzini{ 487139c1837SPaolo Bonzini int32_t ret = 0; 488139c1837SPaolo Bonzini 489139c1837SPaolo Bonzini ret |= (imm & 0x0007fe) << (21 - 1); 490139c1837SPaolo Bonzini ret |= (imm & 0x000800) << (20 - 11); 491139c1837SPaolo Bonzini ret |= (imm & 0x0ff000) << (12 - 12); 492139c1837SPaolo Bonzini ret |= (imm & 0x100000) << (31 - 20); 493139c1837SPaolo Bonzini 494139c1837SPaolo Bonzini return ret; 495139c1837SPaolo Bonzini} 496139c1837SPaolo Bonzini 497139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm) 498139c1837SPaolo Bonzini{ 499139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm); 500139c1837SPaolo Bonzini} 501139c1837SPaolo Bonzini 502d4be6ee1STANG Tiancheng 503d4be6ee1STANG Tiancheng/* Type-OPIVI */ 504d4be6ee1STANG Tiancheng 505d4be6ee1STANG Tianchengstatic int32_t encode_vi(RISCVInsn opc, TCGReg rd, int32_t imm, 506d4be6ee1STANG Tiancheng TCGReg vs2, bool vm) 507d4be6ee1STANG Tiancheng{ 508d4be6ee1STANG Tiancheng return opc | (rd & 0x1f) << 7 | (imm & 0x1f) << 15 | 509d4be6ee1STANG Tiancheng (vs2 & 0x1f) << 20 | (vm << 25); 510d4be6ee1STANG Tiancheng} 511d4be6ee1STANG Tiancheng 512f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */ 513f63e7089SHuang Shiyuan 514f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1, 515f63e7089SHuang Shiyuan TCGReg s2, bool vm) 516f63e7089SHuang Shiyuan{ 517f63e7089SHuang Shiyuan return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 | 518f63e7089SHuang Shiyuan (s2 & 0x1f) << 20 | (vm << 25); 519f63e7089SHuang Shiyuan} 520f63e7089SHuang Shiyuan 521f63e7089SHuang Shiyuan/* Vector vtype */ 522f63e7089SHuang Shiyuan 523f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma, 524f63e7089SHuang Shiyuan MemOp vsew, RISCVVlmul vlmul) 525f63e7089SHuang Shiyuan{ 526f63e7089SHuang Shiyuan return vma << 7 | vta << 6 | vsew << 3 | vlmul; 527f63e7089SHuang Shiyuan} 528f63e7089SHuang Shiyuan 529f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd, 530f63e7089SHuang Shiyuan TCGArg rs1, uint32_t vtype) 531f63e7089SHuang Shiyuan{ 532f63e7089SHuang Shiyuan return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20; 533f63e7089SHuang Shiyuan} 534f63e7089SHuang Shiyuan 535f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd, 536f63e7089SHuang Shiyuan uint32_t uimm, uint32_t vtype) 537f63e7089SHuang Shiyuan{ 538f63e7089SHuang Shiyuan return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20; 539f63e7089SHuang Shiyuan} 540f63e7089SHuang Shiyuan 541139c1837SPaolo Bonzini/* 542139c1837SPaolo Bonzini * RISC-V instruction emitters 543139c1837SPaolo Bonzini */ 544139c1837SPaolo Bonzini 545139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc, 546139c1837SPaolo Bonzini TCGReg rd, TCGReg rs1, TCGReg rs2) 547139c1837SPaolo Bonzini{ 548139c1837SPaolo Bonzini tcg_out32(s, encode_r(opc, rd, rs1, rs2)); 549139c1837SPaolo Bonzini} 550139c1837SPaolo Bonzini 551139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc, 552139c1837SPaolo Bonzini TCGReg rd, TCGReg rs1, TCGArg imm) 553139c1837SPaolo Bonzini{ 554139c1837SPaolo Bonzini tcg_out32(s, encode_i(opc, rd, rs1, imm)); 555139c1837SPaolo Bonzini} 556139c1837SPaolo Bonzini 557139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc, 558139c1837SPaolo Bonzini TCGReg rs1, TCGReg rs2, uint32_t imm) 559139c1837SPaolo Bonzini{ 560139c1837SPaolo Bonzini tcg_out32(s, encode_s(opc, rs1, rs2, imm)); 561139c1837SPaolo Bonzini} 562139c1837SPaolo Bonzini 563139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc, 564139c1837SPaolo Bonzini TCGReg rs1, TCGReg rs2, uint32_t imm) 565139c1837SPaolo Bonzini{ 566139c1837SPaolo Bonzini tcg_out32(s, encode_sb(opc, rs1, rs2, imm)); 567139c1837SPaolo Bonzini} 568139c1837SPaolo Bonzini 569139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc, 570139c1837SPaolo Bonzini TCGReg rd, uint32_t imm) 571139c1837SPaolo Bonzini{ 572139c1837SPaolo Bonzini tcg_out32(s, encode_u(opc, rd, imm)); 573139c1837SPaolo Bonzini} 574139c1837SPaolo Bonzini 575139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc, 576139c1837SPaolo Bonzini TCGReg rd, uint32_t imm) 577139c1837SPaolo Bonzini{ 578139c1837SPaolo Bonzini tcg_out32(s, encode_uj(opc, rd, imm)); 579139c1837SPaolo Bonzini} 580139c1837SPaolo Bonzini 581139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count) 582139c1837SPaolo Bonzini{ 583139c1837SPaolo Bonzini int i; 584139c1837SPaolo Bonzini for (i = 0; i < count; ++i) { 5859ae958e4SRichard Henderson p[i] = OPC_NOP; 586139c1837SPaolo Bonzini } 587139c1837SPaolo Bonzini} 588139c1837SPaolo Bonzini 589139c1837SPaolo Bonzini/* 590139c1837SPaolo Bonzini * Relocations 591139c1837SPaolo Bonzini */ 592139c1837SPaolo Bonzini 593793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 594139c1837SPaolo Bonzini{ 595793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 596793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 597139c1837SPaolo Bonzini 598844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 599844d0442SRichard Henderson if (offset == sextreg(offset, 0, 12)) { 600793f7381SRichard Henderson *src_rw |= encode_sbimm12(offset); 601139c1837SPaolo Bonzini return true; 602139c1837SPaolo Bonzini } 603139c1837SPaolo Bonzini 604139c1837SPaolo Bonzini return false; 605139c1837SPaolo Bonzini} 606139c1837SPaolo Bonzini 607793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 608139c1837SPaolo Bonzini{ 609793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 610793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 611139c1837SPaolo Bonzini 612844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 613844d0442SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 614793f7381SRichard Henderson *src_rw |= encode_ujimm20(offset); 615139c1837SPaolo Bonzini return true; 616139c1837SPaolo Bonzini } 617139c1837SPaolo Bonzini 618139c1837SPaolo Bonzini return false; 619139c1837SPaolo Bonzini} 620139c1837SPaolo Bonzini 621793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 622139c1837SPaolo Bonzini{ 623793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 624793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 625139c1837SPaolo Bonzini int32_t lo = sextreg(offset, 0, 12); 626139c1837SPaolo Bonzini int32_t hi = offset - lo; 627139c1837SPaolo Bonzini 628139c1837SPaolo Bonzini if (offset == hi + lo) { 629793f7381SRichard Henderson src_rw[0] |= encode_uimm20(hi); 630793f7381SRichard Henderson src_rw[1] |= encode_imm12(lo); 631139c1837SPaolo Bonzini return true; 632139c1837SPaolo Bonzini } 633139c1837SPaolo Bonzini 634139c1837SPaolo Bonzini return false; 635139c1837SPaolo Bonzini} 636139c1837SPaolo Bonzini 637139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type, 638139c1837SPaolo Bonzini intptr_t value, intptr_t addend) 639139c1837SPaolo Bonzini{ 640139c1837SPaolo Bonzini tcg_debug_assert(addend == 0); 641139c1837SPaolo Bonzini switch (type) { 642139c1837SPaolo Bonzini case R_RISCV_BRANCH: 643139c1837SPaolo Bonzini return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value); 644139c1837SPaolo Bonzini case R_RISCV_JAL: 645139c1837SPaolo Bonzini return reloc_jimm20(code_ptr, (tcg_insn_unit *)value); 646139c1837SPaolo Bonzini case R_RISCV_CALL: 647139c1837SPaolo Bonzini return reloc_call(code_ptr, (tcg_insn_unit *)value); 648139c1837SPaolo Bonzini default: 6494b6a52d0SRichard Henderson g_assert_not_reached(); 650139c1837SPaolo Bonzini } 651139c1837SPaolo Bonzini} 652139c1837SPaolo Bonzini 653139c1837SPaolo Bonzini/* 654f63e7089SHuang Shiyuan * RISC-V vector instruction emitters 655f63e7089SHuang Shiyuan */ 656f63e7089SHuang Shiyuan 657d4be6ee1STANG Tiancheng/* 658d4be6ee1STANG Tiancheng * Vector registers uses the same 5 lower bits as GPR registers, 659d4be6ee1STANG Tiancheng * and vm=0 (vm = false) means vector masking ENABLED. 660d4be6ee1STANG Tiancheng * With RVV 1.0, vs2 is the first operand, while rs1/imm is the 661d4be6ee1STANG Tiancheng * second operand. 662d4be6ee1STANG Tiancheng */ 6635a63f599STANG Tianchengstatic void tcg_out_opc_vv(TCGContext *s, RISCVInsn opc, 6645a63f599STANG Tiancheng TCGReg vd, TCGReg vs2, TCGReg vs1) 6655a63f599STANG Tiancheng{ 6665a63f599STANG Tiancheng tcg_out32(s, encode_v(opc, vd, vs1, vs2, true)); 6675a63f599STANG Tiancheng} 6685a63f599STANG Tiancheng 669d4be6ee1STANG Tianchengstatic void tcg_out_opc_vx(TCGContext *s, RISCVInsn opc, 670d4be6ee1STANG Tiancheng TCGReg vd, TCGReg vs2, TCGReg rs1) 671d4be6ee1STANG Tiancheng{ 672d4be6ee1STANG Tiancheng tcg_out32(s, encode_v(opc, vd, rs1, vs2, true)); 673d4be6ee1STANG Tiancheng} 674d4be6ee1STANG Tiancheng 675d4be6ee1STANG Tianchengstatic void tcg_out_opc_vi(TCGContext *s, RISCVInsn opc, 676d4be6ee1STANG Tiancheng TCGReg vd, TCGReg vs2, int32_t imm) 677d4be6ee1STANG Tiancheng{ 678d4be6ee1STANG Tiancheng tcg_out32(s, encode_vi(opc, vd, imm, vs2, true)); 679d4be6ee1STANG Tiancheng} 680d4be6ee1STANG Tiancheng 6815a63f599STANG Tianchengstatic void tcg_out_opc_vv_vi(TCGContext *s, RISCVInsn o_vv, RISCVInsn o_vi, 6825a63f599STANG Tiancheng TCGReg vd, TCGReg vs2, TCGArg vi1, int c_vi1) 6835a63f599STANG Tiancheng{ 6845a63f599STANG Tiancheng if (c_vi1) { 6855a63f599STANG Tiancheng tcg_out_opc_vi(s, o_vi, vd, vs2, vi1); 6865a63f599STANG Tiancheng } else { 6875a63f599STANG Tiancheng tcg_out_opc_vv(s, o_vv, vd, vs2, vi1); 6885a63f599STANG Tiancheng } 6895a63f599STANG Tiancheng} 6905a63f599STANG Tiancheng 691a31768c0STANG Tianchengstatic void tcg_out_opc_vim_mask(TCGContext *s, RISCVInsn opc, TCGReg vd, 692a31768c0STANG Tiancheng TCGReg vs2, int32_t imm) 693a31768c0STANG Tiancheng{ 694a31768c0STANG Tiancheng tcg_out32(s, encode_vi(opc, vd, imm, vs2, false)); 695a31768c0STANG Tiancheng} 696a31768c0STANG Tiancheng 697a31768c0STANG Tianchengstatic void tcg_out_opc_vvm_mask(TCGContext *s, RISCVInsn opc, TCGReg vd, 698a31768c0STANG Tiancheng TCGReg vs2, TCGReg vs1) 699a31768c0STANG Tiancheng{ 700a31768c0STANG Tiancheng tcg_out32(s, encode_v(opc, vd, vs1, vs2, false)); 701a31768c0STANG Tiancheng} 702a31768c0STANG Tiancheng 703f63e7089SHuang Shiyuantypedef struct VsetCache { 704f63e7089SHuang Shiyuan uint32_t movi_insn; 705f63e7089SHuang Shiyuan uint32_t vset_insn; 706f63e7089SHuang Shiyuan} VsetCache; 707f63e7089SHuang Shiyuan 708f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4]; 709f63e7089SHuang Shiyuan 710f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew) 711f63e7089SHuang Shiyuan{ 712f63e7089SHuang Shiyuan const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew]; 713f63e7089SHuang Shiyuan 714f63e7089SHuang Shiyuan s->riscv_cur_type = type; 715f63e7089SHuang Shiyuan s->riscv_cur_vsew = vsew; 716f63e7089SHuang Shiyuan 717f63e7089SHuang Shiyuan if (p->movi_insn) { 718f63e7089SHuang Shiyuan tcg_out32(s, p->movi_insn); 719f63e7089SHuang Shiyuan } 720f63e7089SHuang Shiyuan tcg_out32(s, p->vset_insn); 721f63e7089SHuang Shiyuan} 722f63e7089SHuang Shiyuan 723f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type) 724f63e7089SHuang Shiyuan{ 725f63e7089SHuang Shiyuan if (type != s->riscv_cur_type) { 726f63e7089SHuang Shiyuan set_vtype(s, type, MO_64); 727f63e7089SHuang Shiyuan } 728f63e7089SHuang Shiyuan return s->riscv_cur_vsew; 729f63e7089SHuang Shiyuan} 730f63e7089SHuang Shiyuan 731d4be6ee1STANG Tianchengstatic void set_vtype_len_sew(TCGContext *s, TCGType type, MemOp vsew) 732d4be6ee1STANG Tiancheng{ 733d4be6ee1STANG Tiancheng if (type != s->riscv_cur_type || vsew != s->riscv_cur_vsew) { 734d4be6ee1STANG Tiancheng set_vtype(s, type, vsew); 735d4be6ee1STANG Tiancheng } 736d4be6ee1STANG Tiancheng} 737d4be6ee1STANG Tiancheng 738f63e7089SHuang Shiyuan/* 739139c1837SPaolo Bonzini * TCG intrinsics 740139c1837SPaolo Bonzini */ 741139c1837SPaolo Bonzini 742139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 743139c1837SPaolo Bonzini{ 744139c1837SPaolo Bonzini if (ret == arg) { 745139c1837SPaolo Bonzini return true; 746139c1837SPaolo Bonzini } 747139c1837SPaolo Bonzini switch (type) { 748139c1837SPaolo Bonzini case TCG_TYPE_I32: 749139c1837SPaolo Bonzini case TCG_TYPE_I64: 750139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0); 751139c1837SPaolo Bonzini break; 752d4be6ee1STANG Tiancheng case TCG_TYPE_V64: 753d4be6ee1STANG Tiancheng case TCG_TYPE_V128: 754d4be6ee1STANG Tiancheng case TCG_TYPE_V256: 755d4be6ee1STANG Tiancheng { 756d4be6ee1STANG Tiancheng int lmul = type - riscv_lg2_vlenb; 757d4be6ee1STANG Tiancheng int nf = 1 << MAX(lmul, 0); 758d4be6ee1STANG Tiancheng tcg_out_opc_vi(s, OPC_VMVNR_V, ret, arg, nf - 1); 759d4be6ee1STANG Tiancheng } 760d4be6ee1STANG Tiancheng break; 761139c1837SPaolo Bonzini default: 762139c1837SPaolo Bonzini g_assert_not_reached(); 763139c1837SPaolo Bonzini } 764139c1837SPaolo Bonzini return true; 765139c1837SPaolo Bonzini} 766139c1837SPaolo Bonzini 767139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, 768139c1837SPaolo Bonzini tcg_target_long val) 769139c1837SPaolo Bonzini{ 770139c1837SPaolo Bonzini tcg_target_long lo, hi, tmp; 771139c1837SPaolo Bonzini int shift, ret; 772139c1837SPaolo Bonzini 773aeb6326eSRichard Henderson if (type == TCG_TYPE_I32) { 774139c1837SPaolo Bonzini val = (int32_t)val; 775139c1837SPaolo Bonzini } 776139c1837SPaolo Bonzini 777139c1837SPaolo Bonzini lo = sextreg(val, 0, 12); 778139c1837SPaolo Bonzini if (val == lo) { 779139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo); 780139c1837SPaolo Bonzini return; 781139c1837SPaolo Bonzini } 782139c1837SPaolo Bonzini 783139c1837SPaolo Bonzini hi = val - lo; 784aeb6326eSRichard Henderson if (val == (int32_t)val) { 785139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, hi); 786139c1837SPaolo Bonzini if (lo != 0) { 787139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo); 788139c1837SPaolo Bonzini } 789139c1837SPaolo Bonzini return; 790139c1837SPaolo Bonzini } 791139c1837SPaolo Bonzini 792139c1837SPaolo Bonzini tmp = tcg_pcrel_diff(s, (void *)val); 793139c1837SPaolo Bonzini if (tmp == (int32_t)tmp) { 794139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); 795139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0); 796793f7381SRichard Henderson ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val); 797139c1837SPaolo Bonzini tcg_debug_assert(ret == true); 798139c1837SPaolo Bonzini return; 799139c1837SPaolo Bonzini } 800139c1837SPaolo Bonzini 801139c1837SPaolo Bonzini /* Look for a single 20-bit section. */ 802139c1837SPaolo Bonzini shift = ctz64(val); 803139c1837SPaolo Bonzini tmp = val >> shift; 804139c1837SPaolo Bonzini if (tmp == sextreg(tmp, 0, 20)) { 805139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12); 806139c1837SPaolo Bonzini if (shift > 12) { 807139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12); 808139c1837SPaolo Bonzini } else { 809139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift); 810139c1837SPaolo Bonzini } 811139c1837SPaolo Bonzini return; 812139c1837SPaolo Bonzini } 813139c1837SPaolo Bonzini 814139c1837SPaolo Bonzini /* Look for a few high zero bits, with lots of bits set in the middle. */ 815139c1837SPaolo Bonzini shift = clz64(val); 816139c1837SPaolo Bonzini tmp = val << shift; 817139c1837SPaolo Bonzini if (tmp == sextreg(tmp, 12, 20) << 12) { 818139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, tmp); 819139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift); 820139c1837SPaolo Bonzini return; 821139c1837SPaolo Bonzini } else if (tmp == sextreg(tmp, 0, 12)) { 822139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp); 823139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift); 824139c1837SPaolo Bonzini return; 825139c1837SPaolo Bonzini } 826139c1837SPaolo Bonzini 827139c1837SPaolo Bonzini /* Drop into the constant pool. */ 828139c1837SPaolo Bonzini new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0); 829139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); 830139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_LD, rd, rd, 0); 831139c1837SPaolo Bonzini} 832139c1837SPaolo Bonzini 833767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2) 834767c2503SRichard Henderson{ 835767c2503SRichard Henderson return false; 836767c2503SRichard Henderson} 837767c2503SRichard Henderson 8386a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs, 8396a6d772eSRichard Henderson tcg_target_long imm) 8406a6d772eSRichard Henderson{ 8416a6d772eSRichard Henderson /* This function is only used for passing structs by reference. */ 8426a6d772eSRichard Henderson g_assert_not_reached(); 8436a6d772eSRichard Henderson} 8446a6d772eSRichard Henderson 845139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) 846139c1837SPaolo Bonzini{ 847139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff); 848139c1837SPaolo Bonzini} 849139c1837SPaolo Bonzini 850139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) 851139c1837SPaolo Bonzini{ 852b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 853d1c3f4e9SRichard Henderson tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO); 854d1c3f4e9SRichard Henderson } else { 855139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); 856139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16); 857139c1837SPaolo Bonzini } 858d1c3f4e9SRichard Henderson} 859139c1837SPaolo Bonzini 860139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) 861139c1837SPaolo Bonzini{ 862b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBA) { 863d1c3f4e9SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO); 864d1c3f4e9SRichard Henderson } else { 865139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32); 866139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32); 867139c1837SPaolo Bonzini } 868d1c3f4e9SRichard Henderson} 869139c1837SPaolo Bonzini 870678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 871139c1837SPaolo Bonzini{ 872b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 873d1c3f4e9SRichard Henderson tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0); 874d1c3f4e9SRichard Henderson } else { 875139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24); 876139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24); 877139c1837SPaolo Bonzini } 878d1c3f4e9SRichard Henderson} 879139c1837SPaolo Bonzini 880753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 881139c1837SPaolo Bonzini{ 882b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 883d1c3f4e9SRichard Henderson tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0); 884d1c3f4e9SRichard Henderson } else { 885139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); 886139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16); 887139c1837SPaolo Bonzini } 888d1c3f4e9SRichard Henderson} 889139c1837SPaolo Bonzini 890139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) 891139c1837SPaolo Bonzini{ 892139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0); 893139c1837SPaolo Bonzini} 894139c1837SPaolo Bonzini 8959c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg) 8969c6aa274SRichard Henderson{ 8973ea9be33SRichard Henderson if (ret != arg) { 8989c6aa274SRichard Henderson tcg_out_ext32s(s, ret, arg); 8999c6aa274SRichard Henderson } 9003ea9be33SRichard Henderson} 9019c6aa274SRichard Henderson 902b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg) 903b9bfe000SRichard Henderson{ 904b9bfe000SRichard Henderson tcg_out_ext32u(s, ret, arg); 905b9bfe000SRichard Henderson} 906b9bfe000SRichard Henderson 907b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg) 908b8b94ac6SRichard Henderson{ 909b8b94ac6SRichard Henderson tcg_out_ext32s(s, ret, arg); 910b8b94ac6SRichard Henderson} 911b8b94ac6SRichard Henderson 912139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, 913139c1837SPaolo Bonzini TCGReg addr, intptr_t offset) 914139c1837SPaolo Bonzini{ 915139c1837SPaolo Bonzini intptr_t imm12 = sextreg(offset, 0, 12); 916139c1837SPaolo Bonzini 917139c1837SPaolo Bonzini if (offset != imm12) { 9189d9db413SRichard Henderson intptr_t diff = tcg_pcrel_diff(s, (void *)offset); 919139c1837SPaolo Bonzini 920139c1837SPaolo Bonzini if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { 921139c1837SPaolo Bonzini imm12 = sextreg(diff, 0, 12); 922139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12); 923139c1837SPaolo Bonzini } else { 924139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); 925139c1837SPaolo Bonzini if (addr != TCG_REG_ZERO) { 926139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr); 927139c1837SPaolo Bonzini } 928139c1837SPaolo Bonzini } 929139c1837SPaolo Bonzini addr = TCG_REG_TMP2; 930139c1837SPaolo Bonzini } 931139c1837SPaolo Bonzini 932139c1837SPaolo Bonzini switch (opc) { 933139c1837SPaolo Bonzini case OPC_SB: 934139c1837SPaolo Bonzini case OPC_SH: 935139c1837SPaolo Bonzini case OPC_SW: 936139c1837SPaolo Bonzini case OPC_SD: 937139c1837SPaolo Bonzini tcg_out_opc_store(s, opc, addr, data, imm12); 938139c1837SPaolo Bonzini break; 939139c1837SPaolo Bonzini case OPC_LB: 940139c1837SPaolo Bonzini case OPC_LBU: 941139c1837SPaolo Bonzini case OPC_LH: 942139c1837SPaolo Bonzini case OPC_LHU: 943139c1837SPaolo Bonzini case OPC_LW: 944139c1837SPaolo Bonzini case OPC_LWU: 945139c1837SPaolo Bonzini case OPC_LD: 946139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc, data, addr, imm12); 947139c1837SPaolo Bonzini break; 948139c1837SPaolo Bonzini default: 949139c1837SPaolo Bonzini g_assert_not_reached(); 950139c1837SPaolo Bonzini } 951139c1837SPaolo Bonzini} 952139c1837SPaolo Bonzini 953f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, 954f63e7089SHuang Shiyuan TCGReg addr, intptr_t offset) 955f63e7089SHuang Shiyuan{ 956f63e7089SHuang Shiyuan tcg_debug_assert(data >= TCG_REG_V0); 957f63e7089SHuang Shiyuan tcg_debug_assert(addr < TCG_REG_V0); 958f63e7089SHuang Shiyuan 959f63e7089SHuang Shiyuan if (offset) { 960f63e7089SHuang Shiyuan tcg_debug_assert(addr != TCG_REG_ZERO); 961f63e7089SHuang Shiyuan if (offset == sextreg(offset, 0, 12)) { 962f63e7089SHuang Shiyuan tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset); 963f63e7089SHuang Shiyuan } else { 964f63e7089SHuang Shiyuan tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset); 965f63e7089SHuang Shiyuan tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr); 966f63e7089SHuang Shiyuan } 967f63e7089SHuang Shiyuan addr = TCG_REG_TMP0; 968f63e7089SHuang Shiyuan } 969f63e7089SHuang Shiyuan tcg_out32(s, encode_v(opc, data, addr, 0, true)); 970f63e7089SHuang Shiyuan} 971f63e7089SHuang Shiyuan 972139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, 973139c1837SPaolo Bonzini TCGReg arg1, intptr_t arg2) 974139c1837SPaolo Bonzini{ 975f63e7089SHuang Shiyuan RISCVInsn insn; 976f63e7089SHuang Shiyuan 977f63e7089SHuang Shiyuan switch (type) { 978f63e7089SHuang Shiyuan case TCG_TYPE_I32: 979f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_LW, arg, arg1, arg2); 980f63e7089SHuang Shiyuan break; 981f63e7089SHuang Shiyuan case TCG_TYPE_I64: 982f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_LD, arg, arg1, arg2); 983f63e7089SHuang Shiyuan break; 984f63e7089SHuang Shiyuan case TCG_TYPE_V64: 985f63e7089SHuang Shiyuan case TCG_TYPE_V128: 986f63e7089SHuang Shiyuan case TCG_TYPE_V256: 987f63e7089SHuang Shiyuan if (type >= riscv_lg2_vlenb) { 988f63e7089SHuang Shiyuan static const RISCVInsn whole_reg_ld[] = { 989f63e7089SHuang Shiyuan OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V 990f63e7089SHuang Shiyuan }; 991f63e7089SHuang Shiyuan unsigned idx = type - riscv_lg2_vlenb; 992f63e7089SHuang Shiyuan 993f63e7089SHuang Shiyuan tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld)); 994f63e7089SHuang Shiyuan insn = whole_reg_ld[idx]; 995f63e7089SHuang Shiyuan } else { 996f63e7089SHuang Shiyuan static const RISCVInsn unit_stride_ld[] = { 997f63e7089SHuang Shiyuan OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V 998f63e7089SHuang Shiyuan }; 999f63e7089SHuang Shiyuan MemOp prev_vsew = set_vtype_len(s, type); 1000f63e7089SHuang Shiyuan 1001f63e7089SHuang Shiyuan tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld)); 1002f63e7089SHuang Shiyuan insn = unit_stride_ld[prev_vsew]; 1003f63e7089SHuang Shiyuan } 1004f63e7089SHuang Shiyuan tcg_out_vec_ldst(s, insn, arg, arg1, arg2); 1005f63e7089SHuang Shiyuan break; 1006f63e7089SHuang Shiyuan default: 1007f63e7089SHuang Shiyuan g_assert_not_reached(); 1008f63e7089SHuang Shiyuan } 1009139c1837SPaolo Bonzini} 1010139c1837SPaolo Bonzini 1011139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, 1012139c1837SPaolo Bonzini TCGReg arg1, intptr_t arg2) 1013139c1837SPaolo Bonzini{ 1014f63e7089SHuang Shiyuan RISCVInsn insn; 1015f63e7089SHuang Shiyuan 1016f63e7089SHuang Shiyuan switch (type) { 1017f63e7089SHuang Shiyuan case TCG_TYPE_I32: 1018f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_SW, arg, arg1, arg2); 1019f63e7089SHuang Shiyuan break; 1020f63e7089SHuang Shiyuan case TCG_TYPE_I64: 1021f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_SD, arg, arg1, arg2); 1022f63e7089SHuang Shiyuan break; 1023f63e7089SHuang Shiyuan case TCG_TYPE_V64: 1024f63e7089SHuang Shiyuan case TCG_TYPE_V128: 1025f63e7089SHuang Shiyuan case TCG_TYPE_V256: 1026f63e7089SHuang Shiyuan if (type >= riscv_lg2_vlenb) { 1027f63e7089SHuang Shiyuan static const RISCVInsn whole_reg_st[] = { 1028f63e7089SHuang Shiyuan OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V 1029f63e7089SHuang Shiyuan }; 1030f63e7089SHuang Shiyuan unsigned idx = type - riscv_lg2_vlenb; 1031f63e7089SHuang Shiyuan 1032f63e7089SHuang Shiyuan tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st)); 1033f63e7089SHuang Shiyuan insn = whole_reg_st[idx]; 1034f63e7089SHuang Shiyuan } else { 1035f63e7089SHuang Shiyuan static const RISCVInsn unit_stride_st[] = { 1036f63e7089SHuang Shiyuan OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V 1037f63e7089SHuang Shiyuan }; 1038f63e7089SHuang Shiyuan MemOp prev_vsew = set_vtype_len(s, type); 1039f63e7089SHuang Shiyuan 1040f63e7089SHuang Shiyuan tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st)); 1041f63e7089SHuang Shiyuan insn = unit_stride_st[prev_vsew]; 1042f63e7089SHuang Shiyuan } 1043f63e7089SHuang Shiyuan tcg_out_vec_ldst(s, insn, arg, arg1, arg2); 1044f63e7089SHuang Shiyuan break; 1045f63e7089SHuang Shiyuan default: 1046f63e7089SHuang Shiyuan g_assert_not_reached(); 1047f63e7089SHuang Shiyuan } 1048139c1837SPaolo Bonzini} 1049139c1837SPaolo Bonzini 1050139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, 1051139c1837SPaolo Bonzini TCGReg base, intptr_t ofs) 1052139c1837SPaolo Bonzini{ 1053139c1837SPaolo Bonzini if (val == 0) { 1054139c1837SPaolo Bonzini tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); 1055139c1837SPaolo Bonzini return true; 1056139c1837SPaolo Bonzini } 1057139c1837SPaolo Bonzini return false; 1058139c1837SPaolo Bonzini} 1059139c1837SPaolo Bonzini 1060139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s, 1061139c1837SPaolo Bonzini TCGReg rl, TCGReg rh, 1062139c1837SPaolo Bonzini TCGReg al, TCGReg ah, 1063139c1837SPaolo Bonzini TCGArg bl, TCGArg bh, 1064139c1837SPaolo Bonzini bool cbl, bool cbh, bool is_sub, bool is32bit) 1065139c1837SPaolo Bonzini{ 1066139c1837SPaolo Bonzini const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD; 1067139c1837SPaolo Bonzini const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI; 1068139c1837SPaolo Bonzini const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB; 1069139c1837SPaolo Bonzini TCGReg th = TCG_REG_TMP1; 1070139c1837SPaolo Bonzini 1071139c1837SPaolo Bonzini /* If we have a negative constant such that negating it would 1072139c1837SPaolo Bonzini make the high part zero, we can (usually) eliminate one insn. */ 1073139c1837SPaolo Bonzini if (cbl && cbh && bh == -1 && bl != 0) { 1074139c1837SPaolo Bonzini bl = -bl; 1075139c1837SPaolo Bonzini bh = 0; 1076139c1837SPaolo Bonzini is_sub = !is_sub; 1077139c1837SPaolo Bonzini } 1078139c1837SPaolo Bonzini 1079139c1837SPaolo Bonzini /* By operating on the high part first, we get to use the final 1080139c1837SPaolo Bonzini carry operation to move back from the temporary. */ 1081139c1837SPaolo Bonzini if (!cbh) { 1082139c1837SPaolo Bonzini tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh); 1083139c1837SPaolo Bonzini } else if (bh != 0 || ah == rl) { 1084139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh)); 1085139c1837SPaolo Bonzini } else { 1086139c1837SPaolo Bonzini th = ah; 1087139c1837SPaolo Bonzini } 1088139c1837SPaolo Bonzini 1089139c1837SPaolo Bonzini /* Note that tcg optimization should eliminate the bl == 0 case. */ 1090139c1837SPaolo Bonzini if (is_sub) { 1091139c1837SPaolo Bonzini if (cbl) { 1092139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl); 1093139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, rl, al, -bl); 1094139c1837SPaolo Bonzini } else { 1095139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl); 1096139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_sub, rl, al, bl); 1097139c1837SPaolo Bonzini } 1098139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0); 1099139c1837SPaolo Bonzini } else { 1100139c1837SPaolo Bonzini if (cbl) { 1101139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, rl, al, bl); 1102139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl); 11039b246685SRichard Henderson } else if (al == bl) { 11049b246685SRichard Henderson /* 11059b246685SRichard Henderson * If the input regs overlap, this is a simple doubling 11069b246685SRichard Henderson * and carry-out is the input msb. This special case is 11079b246685SRichard Henderson * required when the output reg overlaps the input, 11089b246685SRichard Henderson * but we might as well use it always. 11099b246685SRichard Henderson */ 1110139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0); 11119b246685SRichard Henderson tcg_out_opc_reg(s, opc_add, rl, al, al); 1112139c1837SPaolo Bonzini } else { 1113139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_add, rl, al, bl); 1114139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, 1115139c1837SPaolo Bonzini rl, (rl == bl ? al : bl)); 1116139c1837SPaolo Bonzini } 1117139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0); 1118139c1837SPaolo Bonzini } 1119139c1837SPaolo Bonzini} 1120139c1837SPaolo Bonzini 1121f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece, 1122f63e7089SHuang Shiyuan TCGReg dst, TCGReg src) 1123f63e7089SHuang Shiyuan{ 1124d4be6ee1STANG Tiancheng set_vtype_len_sew(s, type, vece); 1125d4be6ee1STANG Tiancheng tcg_out_opc_vx(s, OPC_VMV_V_X, dst, 0, src); 1126d4be6ee1STANG Tiancheng return true; 1127f63e7089SHuang Shiyuan} 1128f63e7089SHuang Shiyuan 1129f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece, 1130f63e7089SHuang Shiyuan TCGReg dst, TCGReg base, intptr_t offset) 1131f63e7089SHuang Shiyuan{ 1132d4be6ee1STANG Tiancheng tcg_out_ld(s, TCG_TYPE_REG, TCG_REG_TMP0, base, offset); 1133d4be6ee1STANG Tiancheng return tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0); 1134f63e7089SHuang Shiyuan} 1135f63e7089SHuang Shiyuan 1136f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece, 1137f63e7089SHuang Shiyuan TCGReg dst, int64_t arg) 1138f63e7089SHuang Shiyuan{ 1139d4be6ee1STANG Tiancheng /* Arg is replicated by VECE; extract the highest element. */ 1140d4be6ee1STANG Tiancheng arg >>= (-8 << vece) & 63; 1141d4be6ee1STANG Tiancheng 1142d4be6ee1STANG Tiancheng if (arg >= -16 && arg < 16) { 1143d4be6ee1STANG Tiancheng if (arg == 0 || arg == -1) { 1144d4be6ee1STANG Tiancheng set_vtype_len(s, type); 1145d4be6ee1STANG Tiancheng } else { 1146d4be6ee1STANG Tiancheng set_vtype_len_sew(s, type, vece); 1147d4be6ee1STANG Tiancheng } 1148d4be6ee1STANG Tiancheng tcg_out_opc_vi(s, OPC_VMV_V_I, dst, 0, arg); 1149d4be6ee1STANG Tiancheng return; 1150d4be6ee1STANG Tiancheng } 1151d4be6ee1STANG Tiancheng tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, arg); 1152d4be6ee1STANG Tiancheng tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0); 1153f63e7089SHuang Shiyuan} 1154f63e7089SHuang Shiyuan 1155139c1837SPaolo Bonzinistatic const struct { 1156139c1837SPaolo Bonzini RISCVInsn op; 1157139c1837SPaolo Bonzini bool swap; 1158139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = { 1159139c1837SPaolo Bonzini [TCG_COND_EQ] = { OPC_BEQ, false }, 1160139c1837SPaolo Bonzini [TCG_COND_NE] = { OPC_BNE, false }, 1161139c1837SPaolo Bonzini [TCG_COND_LT] = { OPC_BLT, false }, 1162139c1837SPaolo Bonzini [TCG_COND_GE] = { OPC_BGE, false }, 1163139c1837SPaolo Bonzini [TCG_COND_LE] = { OPC_BGE, true }, 1164139c1837SPaolo Bonzini [TCG_COND_GT] = { OPC_BLT, true }, 1165139c1837SPaolo Bonzini [TCG_COND_LTU] = { OPC_BLTU, false }, 1166139c1837SPaolo Bonzini [TCG_COND_GEU] = { OPC_BGEU, false }, 1167139c1837SPaolo Bonzini [TCG_COND_LEU] = { OPC_BGEU, true }, 1168139c1837SPaolo Bonzini [TCG_COND_GTU] = { OPC_BLTU, true } 1169139c1837SPaolo Bonzini}; 1170139c1837SPaolo Bonzini 1171139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, 1172139c1837SPaolo Bonzini TCGReg arg2, TCGLabel *l) 1173139c1837SPaolo Bonzini{ 1174139c1837SPaolo Bonzini RISCVInsn op = tcg_brcond_to_riscv[cond].op; 1175139c1837SPaolo Bonzini 1176139c1837SPaolo Bonzini tcg_debug_assert(op != 0); 1177139c1837SPaolo Bonzini 1178139c1837SPaolo Bonzini if (tcg_brcond_to_riscv[cond].swap) { 1179139c1837SPaolo Bonzini TCGReg t = arg1; 1180139c1837SPaolo Bonzini arg1 = arg2; 1181139c1837SPaolo Bonzini arg2 = t; 1182139c1837SPaolo Bonzini } 1183139c1837SPaolo Bonzini 1184139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0); 1185139c1837SPaolo Bonzini tcg_out_opc_branch(s, op, arg1, arg2, 0); 1186139c1837SPaolo Bonzini} 1187139c1837SPaolo Bonzini 1188f6453695SRichard Henderson#define SETCOND_INV TCG_TARGET_NB_REGS 1189f6453695SRichard Henderson#define SETCOND_NEZ (SETCOND_INV << 1) 1190f6453695SRichard Henderson#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ) 1191f6453695SRichard Henderson 1192f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret, 1193f6453695SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 1194139c1837SPaolo Bonzini{ 1195f6453695SRichard Henderson int flags = 0; 1196f6453695SRichard Henderson 1197139c1837SPaolo Bonzini switch (cond) { 1198f6453695SRichard Henderson case TCG_COND_EQ: /* -> NE */ 1199f6453695SRichard Henderson case TCG_COND_GE: /* -> LT */ 1200f6453695SRichard Henderson case TCG_COND_GEU: /* -> LTU */ 1201f6453695SRichard Henderson case TCG_COND_GT: /* -> LE */ 1202f6453695SRichard Henderson case TCG_COND_GTU: /* -> LEU */ 1203f6453695SRichard Henderson cond = tcg_invert_cond(cond); 1204f6453695SRichard Henderson flags ^= SETCOND_INV; 1205139c1837SPaolo Bonzini break; 1206f6453695SRichard Henderson default: 1207139c1837SPaolo Bonzini break; 1208f6453695SRichard Henderson } 1209f6453695SRichard Henderson 1210f6453695SRichard Henderson switch (cond) { 1211139c1837SPaolo Bonzini case TCG_COND_LE: 1212139c1837SPaolo Bonzini case TCG_COND_LEU: 1213f6453695SRichard Henderson /* 1214f6453695SRichard Henderson * If we have a constant input, the most efficient way to implement 1215f6453695SRichard Henderson * LE is by adding 1 and using LT. Watch out for wrap around for LEU. 1216f6453695SRichard Henderson * We don't need to care for this for LE because the constant input 1217f6453695SRichard Henderson * is constrained to signed 12-bit, and 0x800 is representable in the 1218f6453695SRichard Henderson * temporary register. 1219f6453695SRichard Henderson */ 1220f6453695SRichard Henderson if (c2) { 1221f6453695SRichard Henderson if (cond == TCG_COND_LEU) { 1222f6453695SRichard Henderson /* unsigned <= -1 is true */ 1223f6453695SRichard Henderson if (arg2 == -1) { 1224f6453695SRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV)); 1225f6453695SRichard Henderson return ret; 1226f6453695SRichard Henderson } 1227f6453695SRichard Henderson cond = TCG_COND_LTU; 1228f6453695SRichard Henderson } else { 1229f6453695SRichard Henderson cond = TCG_COND_LT; 1230f6453695SRichard Henderson } 1231f6453695SRichard Henderson tcg_debug_assert(arg2 <= 0x7ff); 1232f6453695SRichard Henderson if (++arg2 == 0x800) { 1233f6453695SRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2); 1234f6453695SRichard Henderson arg2 = TCG_REG_TMP0; 1235f6453695SRichard Henderson c2 = false; 1236f6453695SRichard Henderson } 1237f6453695SRichard Henderson } else { 1238f6453695SRichard Henderson TCGReg tmp = arg2; 1239f6453695SRichard Henderson arg2 = arg1; 1240f6453695SRichard Henderson arg1 = tmp; 1241f6453695SRichard Henderson cond = tcg_swap_cond(cond); /* LE -> GE */ 1242f6453695SRichard Henderson cond = tcg_invert_cond(cond); /* GE -> LT */ 1243f6453695SRichard Henderson flags ^= SETCOND_INV; 1244f6453695SRichard Henderson } 1245139c1837SPaolo Bonzini break; 1246f6453695SRichard Henderson default: 1247f6453695SRichard Henderson break; 1248f6453695SRichard Henderson } 1249f6453695SRichard Henderson 1250f6453695SRichard Henderson switch (cond) { 1251f6453695SRichard Henderson case TCG_COND_NE: 1252f6453695SRichard Henderson flags |= SETCOND_NEZ; 1253f6453695SRichard Henderson if (!c2) { 1254f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2); 1255f6453695SRichard Henderson } else if (arg2 == 0) { 1256f6453695SRichard Henderson ret = arg1; 1257f6453695SRichard Henderson } else { 1258f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2); 1259f6453695SRichard Henderson } 1260f6453695SRichard Henderson break; 1261f6453695SRichard Henderson 1262f6453695SRichard Henderson case TCG_COND_LT: 1263f6453695SRichard Henderson if (c2) { 1264f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2); 1265f6453695SRichard Henderson } else { 1266f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); 1267f6453695SRichard Henderson } 1268f6453695SRichard Henderson break; 1269f6453695SRichard Henderson 1270f6453695SRichard Henderson case TCG_COND_LTU: 1271f6453695SRichard Henderson if (c2) { 1272f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2); 1273f6453695SRichard Henderson } else { 1274f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); 1275f6453695SRichard Henderson } 1276f6453695SRichard Henderson break; 1277f6453695SRichard Henderson 1278f6453695SRichard Henderson default: 1279f6453695SRichard Henderson g_assert_not_reached(); 1280f6453695SRichard Henderson } 1281f6453695SRichard Henderson 1282f6453695SRichard Henderson return ret | flags; 1283f6453695SRichard Henderson} 1284f6453695SRichard Henderson 1285f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, 1286f6453695SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 1287f6453695SRichard Henderson{ 1288f6453695SRichard Henderson int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); 1289f6453695SRichard Henderson 1290f6453695SRichard Henderson if (tmpflags != ret) { 1291f6453695SRichard Henderson TCGReg tmp = tmpflags & ~SETCOND_FLAGS; 1292f6453695SRichard Henderson 1293f6453695SRichard Henderson switch (tmpflags & SETCOND_FLAGS) { 1294f6453695SRichard Henderson case SETCOND_INV: 1295f6453695SRichard Henderson /* Intermediate result is boolean: simply invert. */ 1296f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1); 1297f6453695SRichard Henderson break; 1298f6453695SRichard Henderson case SETCOND_NEZ: 1299f6453695SRichard Henderson /* Intermediate result is zero/non-zero: test != 0. */ 1300f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp); 1301f6453695SRichard Henderson break; 1302f6453695SRichard Henderson case SETCOND_NEZ | SETCOND_INV: 1303f6453695SRichard Henderson /* Intermediate result is zero/non-zero: test == 0. */ 1304f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1); 1305139c1837SPaolo Bonzini break; 1306139c1837SPaolo Bonzini default: 1307139c1837SPaolo Bonzini g_assert_not_reached(); 1308f6453695SRichard Henderson } 1309139c1837SPaolo Bonzini } 1310139c1837SPaolo Bonzini} 1311139c1837SPaolo Bonzini 131241e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret, 131341e4c0a9SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 131441e4c0a9SRichard Henderson{ 131541e4c0a9SRichard Henderson int tmpflags; 131641e4c0a9SRichard Henderson TCGReg tmp; 131741e4c0a9SRichard Henderson 131841e4c0a9SRichard Henderson /* For LT/GE comparison against 0, replicate the sign bit. */ 131941e4c0a9SRichard Henderson if (c2 && arg2 == 0) { 132041e4c0a9SRichard Henderson switch (cond) { 132141e4c0a9SRichard Henderson case TCG_COND_GE: 132241e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1); 132341e4c0a9SRichard Henderson arg1 = ret; 132441e4c0a9SRichard Henderson /* fall through */ 132541e4c0a9SRichard Henderson case TCG_COND_LT: 132641e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1); 132741e4c0a9SRichard Henderson return; 132841e4c0a9SRichard Henderson default: 132941e4c0a9SRichard Henderson break; 133041e4c0a9SRichard Henderson } 133141e4c0a9SRichard Henderson } 133241e4c0a9SRichard Henderson 133341e4c0a9SRichard Henderson tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); 133441e4c0a9SRichard Henderson tmp = tmpflags & ~SETCOND_FLAGS; 133541e4c0a9SRichard Henderson 133641e4c0a9SRichard Henderson /* If intermediate result is zero/non-zero: test != 0. */ 133741e4c0a9SRichard Henderson if (tmpflags & SETCOND_NEZ) { 133841e4c0a9SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp); 133941e4c0a9SRichard Henderson tmp = ret; 134041e4c0a9SRichard Henderson } 134141e4c0a9SRichard Henderson 134241e4c0a9SRichard Henderson /* Produce the 0/-1 result. */ 134341e4c0a9SRichard Henderson if (tmpflags & SETCOND_INV) { 134441e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1); 134541e4c0a9SRichard Henderson } else { 134641e4c0a9SRichard Henderson tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp); 134741e4c0a9SRichard Henderson } 134841e4c0a9SRichard Henderson} 134941e4c0a9SRichard Henderson 1350a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne, 1351a18d783eSRichard Henderson int val1, bool c_val1, 1352a18d783eSRichard Henderson int val2, bool c_val2) 1353a18d783eSRichard Henderson{ 1354a18d783eSRichard Henderson if (val1 == 0) { 1355a18d783eSRichard Henderson if (c_val2) { 1356a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2); 1357a18d783eSRichard Henderson val2 = TCG_REG_TMP1; 1358a18d783eSRichard Henderson } 1359a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne); 1360a18d783eSRichard Henderson return; 1361a18d783eSRichard Henderson } 1362a18d783eSRichard Henderson 1363a18d783eSRichard Henderson if (val2 == 0) { 1364a18d783eSRichard Henderson if (c_val1) { 1365a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1); 1366a18d783eSRichard Henderson val1 = TCG_REG_TMP1; 1367a18d783eSRichard Henderson } 1368a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne); 1369a18d783eSRichard Henderson return; 1370a18d783eSRichard Henderson } 1371a18d783eSRichard Henderson 1372a18d783eSRichard Henderson if (c_val2) { 1373a18d783eSRichard Henderson if (c_val1) { 1374a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2); 1375a18d783eSRichard Henderson } else { 1376a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2); 1377a18d783eSRichard Henderson } 1378a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne); 1379a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2); 1380a18d783eSRichard Henderson return; 1381a18d783eSRichard Henderson } 1382a18d783eSRichard Henderson 1383a18d783eSRichard Henderson if (c_val1) { 1384a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1); 1385a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne); 1386a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1); 1387a18d783eSRichard Henderson return; 1388a18d783eSRichard Henderson } 1389a18d783eSRichard Henderson 1390a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne); 1391a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne); 1392a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1); 1393a18d783eSRichard Henderson} 1394a18d783eSRichard Henderson 1395a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret, 1396a18d783eSRichard Henderson TCGReg cmp1, TCGReg cmp2, 1397a18d783eSRichard Henderson int val, bool c_val) 1398a18d783eSRichard Henderson{ 1399a18d783eSRichard Henderson RISCVInsn op; 1400a18d783eSRichard Henderson int disp = 8; 1401a18d783eSRichard Henderson 1402a18d783eSRichard Henderson tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv)); 1403a18d783eSRichard Henderson op = tcg_brcond_to_riscv[cond].op; 1404a18d783eSRichard Henderson tcg_debug_assert(op != 0); 1405a18d783eSRichard Henderson 1406a18d783eSRichard Henderson if (tcg_brcond_to_riscv[cond].swap) { 1407a18d783eSRichard Henderson tcg_out_opc_branch(s, op, cmp2, cmp1, disp); 1408a18d783eSRichard Henderson } else { 1409a18d783eSRichard Henderson tcg_out_opc_branch(s, op, cmp1, cmp2, disp); 1410a18d783eSRichard Henderson } 1411a18d783eSRichard Henderson if (c_val) { 1412a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val); 1413a18d783eSRichard Henderson } else { 1414a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0); 1415a18d783eSRichard Henderson } 1416a18d783eSRichard Henderson} 1417a18d783eSRichard Henderson 1418a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret, 1419a18d783eSRichard Henderson TCGReg cmp1, TCGReg cmp2, 1420a18d783eSRichard Henderson int val1, bool c_val1, 1421a18d783eSRichard Henderson int val2, bool c_val2) 1422a18d783eSRichard Henderson{ 1423a18d783eSRichard Henderson TCGReg tmp; 1424a18d783eSRichard Henderson 1425a18d783eSRichard Henderson /* TCG optimizer reorders to prefer ret matching val2. */ 1426a18d783eSRichard Henderson if (!c_val2 && ret == val2) { 1427a18d783eSRichard Henderson cond = tcg_invert_cond(cond); 1428a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1); 1429a18d783eSRichard Henderson return; 1430a18d783eSRichard Henderson } 1431a18d783eSRichard Henderson 1432a18d783eSRichard Henderson if (!c_val1 && ret == val1) { 1433a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2); 1434a18d783eSRichard Henderson return; 1435a18d783eSRichard Henderson } 1436a18d783eSRichard Henderson 1437a18d783eSRichard Henderson tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret); 1438a18d783eSRichard Henderson if (c_val1) { 1439a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, tmp, val1); 1440a18d783eSRichard Henderson } else { 1441a18d783eSRichard Henderson tcg_out_mov(s, TCG_TYPE_REG, tmp, val1); 1442a18d783eSRichard Henderson } 1443a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2); 1444a18d783eSRichard Henderson tcg_out_mov(s, TCG_TYPE_REG, ret, tmp); 1445a18d783eSRichard Henderson} 1446a18d783eSRichard Henderson 1447a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, 1448a18d783eSRichard Henderson TCGReg cmp1, int cmp2, bool c_cmp2, 1449a18d783eSRichard Henderson TCGReg val1, bool c_val1, 1450a18d783eSRichard Henderson TCGReg val2, bool c_val2) 1451a18d783eSRichard Henderson{ 1452a18d783eSRichard Henderson int tmpflags; 1453a18d783eSRichard Henderson TCGReg t; 1454a18d783eSRichard Henderson 1455b86c6ba6SRichard Henderson if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) { 1456a18d783eSRichard Henderson tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2, 1457a18d783eSRichard Henderson val1, c_val1, val2, c_val2); 1458a18d783eSRichard Henderson return; 1459a18d783eSRichard Henderson } 1460a18d783eSRichard Henderson 1461a18d783eSRichard Henderson tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2); 1462a18d783eSRichard Henderson t = tmpflags & ~SETCOND_FLAGS; 1463a18d783eSRichard Henderson 1464b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZICOND) { 1465a18d783eSRichard Henderson if (tmpflags & SETCOND_INV) { 1466a18d783eSRichard Henderson tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1); 1467a18d783eSRichard Henderson } else { 1468a18d783eSRichard Henderson tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2); 1469a18d783eSRichard Henderson } 1470a18d783eSRichard Henderson } else { 1471a18d783eSRichard Henderson cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE; 1472a18d783eSRichard Henderson tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO, 1473a18d783eSRichard Henderson val1, c_val1, val2, c_val2); 1474a18d783eSRichard Henderson } 1475a18d783eSRichard Henderson} 1476a18d783eSRichard Henderson 1477a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn, 1478a30498fcSRichard Henderson TCGReg ret, TCGReg src1, int src2, bool c_src2) 1479a30498fcSRichard Henderson{ 1480a30498fcSRichard Henderson tcg_out_opc_imm(s, insn, ret, src1, 0); 1481a30498fcSRichard Henderson 1482a30498fcSRichard Henderson if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) { 1483a30498fcSRichard Henderson /* 1484a30498fcSRichard Henderson * The requested zero result does not match the insn, so adjust. 1485a30498fcSRichard Henderson * Note that constraints put 'ret' in a new register, so the 1486a30498fcSRichard Henderson * computation above did not clobber either 'src1' or 'src2'. 1487a30498fcSRichard Henderson */ 1488a30498fcSRichard Henderson tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true, 1489a30498fcSRichard Henderson src2, c_src2, ret, false); 1490a30498fcSRichard Henderson } 1491a30498fcSRichard Henderson} 1492a30498fcSRichard Henderson 1493a31768c0STANG Tianchengstatic void tcg_out_cmpsel(TCGContext *s, TCGType type, unsigned vece, 1494a31768c0STANG Tiancheng TCGCond cond, TCGReg ret, 1495a31768c0STANG Tiancheng TCGReg cmp1, TCGReg cmp2, bool c_cmp2, 1496a31768c0STANG Tiancheng TCGReg val1, bool c_val1, 1497a31768c0STANG Tiancheng TCGReg val2, bool c_val2) 1498a31768c0STANG Tiancheng{ 1499a31768c0STANG Tiancheng set_vtype_len_sew(s, type, vece); 1500a31768c0STANG Tiancheng 1501a31768c0STANG Tiancheng /* Use only vmerge_vim if possible, by inverting the test. */ 1502a31768c0STANG Tiancheng if (c_val2 && !c_val1) { 1503a31768c0STANG Tiancheng TCGArg temp = val1; 1504a31768c0STANG Tiancheng cond = tcg_invert_cond(cond); 1505a31768c0STANG Tiancheng val1 = val2; 1506a31768c0STANG Tiancheng val2 = temp; 1507a31768c0STANG Tiancheng c_val1 = true; 1508a31768c0STANG Tiancheng c_val2 = false; 1509a31768c0STANG Tiancheng } 1510a31768c0STANG Tiancheng 1511a31768c0STANG Tiancheng /* Perform the comparison into V0 mask. */ 1512a31768c0STANG Tiancheng if (c_cmp2) { 1513a31768c0STANG Tiancheng tcg_out_opc_vi(s, tcg_cmpcond_to_rvv_vi[cond].op, TCG_REG_V0, cmp1, 1514a31768c0STANG Tiancheng cmp2 - tcg_cmpcond_to_rvv_vi[cond].adjust); 1515a31768c0STANG Tiancheng } else if (tcg_cmpcond_to_rvv_vv[cond].swap) { 1516a31768c0STANG Tiancheng tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op, 1517a31768c0STANG Tiancheng TCG_REG_V0, cmp2, cmp1); 1518a31768c0STANG Tiancheng } else { 1519a31768c0STANG Tiancheng tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op, 1520a31768c0STANG Tiancheng TCG_REG_V0, cmp1, cmp2); 1521a31768c0STANG Tiancheng } 1522a31768c0STANG Tiancheng if (c_val1) { 1523a31768c0STANG Tiancheng if (c_val2) { 1524a31768c0STANG Tiancheng tcg_out_opc_vi(s, OPC_VMV_V_I, ret, 0, val2); 1525a31768c0STANG Tiancheng val2 = ret; 1526a31768c0STANG Tiancheng } 1527a31768c0STANG Tiancheng /* vd[i] == v0.mask[i] ? imm : vs2[i] */ 1528a31768c0STANG Tiancheng tcg_out_opc_vim_mask(s, OPC_VMERGE_VIM, ret, val2, val1); 1529a31768c0STANG Tiancheng } else { 1530a31768c0STANG Tiancheng /* vd[i] == v0.mask[i] ? vs1[i] : vs2[i] */ 1531a31768c0STANG Tiancheng tcg_out_opc_vvm_mask(s, OPC_VMERGE_VVM, ret, val2, val1); 1532a31768c0STANG Tiancheng } 1533a31768c0STANG Tiancheng} 1534a31768c0STANG Tiancheng 1535f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s) 1536f63e7089SHuang Shiyuan{ 1537f63e7089SHuang Shiyuan s->riscv_cur_type = TCG_TYPE_COUNT; 1538f63e7089SHuang Shiyuan} 1539f63e7089SHuang Shiyuan 15402be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) 1541139c1837SPaolo Bonzini{ 1542139c1837SPaolo Bonzini TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; 1543139c1837SPaolo Bonzini ptrdiff_t offset = tcg_pcrel_diff(s, arg); 1544139c1837SPaolo Bonzini int ret; 1545139c1837SPaolo Bonzini 1546f63e7089SHuang Shiyuan init_setting_vtype(s); 1547f63e7089SHuang Shiyuan 1548844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 1549844d0442SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 1550139c1837SPaolo Bonzini /* short jump: -2097150 to 2097152 */ 1551139c1837SPaolo Bonzini tcg_out_opc_jump(s, OPC_JAL, link, offset); 1552aeb6326eSRichard Henderson } else if (offset == (int32_t)offset) { 1553139c1837SPaolo Bonzini /* long jump: -2147483646 to 2147483648 */ 1554139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0); 1555139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0); 1556844d0442SRichard Henderson ret = reloc_call(s->code_ptr - 2, arg); 1557139c1837SPaolo Bonzini tcg_debug_assert(ret == true); 1558aeb6326eSRichard Henderson } else { 1559139c1837SPaolo Bonzini /* far jump: 64-bit */ 1560139c1837SPaolo Bonzini tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12); 1561139c1837SPaolo Bonzini tcg_target_long base = (tcg_target_long)arg - imm; 1562139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base); 1563139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm); 1564139c1837SPaolo Bonzini } 1565139c1837SPaolo Bonzini} 1566139c1837SPaolo Bonzini 1567cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg, 1568cee44b03SRichard Henderson const TCGHelperInfo *info) 1569139c1837SPaolo Bonzini{ 1570139c1837SPaolo Bonzini tcg_out_call_int(s, arg, false); 1571139c1837SPaolo Bonzini} 1572139c1837SPaolo Bonzini 1573139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0) 1574139c1837SPaolo Bonzini{ 1575139c1837SPaolo Bonzini tcg_insn_unit insn = OPC_FENCE; 1576139c1837SPaolo Bonzini 1577139c1837SPaolo Bonzini if (a0 & TCG_MO_LD_LD) { 1578139c1837SPaolo Bonzini insn |= 0x02200000; 1579139c1837SPaolo Bonzini } 1580139c1837SPaolo Bonzini if (a0 & TCG_MO_ST_LD) { 1581139c1837SPaolo Bonzini insn |= 0x01200000; 1582139c1837SPaolo Bonzini } 1583139c1837SPaolo Bonzini if (a0 & TCG_MO_LD_ST) { 1584139c1837SPaolo Bonzini insn |= 0x02100000; 1585139c1837SPaolo Bonzini } 1586139c1837SPaolo Bonzini if (a0 & TCG_MO_ST_ST) { 1587139c1837SPaolo Bonzini insn |= 0x02200000; 1588139c1837SPaolo Bonzini } 1589139c1837SPaolo Bonzini tcg_out32(s, insn); 1590139c1837SPaolo Bonzini} 1591139c1837SPaolo Bonzini 1592139c1837SPaolo Bonzini/* 1593139c1837SPaolo Bonzini * Load/store and TLB 1594139c1837SPaolo Bonzini */ 1595139c1837SPaolo Bonzini 1596793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) 1597844d0442SRichard Henderson{ 1598844d0442SRichard Henderson tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0); 1599844d0442SRichard Henderson bool ok = reloc_jimm20(s->code_ptr - 1, target); 1600844d0442SRichard Henderson tcg_debug_assert(ok); 1601844d0442SRichard Henderson} 1602844d0442SRichard Henderson 16037b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop) 16047b880107SRichard Henderson{ 16057b880107SRichard Henderson return false; 16067b880107SRichard Henderson} 16077b880107SRichard Henderson 160861b6daafSRichard Henderson/* We have three temps, we might as well expose them. */ 160961b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = { 161061b6daafSRichard Henderson .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 } 161161b6daafSRichard Henderson}; 161261b6daafSRichard Henderson 1613139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1614139c1837SPaolo Bonzini{ 161561b6daafSRichard Henderson MemOp opc = get_memop(l->oi); 1616139c1837SPaolo Bonzini 1617139c1837SPaolo Bonzini /* resolve label address */ 1618793f7381SRichard Henderson if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1619139c1837SPaolo Bonzini return false; 1620139c1837SPaolo Bonzini } 1621139c1837SPaolo Bonzini 1622139c1837SPaolo Bonzini /* call load helper */ 162361b6daafSRichard Henderson tcg_out_ld_helper_args(s, l, &ldst_helper_param); 1624cee44b03SRichard Henderson tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false); 162561b6daafSRichard Henderson tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param); 1626139c1837SPaolo Bonzini 1627139c1837SPaolo Bonzini tcg_out_goto(s, l->raddr); 1628139c1837SPaolo Bonzini return true; 1629139c1837SPaolo Bonzini} 1630139c1837SPaolo Bonzini 1631139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1632139c1837SPaolo Bonzini{ 163361b6daafSRichard Henderson MemOp opc = get_memop(l->oi); 1634139c1837SPaolo Bonzini 1635139c1837SPaolo Bonzini /* resolve label address */ 1636793f7381SRichard Henderson if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1637139c1837SPaolo Bonzini return false; 1638139c1837SPaolo Bonzini } 1639139c1837SPaolo Bonzini 1640139c1837SPaolo Bonzini /* call store helper */ 164161b6daafSRichard Henderson tcg_out_st_helper_args(s, l, &ldst_helper_param); 1642cee44b03SRichard Henderson tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false); 1643139c1837SPaolo Bonzini 1644139c1837SPaolo Bonzini tcg_out_goto(s, l->raddr); 1645139c1837SPaolo Bonzini return true; 1646139c1837SPaolo Bonzini} 1647139c1837SPaolo Bonzini 1648d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV. */ 1649d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS -(1 << 11) 1650d0a9bb5eSRichard Henderson 1651001dddfeSRichard Henderson/* 16527893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare. 16537893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests. 1654001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path 1655001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path. 1656001dddfeSRichard Henderson */ 1657001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase, 1658001dddfeSRichard Henderson TCGReg addr_reg, MemOpIdx oi, 1659001dddfeSRichard Henderson bool is_ld) 1660001dddfeSRichard Henderson{ 16618aefe1fbSRichard Henderson TCGType addr_type = s->addr_type; 1662001dddfeSRichard Henderson TCGLabelQemuLdst *ldst = NULL; 1663001dddfeSRichard Henderson MemOp opc = get_memop(oi); 166437e523f0SRichard Henderson TCGAtomAlign aa; 166537e523f0SRichard Henderson unsigned a_mask; 166637e523f0SRichard Henderson 166737e523f0SRichard Henderson aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false); 166837e523f0SRichard Henderson a_mask = (1u << aa.align) - 1; 1669001dddfeSRichard Henderson 16704944d359SRichard Henderson if (tcg_use_softmmu) { 1671001dddfeSRichard Henderson unsigned s_bits = opc & MO_SIZE; 1672933b331bSRichard Henderson unsigned s_mask = (1u << s_bits) - 1; 1673001dddfeSRichard Henderson int mem_index = get_mmuidx(oi); 1674d0a9bb5eSRichard Henderson int fast_ofs = tlb_mask_table_ofs(s, mem_index); 1675001dddfeSRichard Henderson int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); 1676001dddfeSRichard Henderson int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); 1677933b331bSRichard Henderson int compare_mask; 1678933b331bSRichard Henderson TCGReg addr_adj; 1679001dddfeSRichard Henderson 1680001dddfeSRichard Henderson ldst = new_ldst_label(s); 1681001dddfeSRichard Henderson ldst->is_ld = is_ld; 1682001dddfeSRichard Henderson ldst->oi = oi; 1683001dddfeSRichard Henderson ldst->addrlo_reg = addr_reg; 1684001dddfeSRichard Henderson 1685f63e7089SHuang Shiyuan init_setting_vtype(s); 1686f63e7089SHuang Shiyuan 1687933b331bSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); 1688933b331bSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); 1689001dddfeSRichard Henderson 1690001dddfeSRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg, 1691aece72b7SRichard Henderson s->page_bits - CPU_TLB_ENTRY_BITS); 1692001dddfeSRichard Henderson tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); 1693001dddfeSRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); 1694001dddfeSRichard Henderson 1695933b331bSRichard Henderson /* 16964944d359SRichard Henderson * For aligned accesses, we check the first byte and include the 16974944d359SRichard Henderson * alignment bits within the address. For unaligned access, we 16984944d359SRichard Henderson * check that we don't cross pages using the address of the last 16994944d359SRichard Henderson * byte of the access. 1700933b331bSRichard Henderson */ 1701933b331bSRichard Henderson addr_adj = addr_reg; 170237e523f0SRichard Henderson if (a_mask < s_mask) { 1703933b331bSRichard Henderson addr_adj = TCG_REG_TMP0; 17048aefe1fbSRichard Henderson tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI, 1705933b331bSRichard Henderson addr_adj, addr_reg, s_mask - a_mask); 1706933b331bSRichard Henderson } 1707aece72b7SRichard Henderson compare_mask = s->page_mask | a_mask; 1708933b331bSRichard Henderson if (compare_mask == sextreg(compare_mask, 0, 12)) { 1709933b331bSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask); 1710933b331bSRichard Henderson } else { 17118aefe1fbSRichard Henderson tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask); 1712933b331bSRichard Henderson tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj); 1713933b331bSRichard Henderson } 1714933b331bSRichard Henderson 1715001dddfeSRichard Henderson /* Load the tlb comparator and the addend. */ 1716238f4380SRichard Henderson QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN); 17178aefe1fbSRichard Henderson tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2, 1718001dddfeSRichard Henderson is_ld ? offsetof(CPUTLBEntry, addr_read) 1719001dddfeSRichard Henderson : offsetof(CPUTLBEntry, addr_write)); 1720001dddfeSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, 1721001dddfeSRichard Henderson offsetof(CPUTLBEntry, addend)); 1722001dddfeSRichard Henderson 1723001dddfeSRichard Henderson /* Compare masked address with the TLB entry. */ 1724001dddfeSRichard Henderson ldst->label_ptr[0] = s->code_ptr; 1725001dddfeSRichard Henderson tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0); 1726001dddfeSRichard Henderson 1727001dddfeSRichard Henderson /* TLB Hit - translate address using addend. */ 17288aefe1fbSRichard Henderson if (addr_type != TCG_TYPE_I32) { 1729eda15159SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2); 1730b86c6ba6SRichard Henderson } else if (cpuinfo & CPUINFO_ZBA) { 17314944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, 17324944d359SRichard Henderson addr_reg, TCG_REG_TMP2); 1733eda15159SRichard Henderson } else { 1734eda15159SRichard Henderson tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg); 17354944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, 17364944d359SRichard Henderson TCG_REG_TMP0, TCG_REG_TMP2); 1737001dddfeSRichard Henderson } 1738001dddfeSRichard Henderson *pbase = TCG_REG_TMP0; 17394944d359SRichard Henderson } else { 1740eda15159SRichard Henderson TCGReg base; 1741eda15159SRichard Henderson 1742001dddfeSRichard Henderson if (a_mask) { 1743001dddfeSRichard Henderson ldst = new_ldst_label(s); 1744001dddfeSRichard Henderson ldst->is_ld = is_ld; 1745001dddfeSRichard Henderson ldst->oi = oi; 1746001dddfeSRichard Henderson ldst->addrlo_reg = addr_reg; 1747001dddfeSRichard Henderson 1748f63e7089SHuang Shiyuan init_setting_vtype(s); 1749f63e7089SHuang Shiyuan 175037e523f0SRichard Henderson /* We are expecting alignment max 7, so we can always use andi. */ 175137e523f0SRichard Henderson tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12)); 1752001dddfeSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask); 1753001dddfeSRichard Henderson 1754001dddfeSRichard Henderson ldst->label_ptr[0] = s->code_ptr; 1755001dddfeSRichard Henderson tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0); 1756001dddfeSRichard Henderson } 1757001dddfeSRichard Henderson 1758001dddfeSRichard Henderson if (guest_base != 0) { 1759001dddfeSRichard Henderson base = TCG_REG_TMP0; 17608aefe1fbSRichard Henderson if (addr_type != TCG_TYPE_I32) { 17614944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, 17624944d359SRichard Henderson TCG_GUEST_BASE_REG); 1763b86c6ba6SRichard Henderson } else if (cpuinfo & CPUINFO_ZBA) { 17644944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, 17654944d359SRichard Henderson TCG_GUEST_BASE_REG); 1766eda15159SRichard Henderson } else { 1767eda15159SRichard Henderson tcg_out_ext32u(s, base, addr_reg); 1768eda15159SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG); 1769eda15159SRichard Henderson } 17708aefe1fbSRichard Henderson } else if (addr_type != TCG_TYPE_I32) { 1771eda15159SRichard Henderson base = addr_reg; 1772eda15159SRichard Henderson } else { 1773eda15159SRichard Henderson base = TCG_REG_TMP0; 1774eda15159SRichard Henderson tcg_out_ext32u(s, base, addr_reg); 1775001dddfeSRichard Henderson } 1776001dddfeSRichard Henderson *pbase = base; 17774944d359SRichard Henderson } 1778001dddfeSRichard Henderson 1779001dddfeSRichard Henderson return ldst; 1780001dddfeSRichard Henderson} 1781001dddfeSRichard Henderson 1782aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val, 1783f7041977SRichard Henderson TCGReg base, MemOp opc, TCGType type) 1784139c1837SPaolo Bonzini{ 1785c86bd2dcSRichard Henderson /* Byte swapping is left to middle-end expansion. */ 1786c86bd2dcSRichard Henderson tcg_debug_assert((opc & MO_BSWAP) == 0); 1787139c1837SPaolo Bonzini 1788139c1837SPaolo Bonzini switch (opc & (MO_SSIZE)) { 1789139c1837SPaolo Bonzini case MO_UB: 1790aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LBU, val, base, 0); 1791139c1837SPaolo Bonzini break; 1792139c1837SPaolo Bonzini case MO_SB: 1793aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LB, val, base, 0); 1794139c1837SPaolo Bonzini break; 1795139c1837SPaolo Bonzini case MO_UW: 1796aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LHU, val, base, 0); 1797139c1837SPaolo Bonzini break; 1798139c1837SPaolo Bonzini case MO_SW: 1799aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LH, val, base, 0); 1800139c1837SPaolo Bonzini break; 1801139c1837SPaolo Bonzini case MO_UL: 1802f7041977SRichard Henderson if (type == TCG_TYPE_I64) { 1803aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LWU, val, base, 0); 1804139c1837SPaolo Bonzini break; 1805139c1837SPaolo Bonzini } 1806139c1837SPaolo Bonzini /* FALLTHRU */ 1807139c1837SPaolo Bonzini case MO_SL: 1808aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LW, val, base, 0); 1809139c1837SPaolo Bonzini break; 1810fc313c64SFrédéric Pétrot case MO_UQ: 1811aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LD, val, base, 0); 1812139c1837SPaolo Bonzini break; 1813139c1837SPaolo Bonzini default: 1814139c1837SPaolo Bonzini g_assert_not_reached(); 1815139c1837SPaolo Bonzini } 1816139c1837SPaolo Bonzini} 1817139c1837SPaolo Bonzini 1818f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1819f7041977SRichard Henderson MemOpIdx oi, TCGType data_type) 1820139c1837SPaolo Bonzini{ 1821001dddfeSRichard Henderson TCGLabelQemuLdst *ldst; 18222e3a933aSRichard Henderson TCGReg base; 1823139c1837SPaolo Bonzini 1824001dddfeSRichard Henderson ldst = prepare_host_addr(s, &base, addr_reg, oi, true); 1825001dddfeSRichard Henderson tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type); 1826f7041977SRichard Henderson 1827001dddfeSRichard Henderson if (ldst) { 1828001dddfeSRichard Henderson ldst->type = data_type; 1829001dddfeSRichard Henderson ldst->datalo_reg = data_reg; 1830001dddfeSRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1831a3fb7c99SRichard Henderson } 1832139c1837SPaolo Bonzini} 1833139c1837SPaolo Bonzini 1834aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val, 1835139c1837SPaolo Bonzini TCGReg base, MemOp opc) 1836139c1837SPaolo Bonzini{ 1837c86bd2dcSRichard Henderson /* Byte swapping is left to middle-end expansion. */ 1838c86bd2dcSRichard Henderson tcg_debug_assert((opc & MO_BSWAP) == 0); 1839139c1837SPaolo Bonzini 1840139c1837SPaolo Bonzini switch (opc & (MO_SSIZE)) { 1841139c1837SPaolo Bonzini case MO_8: 1842aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SB, base, val, 0); 1843139c1837SPaolo Bonzini break; 1844139c1837SPaolo Bonzini case MO_16: 1845aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SH, base, val, 0); 1846139c1837SPaolo Bonzini break; 1847139c1837SPaolo Bonzini case MO_32: 1848aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SW, base, val, 0); 1849139c1837SPaolo Bonzini break; 1850139c1837SPaolo Bonzini case MO_64: 1851aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SD, base, val, 0); 1852139c1837SPaolo Bonzini break; 1853139c1837SPaolo Bonzini default: 1854139c1837SPaolo Bonzini g_assert_not_reached(); 1855139c1837SPaolo Bonzini } 1856139c1837SPaolo Bonzini} 1857139c1837SPaolo Bonzini 1858f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1859f7041977SRichard Henderson MemOpIdx oi, TCGType data_type) 1860139c1837SPaolo Bonzini{ 1861001dddfeSRichard Henderson TCGLabelQemuLdst *ldst; 18622e3a933aSRichard Henderson TCGReg base; 1863139c1837SPaolo Bonzini 1864001dddfeSRichard Henderson ldst = prepare_host_addr(s, &base, addr_reg, oi, false); 1865001dddfeSRichard Henderson tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi)); 1866f7041977SRichard Henderson 1867001dddfeSRichard Henderson if (ldst) { 1868001dddfeSRichard Henderson ldst->type = data_type; 1869001dddfeSRichard Henderson ldst->datalo_reg = data_reg; 1870001dddfeSRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1871a3fb7c99SRichard Henderson } 1872139c1837SPaolo Bonzini} 1873139c1837SPaolo Bonzini 1874793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr; 1875139c1837SPaolo Bonzini 1876b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) 1877b55a8d9dSRichard Henderson{ 1878b55a8d9dSRichard Henderson /* Reuse the zeroing that exists for goto_ptr. */ 1879b55a8d9dSRichard Henderson if (a0 == 0) { 1880b55a8d9dSRichard Henderson tcg_out_call_int(s, tcg_code_gen_epilogue, true); 1881b55a8d9dSRichard Henderson } else { 1882b55a8d9dSRichard Henderson tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); 1883b55a8d9dSRichard Henderson tcg_out_call_int(s, tb_ret_addr, true); 1884b55a8d9dSRichard Henderson } 1885b55a8d9dSRichard Henderson} 1886b55a8d9dSRichard Henderson 1887cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which) 1888cf7d6b8eSRichard Henderson{ 1889493c9b19SRichard Henderson /* Direct branch will be patched by tb_target_set_jmp_target. */ 1890493c9b19SRichard Henderson set_jmp_insn_offset(s, which); 1891493c9b19SRichard Henderson tcg_out32(s, OPC_JAL); 1892493c9b19SRichard Henderson 1893493c9b19SRichard Henderson /* When branch is out of range, fall through to indirect. */ 1894cf7d6b8eSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, 1895cf7d6b8eSRichard Henderson get_jmp_target_addr(s, which)); 1896cf7d6b8eSRichard Henderson tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); 1897cf7d6b8eSRichard Henderson set_jmp_reset_offset(s, which); 1898cf7d6b8eSRichard Henderson} 1899cf7d6b8eSRichard Henderson 190090c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n, 190190c0fee3SRichard Henderson uintptr_t jmp_rx, uintptr_t jmp_rw) 190290c0fee3SRichard Henderson{ 1903493c9b19SRichard Henderson uintptr_t addr = tb->jmp_target_addr[n]; 1904493c9b19SRichard Henderson ptrdiff_t offset = addr - jmp_rx; 1905493c9b19SRichard Henderson tcg_insn_unit insn; 1906493c9b19SRichard Henderson 1907493c9b19SRichard Henderson /* Either directly branch, or fall through to indirect branch. */ 1908493c9b19SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 1909493c9b19SRichard Henderson insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset); 1910493c9b19SRichard Henderson } else { 1911493c9b19SRichard Henderson insn = OPC_NOP; 1912493c9b19SRichard Henderson } 1913493c9b19SRichard Henderson qatomic_set((uint32_t *)jmp_rw, insn); 1914493c9b19SRichard Henderson flush_idcache_range(jmp_rx, jmp_rw, 4); 191590c0fee3SRichard Henderson} 191690c0fee3SRichard Henderson 1917139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc, 19185e8892dbSMiroslav Rezanina const TCGArg args[TCG_MAX_OP_ARGS], 19195e8892dbSMiroslav Rezanina const int const_args[TCG_MAX_OP_ARGS]) 1920139c1837SPaolo Bonzini{ 1921139c1837SPaolo Bonzini TCGArg a0 = args[0]; 1922139c1837SPaolo Bonzini TCGArg a1 = args[1]; 1923139c1837SPaolo Bonzini TCGArg a2 = args[2]; 1924139c1837SPaolo Bonzini int c2 = const_args[2]; 1925139c1837SPaolo Bonzini 1926139c1837SPaolo Bonzini switch (opc) { 1927139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 1928139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0); 1929139c1837SPaolo Bonzini break; 1930139c1837SPaolo Bonzini 1931139c1837SPaolo Bonzini case INDEX_op_br: 1932139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0); 1933139c1837SPaolo Bonzini tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0); 1934139c1837SPaolo Bonzini break; 1935139c1837SPaolo Bonzini 1936139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 1937139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 1938139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LBU, a0, a1, a2); 1939139c1837SPaolo Bonzini break; 1940139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 1941139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 1942139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LB, a0, a1, a2); 1943139c1837SPaolo Bonzini break; 1944139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 1945139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 1946139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LHU, a0, a1, a2); 1947139c1837SPaolo Bonzini break; 1948139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 1949139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 1950139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LH, a0, a1, a2); 1951139c1837SPaolo Bonzini break; 1952139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 1953139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LWU, a0, a1, a2); 1954139c1837SPaolo Bonzini break; 1955139c1837SPaolo Bonzini case INDEX_op_ld_i32: 1956139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 1957139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LW, a0, a1, a2); 1958139c1837SPaolo Bonzini break; 1959139c1837SPaolo Bonzini case INDEX_op_ld_i64: 1960139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LD, a0, a1, a2); 1961139c1837SPaolo Bonzini break; 1962139c1837SPaolo Bonzini 1963139c1837SPaolo Bonzini case INDEX_op_st8_i32: 1964139c1837SPaolo Bonzini case INDEX_op_st8_i64: 1965139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SB, a0, a1, a2); 1966139c1837SPaolo Bonzini break; 1967139c1837SPaolo Bonzini case INDEX_op_st16_i32: 1968139c1837SPaolo Bonzini case INDEX_op_st16_i64: 1969139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SH, a0, a1, a2); 1970139c1837SPaolo Bonzini break; 1971139c1837SPaolo Bonzini case INDEX_op_st_i32: 1972139c1837SPaolo Bonzini case INDEX_op_st32_i64: 1973139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SW, a0, a1, a2); 1974139c1837SPaolo Bonzini break; 1975139c1837SPaolo Bonzini case INDEX_op_st_i64: 1976139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SD, a0, a1, a2); 1977139c1837SPaolo Bonzini break; 1978139c1837SPaolo Bonzini 1979139c1837SPaolo Bonzini case INDEX_op_add_i32: 1980139c1837SPaolo Bonzini if (c2) { 1981139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2); 1982139c1837SPaolo Bonzini } else { 1983139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2); 1984139c1837SPaolo Bonzini } 1985139c1837SPaolo Bonzini break; 1986139c1837SPaolo Bonzini case INDEX_op_add_i64: 1987139c1837SPaolo Bonzini if (c2) { 1988139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2); 1989139c1837SPaolo Bonzini } else { 1990139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2); 1991139c1837SPaolo Bonzini } 1992139c1837SPaolo Bonzini break; 1993139c1837SPaolo Bonzini 1994139c1837SPaolo Bonzini case INDEX_op_sub_i32: 1995139c1837SPaolo Bonzini if (c2) { 1996139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2); 1997139c1837SPaolo Bonzini } else { 1998139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2); 1999139c1837SPaolo Bonzini } 2000139c1837SPaolo Bonzini break; 2001139c1837SPaolo Bonzini case INDEX_op_sub_i64: 2002139c1837SPaolo Bonzini if (c2) { 2003139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2); 2004139c1837SPaolo Bonzini } else { 2005139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2); 2006139c1837SPaolo Bonzini } 2007139c1837SPaolo Bonzini break; 2008139c1837SPaolo Bonzini 2009139c1837SPaolo Bonzini case INDEX_op_and_i32: 2010139c1837SPaolo Bonzini case INDEX_op_and_i64: 2011139c1837SPaolo Bonzini if (c2) { 2012139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2); 2013139c1837SPaolo Bonzini } else { 2014139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_AND, a0, a1, a2); 2015139c1837SPaolo Bonzini } 2016139c1837SPaolo Bonzini break; 2017139c1837SPaolo Bonzini 2018139c1837SPaolo Bonzini case INDEX_op_or_i32: 2019139c1837SPaolo Bonzini case INDEX_op_or_i64: 2020139c1837SPaolo Bonzini if (c2) { 2021139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2); 2022139c1837SPaolo Bonzini } else { 2023139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_OR, a0, a1, a2); 2024139c1837SPaolo Bonzini } 2025139c1837SPaolo Bonzini break; 2026139c1837SPaolo Bonzini 2027139c1837SPaolo Bonzini case INDEX_op_xor_i32: 2028139c1837SPaolo Bonzini case INDEX_op_xor_i64: 2029139c1837SPaolo Bonzini if (c2) { 2030139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2); 2031139c1837SPaolo Bonzini } else { 2032139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2); 2033139c1837SPaolo Bonzini } 2034139c1837SPaolo Bonzini break; 2035139c1837SPaolo Bonzini 203699f4ec6eSRichard Henderson case INDEX_op_andc_i32: 203799f4ec6eSRichard Henderson case INDEX_op_andc_i64: 203899f4ec6eSRichard Henderson if (c2) { 203999f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2); 204099f4ec6eSRichard Henderson } else { 204199f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2); 204299f4ec6eSRichard Henderson } 204399f4ec6eSRichard Henderson break; 204499f4ec6eSRichard Henderson case INDEX_op_orc_i32: 204599f4ec6eSRichard Henderson case INDEX_op_orc_i64: 204699f4ec6eSRichard Henderson if (c2) { 204799f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2); 204899f4ec6eSRichard Henderson } else { 204999f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2); 205099f4ec6eSRichard Henderson } 205199f4ec6eSRichard Henderson break; 205299f4ec6eSRichard Henderson case INDEX_op_eqv_i32: 205399f4ec6eSRichard Henderson case INDEX_op_eqv_i64: 205499f4ec6eSRichard Henderson if (c2) { 205599f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2); 205699f4ec6eSRichard Henderson } else { 205799f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2); 205899f4ec6eSRichard Henderson } 205999f4ec6eSRichard Henderson break; 206099f4ec6eSRichard Henderson 2061139c1837SPaolo Bonzini case INDEX_op_not_i32: 2062139c1837SPaolo Bonzini case INDEX_op_not_i64: 2063139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1); 2064139c1837SPaolo Bonzini break; 2065139c1837SPaolo Bonzini 2066139c1837SPaolo Bonzini case INDEX_op_neg_i32: 2067139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1); 2068139c1837SPaolo Bonzini break; 2069139c1837SPaolo Bonzini case INDEX_op_neg_i64: 2070139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1); 2071139c1837SPaolo Bonzini break; 2072139c1837SPaolo Bonzini 2073139c1837SPaolo Bonzini case INDEX_op_mul_i32: 2074139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2); 2075139c1837SPaolo Bonzini break; 2076139c1837SPaolo Bonzini case INDEX_op_mul_i64: 2077139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2); 2078139c1837SPaolo Bonzini break; 2079139c1837SPaolo Bonzini 2080139c1837SPaolo Bonzini case INDEX_op_div_i32: 2081139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2); 2082139c1837SPaolo Bonzini break; 2083139c1837SPaolo Bonzini case INDEX_op_div_i64: 2084139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2); 2085139c1837SPaolo Bonzini break; 2086139c1837SPaolo Bonzini 2087139c1837SPaolo Bonzini case INDEX_op_divu_i32: 2088139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2); 2089139c1837SPaolo Bonzini break; 2090139c1837SPaolo Bonzini case INDEX_op_divu_i64: 2091139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2); 2092139c1837SPaolo Bonzini break; 2093139c1837SPaolo Bonzini 2094139c1837SPaolo Bonzini case INDEX_op_rem_i32: 2095139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2); 2096139c1837SPaolo Bonzini break; 2097139c1837SPaolo Bonzini case INDEX_op_rem_i64: 2098139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REM, a0, a1, a2); 2099139c1837SPaolo Bonzini break; 2100139c1837SPaolo Bonzini 2101139c1837SPaolo Bonzini case INDEX_op_remu_i32: 2102139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2); 2103139c1837SPaolo Bonzini break; 2104139c1837SPaolo Bonzini case INDEX_op_remu_i64: 2105139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2); 2106139c1837SPaolo Bonzini break; 2107139c1837SPaolo Bonzini 2108139c1837SPaolo Bonzini case INDEX_op_shl_i32: 2109139c1837SPaolo Bonzini if (c2) { 2110d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f); 2111139c1837SPaolo Bonzini } else { 2112139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2); 2113139c1837SPaolo Bonzini } 2114139c1837SPaolo Bonzini break; 2115139c1837SPaolo Bonzini case INDEX_op_shl_i64: 2116139c1837SPaolo Bonzini if (c2) { 2117d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f); 2118139c1837SPaolo Bonzini } else { 2119139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2); 2120139c1837SPaolo Bonzini } 2121139c1837SPaolo Bonzini break; 2122139c1837SPaolo Bonzini 2123139c1837SPaolo Bonzini case INDEX_op_shr_i32: 2124139c1837SPaolo Bonzini if (c2) { 2125d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f); 2126139c1837SPaolo Bonzini } else { 2127139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2); 2128139c1837SPaolo Bonzini } 2129139c1837SPaolo Bonzini break; 2130139c1837SPaolo Bonzini case INDEX_op_shr_i64: 2131139c1837SPaolo Bonzini if (c2) { 2132d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f); 2133139c1837SPaolo Bonzini } else { 2134139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2); 2135139c1837SPaolo Bonzini } 2136139c1837SPaolo Bonzini break; 2137139c1837SPaolo Bonzini 2138139c1837SPaolo Bonzini case INDEX_op_sar_i32: 2139139c1837SPaolo Bonzini if (c2) { 2140d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f); 2141139c1837SPaolo Bonzini } else { 2142139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2); 2143139c1837SPaolo Bonzini } 2144139c1837SPaolo Bonzini break; 2145139c1837SPaolo Bonzini case INDEX_op_sar_i64: 2146139c1837SPaolo Bonzini if (c2) { 2147d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f); 2148139c1837SPaolo Bonzini } else { 2149139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2); 2150139c1837SPaolo Bonzini } 2151139c1837SPaolo Bonzini break; 2152139c1837SPaolo Bonzini 215319d016adSRichard Henderson case INDEX_op_rotl_i32: 215419d016adSRichard Henderson if (c2) { 215519d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f); 215619d016adSRichard Henderson } else { 215719d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2); 215819d016adSRichard Henderson } 215919d016adSRichard Henderson break; 216019d016adSRichard Henderson case INDEX_op_rotl_i64: 216119d016adSRichard Henderson if (c2) { 216219d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f); 216319d016adSRichard Henderson } else { 216419d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2); 216519d016adSRichard Henderson } 216619d016adSRichard Henderson break; 216719d016adSRichard Henderson 216819d016adSRichard Henderson case INDEX_op_rotr_i32: 216919d016adSRichard Henderson if (c2) { 217019d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f); 217119d016adSRichard Henderson } else { 217219d016adSRichard Henderson tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2); 217319d016adSRichard Henderson } 217419d016adSRichard Henderson break; 217519d016adSRichard Henderson case INDEX_op_rotr_i64: 217619d016adSRichard Henderson if (c2) { 217719d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f); 217819d016adSRichard Henderson } else { 217919d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2); 218019d016adSRichard Henderson } 218119d016adSRichard Henderson break; 218219d016adSRichard Henderson 21837b4d5274SRichard Henderson case INDEX_op_bswap64_i64: 21847b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 21857b4d5274SRichard Henderson break; 21867b4d5274SRichard Henderson case INDEX_op_bswap32_i32: 21877b4d5274SRichard Henderson a2 = 0; 21887b4d5274SRichard Henderson /* fall through */ 21897b4d5274SRichard Henderson case INDEX_op_bswap32_i64: 21907b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 21917b4d5274SRichard Henderson if (a2 & TCG_BSWAP_OZ) { 21927b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32); 21937b4d5274SRichard Henderson } else { 21947b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32); 21957b4d5274SRichard Henderson } 21967b4d5274SRichard Henderson break; 21977b4d5274SRichard Henderson case INDEX_op_bswap16_i64: 21987b4d5274SRichard Henderson case INDEX_op_bswap16_i32: 21997b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 22007b4d5274SRichard Henderson if (a2 & TCG_BSWAP_OZ) { 22017b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48); 22027b4d5274SRichard Henderson } else { 22037b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48); 22047b4d5274SRichard Henderson } 22057b4d5274SRichard Henderson break; 22067b4d5274SRichard Henderson 22070956ecdaSRichard Henderson case INDEX_op_ctpop_i32: 22080956ecdaSRichard Henderson tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0); 22090956ecdaSRichard Henderson break; 22100956ecdaSRichard Henderson case INDEX_op_ctpop_i64: 22110956ecdaSRichard Henderson tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0); 22120956ecdaSRichard Henderson break; 22130956ecdaSRichard Henderson 2214a30498fcSRichard Henderson case INDEX_op_clz_i32: 2215a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2); 2216a30498fcSRichard Henderson break; 2217a30498fcSRichard Henderson case INDEX_op_clz_i64: 2218a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2); 2219a30498fcSRichard Henderson break; 2220a30498fcSRichard Henderson case INDEX_op_ctz_i32: 2221a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2); 2222a30498fcSRichard Henderson break; 2223a30498fcSRichard Henderson case INDEX_op_ctz_i64: 2224a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2); 2225a30498fcSRichard Henderson break; 2226a30498fcSRichard Henderson 2227139c1837SPaolo Bonzini case INDEX_op_add2_i32: 2228139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2229139c1837SPaolo Bonzini const_args[4], const_args[5], false, true); 2230139c1837SPaolo Bonzini break; 2231139c1837SPaolo Bonzini case INDEX_op_add2_i64: 2232139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2233139c1837SPaolo Bonzini const_args[4], const_args[5], false, false); 2234139c1837SPaolo Bonzini break; 2235139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 2236139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2237139c1837SPaolo Bonzini const_args[4], const_args[5], true, true); 2238139c1837SPaolo Bonzini break; 2239139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 2240139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2241139c1837SPaolo Bonzini const_args[4], const_args[5], true, false); 2242139c1837SPaolo Bonzini break; 2243139c1837SPaolo Bonzini 2244139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 2245139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 2246139c1837SPaolo Bonzini tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); 2247139c1837SPaolo Bonzini break; 2248139c1837SPaolo Bonzini 2249139c1837SPaolo Bonzini case INDEX_op_setcond_i32: 2250139c1837SPaolo Bonzini case INDEX_op_setcond_i64: 2251f6453695SRichard Henderson tcg_out_setcond(s, args[3], a0, a1, a2, c2); 2252139c1837SPaolo Bonzini break; 2253139c1837SPaolo Bonzini 225441e4c0a9SRichard Henderson case INDEX_op_negsetcond_i32: 225541e4c0a9SRichard Henderson case INDEX_op_negsetcond_i64: 225641e4c0a9SRichard Henderson tcg_out_negsetcond(s, args[3], a0, a1, a2, c2); 225741e4c0a9SRichard Henderson break; 225841e4c0a9SRichard Henderson 2259a18d783eSRichard Henderson case INDEX_op_movcond_i32: 2260a18d783eSRichard Henderson case INDEX_op_movcond_i64: 2261a18d783eSRichard Henderson tcg_out_movcond(s, args[5], a0, a1, a2, c2, 2262a18d783eSRichard Henderson args[3], const_args[3], args[4], const_args[4]); 2263a18d783eSRichard Henderson break; 2264a18d783eSRichard Henderson 2265fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 2266fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 2267f7041977SRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); 2268139c1837SPaolo Bonzini break; 2269fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 2270fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 2271f7041977SRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64); 2272139c1837SPaolo Bonzini break; 2273fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 2274fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 2275f7041977SRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32); 2276139c1837SPaolo Bonzini break; 2277fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 2278fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 2279f7041977SRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64); 2280139c1837SPaolo Bonzini break; 2281139c1837SPaolo Bonzini 2282139c1837SPaolo Bonzini case INDEX_op_extrh_i64_i32: 2283139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32); 2284139c1837SPaolo Bonzini break; 2285139c1837SPaolo Bonzini 2286139c1837SPaolo Bonzini case INDEX_op_mulsh_i32: 2287139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 2288139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2); 2289139c1837SPaolo Bonzini break; 2290139c1837SPaolo Bonzini 2291139c1837SPaolo Bonzini case INDEX_op_muluh_i32: 2292139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 2293139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2); 2294139c1837SPaolo Bonzini break; 2295139c1837SPaolo Bonzini 2296139c1837SPaolo Bonzini case INDEX_op_mb: 2297139c1837SPaolo Bonzini tcg_out_mb(s, a0); 2298139c1837SPaolo Bonzini break; 2299139c1837SPaolo Bonzini 2300139c1837SPaolo Bonzini case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ 2301139c1837SPaolo Bonzini case INDEX_op_mov_i64: 2302139c1837SPaolo Bonzini case INDEX_op_call: /* Always emitted via tcg_out_call. */ 2303b55a8d9dSRichard Henderson case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ 2304cf7d6b8eSRichard Henderson case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ 2305678155b2SRichard Henderson case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */ 2306678155b2SRichard Henderson case INDEX_op_ext8s_i64: 2307d0e66c89SRichard Henderson case INDEX_op_ext8u_i32: 2308d0e66c89SRichard Henderson case INDEX_op_ext8u_i64: 2309753e42eaSRichard Henderson case INDEX_op_ext16s_i32: 2310753e42eaSRichard Henderson case INDEX_op_ext16s_i64: 2311379afdffSRichard Henderson case INDEX_op_ext16u_i32: 2312379afdffSRichard Henderson case INDEX_op_ext16u_i64: 231352bf3398SRichard Henderson case INDEX_op_ext32s_i64: 23149ecf5f61SRichard Henderson case INDEX_op_ext32u_i64: 23159c6aa274SRichard Henderson case INDEX_op_ext_i32_i64: 2316b9bfe000SRichard Henderson case INDEX_op_extu_i32_i64: 2317b8b94ac6SRichard Henderson case INDEX_op_extrl_i64_i32: 2318139c1837SPaolo Bonzini default: 2319139c1837SPaolo Bonzini g_assert_not_reached(); 2320139c1837SPaolo Bonzini } 2321139c1837SPaolo Bonzini} 2322139c1837SPaolo Bonzini 2323f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, 2324f63e7089SHuang Shiyuan unsigned vecl, unsigned vece, 2325f63e7089SHuang Shiyuan const TCGArg args[TCG_MAX_OP_ARGS], 2326f63e7089SHuang Shiyuan const int const_args[TCG_MAX_OP_ARGS]) 2327f63e7089SHuang Shiyuan{ 2328f63e7089SHuang Shiyuan TCGType type = vecl + TCG_TYPE_V64; 2329f63e7089SHuang Shiyuan TCGArg a0, a1, a2; 23305a63f599STANG Tiancheng int c2; 2331f63e7089SHuang Shiyuan 2332f63e7089SHuang Shiyuan a0 = args[0]; 2333f63e7089SHuang Shiyuan a1 = args[1]; 2334f63e7089SHuang Shiyuan a2 = args[2]; 23355a63f599STANG Tiancheng c2 = const_args[2]; 2336f63e7089SHuang Shiyuan 2337f63e7089SHuang Shiyuan switch (opc) { 2338d4be6ee1STANG Tiancheng case INDEX_op_dupm_vec: 2339d4be6ee1STANG Tiancheng tcg_out_dupm_vec(s, type, vece, a0, a1, a2); 2340d4be6ee1STANG Tiancheng break; 2341f63e7089SHuang Shiyuan case INDEX_op_ld_vec: 2342f63e7089SHuang Shiyuan tcg_out_ld(s, type, a0, a1, a2); 2343f63e7089SHuang Shiyuan break; 2344f63e7089SHuang Shiyuan case INDEX_op_st_vec: 2345f63e7089SHuang Shiyuan tcg_out_st(s, type, a0, a1, a2); 2346f63e7089SHuang Shiyuan break; 23475a63f599STANG Tiancheng case INDEX_op_add_vec: 23485a63f599STANG Tiancheng set_vtype_len_sew(s, type, vece); 23495a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VADD_VV, OPC_VADD_VI, a0, a1, a2, c2); 23505a63f599STANG Tiancheng break; 23515a63f599STANG Tiancheng case INDEX_op_sub_vec: 23525a63f599STANG Tiancheng set_vtype_len_sew(s, type, vece); 23535a63f599STANG Tiancheng tcg_out_opc_vv(s, OPC_VSUB_VV, a0, a1, a2); 23545a63f599STANG Tiancheng break; 23555a63f599STANG Tiancheng case INDEX_op_and_vec: 23565a63f599STANG Tiancheng set_vtype_len(s, type); 23575a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VAND_VV, OPC_VAND_VI, a0, a1, a2, c2); 23585a63f599STANG Tiancheng break; 23595a63f599STANG Tiancheng case INDEX_op_or_vec: 23605a63f599STANG Tiancheng set_vtype_len(s, type); 23615a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VOR_VV, OPC_VOR_VI, a0, a1, a2, c2); 23625a63f599STANG Tiancheng break; 23635a63f599STANG Tiancheng case INDEX_op_xor_vec: 23645a63f599STANG Tiancheng set_vtype_len(s, type); 23655a63f599STANG Tiancheng tcg_out_opc_vv_vi(s, OPC_VXOR_VV, OPC_VXOR_VI, a0, a1, a2, c2); 23665a63f599STANG Tiancheng break; 23675a63f599STANG Tiancheng case INDEX_op_not_vec: 23685a63f599STANG Tiancheng set_vtype_len(s, type); 23695a63f599STANG Tiancheng tcg_out_opc_vi(s, OPC_VXOR_VI, a0, a1, -1); 23705a63f599STANG Tiancheng break; 2371*c283c074STANG Tiancheng case INDEX_op_neg_vec: 2372*c283c074STANG Tiancheng set_vtype_len_sew(s, type, vece); 2373*c283c074STANG Tiancheng tcg_out_opc_vi(s, OPC_VRSUB_VI, a0, a1, 0); 2374*c283c074STANG Tiancheng break; 2375a31768c0STANG Tiancheng case INDEX_op_cmp_vec: 2376a31768c0STANG Tiancheng tcg_out_cmpsel(s, type, vece, args[3], a0, a1, a2, c2, 2377a31768c0STANG Tiancheng -1, true, 0, true); 2378a31768c0STANG Tiancheng break; 2379a31768c0STANG Tiancheng case INDEX_op_cmpsel_vec: 2380a31768c0STANG Tiancheng tcg_out_cmpsel(s, type, vece, args[5], a0, a1, a2, c2, 2381a31768c0STANG Tiancheng args[3], const_args[3], args[4], const_args[4]); 2382a31768c0STANG Tiancheng break; 2383f63e7089SHuang Shiyuan case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */ 2384f63e7089SHuang Shiyuan case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */ 2385f63e7089SHuang Shiyuan default: 2386f63e7089SHuang Shiyuan g_assert_not_reached(); 2387f63e7089SHuang Shiyuan } 2388f63e7089SHuang Shiyuan} 2389f63e7089SHuang Shiyuan 2390f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, 2391f63e7089SHuang Shiyuan TCGArg a0, ...) 2392f63e7089SHuang Shiyuan{ 2393f63e7089SHuang Shiyuan g_assert_not_reached(); 2394f63e7089SHuang Shiyuan} 2395f63e7089SHuang Shiyuan 2396f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) 2397f63e7089SHuang Shiyuan{ 2398f63e7089SHuang Shiyuan switch (opc) { 23995a63f599STANG Tiancheng case INDEX_op_add_vec: 24005a63f599STANG Tiancheng case INDEX_op_sub_vec: 24015a63f599STANG Tiancheng case INDEX_op_and_vec: 24025a63f599STANG Tiancheng case INDEX_op_or_vec: 24035a63f599STANG Tiancheng case INDEX_op_xor_vec: 24045a63f599STANG Tiancheng case INDEX_op_not_vec: 2405*c283c074STANG Tiancheng case INDEX_op_neg_vec: 2406a31768c0STANG Tiancheng case INDEX_op_cmp_vec: 2407a31768c0STANG Tiancheng case INDEX_op_cmpsel_vec: 24085a63f599STANG Tiancheng return 1; 2409f63e7089SHuang Shiyuan default: 2410f63e7089SHuang Shiyuan return 0; 2411f63e7089SHuang Shiyuan } 2412f63e7089SHuang Shiyuan} 2413f63e7089SHuang Shiyuan 2414665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) 2415139c1837SPaolo Bonzini{ 2416139c1837SPaolo Bonzini switch (op) { 2417139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 2418665be288SRichard Henderson return C_O0_I1(r); 2419139c1837SPaolo Bonzini 2420139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 2421139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 2422139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 2423139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 2424139c1837SPaolo Bonzini case INDEX_op_ld_i32: 2425139c1837SPaolo Bonzini case INDEX_op_not_i32: 2426139c1837SPaolo Bonzini case INDEX_op_neg_i32: 2427139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 2428139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 2429139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 2430139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 2431139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 2432139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 2433139c1837SPaolo Bonzini case INDEX_op_ld_i64: 2434139c1837SPaolo Bonzini case INDEX_op_not_i64: 2435139c1837SPaolo Bonzini case INDEX_op_neg_i64: 2436139c1837SPaolo Bonzini case INDEX_op_ext8u_i32: 2437139c1837SPaolo Bonzini case INDEX_op_ext8u_i64: 2438139c1837SPaolo Bonzini case INDEX_op_ext16u_i32: 2439139c1837SPaolo Bonzini case INDEX_op_ext16u_i64: 2440139c1837SPaolo Bonzini case INDEX_op_ext32u_i64: 2441139c1837SPaolo Bonzini case INDEX_op_extu_i32_i64: 2442139c1837SPaolo Bonzini case INDEX_op_ext8s_i32: 2443139c1837SPaolo Bonzini case INDEX_op_ext8s_i64: 2444139c1837SPaolo Bonzini case INDEX_op_ext16s_i32: 2445139c1837SPaolo Bonzini case INDEX_op_ext16s_i64: 2446139c1837SPaolo Bonzini case INDEX_op_ext32s_i64: 2447139c1837SPaolo Bonzini case INDEX_op_extrl_i64_i32: 2448139c1837SPaolo Bonzini case INDEX_op_extrh_i64_i32: 2449139c1837SPaolo Bonzini case INDEX_op_ext_i32_i64: 24507b4d5274SRichard Henderson case INDEX_op_bswap16_i32: 24517b4d5274SRichard Henderson case INDEX_op_bswap32_i32: 24527b4d5274SRichard Henderson case INDEX_op_bswap16_i64: 24537b4d5274SRichard Henderson case INDEX_op_bswap32_i64: 24547b4d5274SRichard Henderson case INDEX_op_bswap64_i64: 24550956ecdaSRichard Henderson case INDEX_op_ctpop_i32: 24560956ecdaSRichard Henderson case INDEX_op_ctpop_i64: 2457665be288SRichard Henderson return C_O1_I1(r, r); 2458139c1837SPaolo Bonzini 2459139c1837SPaolo Bonzini case INDEX_op_st8_i32: 2460139c1837SPaolo Bonzini case INDEX_op_st16_i32: 2461139c1837SPaolo Bonzini case INDEX_op_st_i32: 2462139c1837SPaolo Bonzini case INDEX_op_st8_i64: 2463139c1837SPaolo Bonzini case INDEX_op_st16_i64: 2464139c1837SPaolo Bonzini case INDEX_op_st32_i64: 2465139c1837SPaolo Bonzini case INDEX_op_st_i64: 2466665be288SRichard Henderson return C_O0_I2(rZ, r); 2467139c1837SPaolo Bonzini 2468139c1837SPaolo Bonzini case INDEX_op_add_i32: 2469139c1837SPaolo Bonzini case INDEX_op_and_i32: 2470139c1837SPaolo Bonzini case INDEX_op_or_i32: 2471139c1837SPaolo Bonzini case INDEX_op_xor_i32: 2472139c1837SPaolo Bonzini case INDEX_op_add_i64: 2473139c1837SPaolo Bonzini case INDEX_op_and_i64: 2474139c1837SPaolo Bonzini case INDEX_op_or_i64: 2475139c1837SPaolo Bonzini case INDEX_op_xor_i64: 2476f6453695SRichard Henderson case INDEX_op_setcond_i32: 2477f6453695SRichard Henderson case INDEX_op_setcond_i64: 247841e4c0a9SRichard Henderson case INDEX_op_negsetcond_i32: 247941e4c0a9SRichard Henderson case INDEX_op_negsetcond_i64: 2480665be288SRichard Henderson return C_O1_I2(r, r, rI); 2481139c1837SPaolo Bonzini 248299f4ec6eSRichard Henderson case INDEX_op_andc_i32: 248399f4ec6eSRichard Henderson case INDEX_op_andc_i64: 248499f4ec6eSRichard Henderson case INDEX_op_orc_i32: 248599f4ec6eSRichard Henderson case INDEX_op_orc_i64: 248699f4ec6eSRichard Henderson case INDEX_op_eqv_i32: 248799f4ec6eSRichard Henderson case INDEX_op_eqv_i64: 248899f4ec6eSRichard Henderson return C_O1_I2(r, r, rJ); 248999f4ec6eSRichard Henderson 2490139c1837SPaolo Bonzini case INDEX_op_sub_i32: 2491139c1837SPaolo Bonzini case INDEX_op_sub_i64: 2492665be288SRichard Henderson return C_O1_I2(r, rZ, rN); 2493139c1837SPaolo Bonzini 2494139c1837SPaolo Bonzini case INDEX_op_mul_i32: 2495139c1837SPaolo Bonzini case INDEX_op_mulsh_i32: 2496139c1837SPaolo Bonzini case INDEX_op_muluh_i32: 2497139c1837SPaolo Bonzini case INDEX_op_div_i32: 2498139c1837SPaolo Bonzini case INDEX_op_divu_i32: 2499139c1837SPaolo Bonzini case INDEX_op_rem_i32: 2500139c1837SPaolo Bonzini case INDEX_op_remu_i32: 2501139c1837SPaolo Bonzini case INDEX_op_mul_i64: 2502139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 2503139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 2504139c1837SPaolo Bonzini case INDEX_op_div_i64: 2505139c1837SPaolo Bonzini case INDEX_op_divu_i64: 2506139c1837SPaolo Bonzini case INDEX_op_rem_i64: 2507139c1837SPaolo Bonzini case INDEX_op_remu_i64: 2508665be288SRichard Henderson return C_O1_I2(r, rZ, rZ); 2509139c1837SPaolo Bonzini 2510139c1837SPaolo Bonzini case INDEX_op_shl_i32: 2511139c1837SPaolo Bonzini case INDEX_op_shr_i32: 2512139c1837SPaolo Bonzini case INDEX_op_sar_i32: 251319d016adSRichard Henderson case INDEX_op_rotl_i32: 251419d016adSRichard Henderson case INDEX_op_rotr_i32: 2515139c1837SPaolo Bonzini case INDEX_op_shl_i64: 2516139c1837SPaolo Bonzini case INDEX_op_shr_i64: 2517139c1837SPaolo Bonzini case INDEX_op_sar_i64: 251819d016adSRichard Henderson case INDEX_op_rotl_i64: 251919d016adSRichard Henderson case INDEX_op_rotr_i64: 2520665be288SRichard Henderson return C_O1_I2(r, r, ri); 2521139c1837SPaolo Bonzini 2522a30498fcSRichard Henderson case INDEX_op_clz_i32: 2523a30498fcSRichard Henderson case INDEX_op_clz_i64: 2524a30498fcSRichard Henderson case INDEX_op_ctz_i32: 2525a30498fcSRichard Henderson case INDEX_op_ctz_i64: 2526a30498fcSRichard Henderson return C_N1_I2(r, r, rM); 2527a30498fcSRichard Henderson 2528139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 2529139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 2530665be288SRichard Henderson return C_O0_I2(rZ, rZ); 2531139c1837SPaolo Bonzini 2532a18d783eSRichard Henderson case INDEX_op_movcond_i32: 2533a18d783eSRichard Henderson case INDEX_op_movcond_i64: 2534a18d783eSRichard Henderson return C_O1_I4(r, r, rI, rM, rM); 2535a18d783eSRichard Henderson 2536139c1837SPaolo Bonzini case INDEX_op_add2_i32: 2537139c1837SPaolo Bonzini case INDEX_op_add2_i64: 2538139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 2539139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 2540665be288SRichard Henderson return C_O2_I4(r, r, rZ, rZ, rM, rM); 2541139c1837SPaolo Bonzini 2542fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 2543fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 2544fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 2545fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 2546f0f43534SRichard Henderson return C_O1_I1(r, r); 2547fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 2548fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 2549fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 2550fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 2551f0f43534SRichard Henderson return C_O0_I2(rZ, r); 2552139c1837SPaolo Bonzini 2553f63e7089SHuang Shiyuan case INDEX_op_st_vec: 2554f63e7089SHuang Shiyuan return C_O0_I2(v, r); 2555d4be6ee1STANG Tiancheng case INDEX_op_dup_vec: 2556d4be6ee1STANG Tiancheng case INDEX_op_dupm_vec: 2557f63e7089SHuang Shiyuan case INDEX_op_ld_vec: 2558f63e7089SHuang Shiyuan return C_O1_I1(v, r); 2559*c283c074STANG Tiancheng case INDEX_op_neg_vec: 25605a63f599STANG Tiancheng case INDEX_op_not_vec: 25615a63f599STANG Tiancheng return C_O1_I1(v, v); 25625a63f599STANG Tiancheng case INDEX_op_add_vec: 25635a63f599STANG Tiancheng case INDEX_op_and_vec: 25645a63f599STANG Tiancheng case INDEX_op_or_vec: 25655a63f599STANG Tiancheng case INDEX_op_xor_vec: 25665a63f599STANG Tiancheng return C_O1_I2(v, v, vK); 25675a63f599STANG Tiancheng case INDEX_op_sub_vec: 25685a63f599STANG Tiancheng return C_O1_I2(v, v, v); 2569a31768c0STANG Tiancheng case INDEX_op_cmp_vec: 2570a31768c0STANG Tiancheng return C_O1_I2(v, v, vL); 2571a31768c0STANG Tiancheng case INDEX_op_cmpsel_vec: 2572a31768c0STANG Tiancheng return C_O1_I4(v, v, vL, vK, vK); 2573139c1837SPaolo Bonzini default: 2574665be288SRichard Henderson g_assert_not_reached(); 2575139c1837SPaolo Bonzini } 2576139c1837SPaolo Bonzini} 2577139c1837SPaolo Bonzini 2578139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = { 2579139c1837SPaolo Bonzini TCG_REG_S0, /* used for the global env (TCG_AREG0) */ 2580139c1837SPaolo Bonzini TCG_REG_S1, 2581139c1837SPaolo Bonzini TCG_REG_S2, 2582139c1837SPaolo Bonzini TCG_REG_S3, 2583139c1837SPaolo Bonzini TCG_REG_S4, 2584139c1837SPaolo Bonzini TCG_REG_S5, 2585139c1837SPaolo Bonzini TCG_REG_S6, 2586139c1837SPaolo Bonzini TCG_REG_S7, 2587139c1837SPaolo Bonzini TCG_REG_S8, 2588139c1837SPaolo Bonzini TCG_REG_S9, 2589139c1837SPaolo Bonzini TCG_REG_S10, 2590139c1837SPaolo Bonzini TCG_REG_S11, 2591139c1837SPaolo Bonzini TCG_REG_RA, /* should be last for ABI compliance */ 2592139c1837SPaolo Bonzini}; 2593139c1837SPaolo Bonzini 2594139c1837SPaolo Bonzini/* Stack frame parameters. */ 2595139c1837SPaolo Bonzini#define REG_SIZE (TCG_TARGET_REG_BITS / 8) 2596139c1837SPaolo Bonzini#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) 2597139c1837SPaolo Bonzini#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) 2598139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ 2599139c1837SPaolo Bonzini + TCG_TARGET_STACK_ALIGN - 1) \ 2600139c1837SPaolo Bonzini & -TCG_TARGET_STACK_ALIGN) 2601139c1837SPaolo Bonzini#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) 2602139c1837SPaolo Bonzini 2603139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation. */ 2604139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); 2605139c1837SPaolo Bonzini 2606139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */ 2607139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s) 2608139c1837SPaolo Bonzini{ 2609139c1837SPaolo Bonzini int i; 2610139c1837SPaolo Bonzini 2611139c1837SPaolo Bonzini tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); 2612139c1837SPaolo Bonzini 2613139c1837SPaolo Bonzini /* TB prologue */ 2614139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); 2615139c1837SPaolo Bonzini for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 2616139c1837SPaolo Bonzini tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 2617139c1837SPaolo Bonzini TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 2618139c1837SPaolo Bonzini } 2619139c1837SPaolo Bonzini 26204944d359SRichard Henderson if (!tcg_use_softmmu && guest_base) { 2621139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); 2622139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); 2623cf0ed30eSRichard Henderson } 2624139c1837SPaolo Bonzini 2625139c1837SPaolo Bonzini /* Call generated code */ 2626139c1837SPaolo Bonzini tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); 2627139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); 2628139c1837SPaolo Bonzini 2629139c1837SPaolo Bonzini /* Return path for goto_ptr. Set return value to 0 */ 2630c8bc1168SRichard Henderson tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); 2631139c1837SPaolo Bonzini tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); 2632139c1837SPaolo Bonzini 2633139c1837SPaolo Bonzini /* TB epilogue */ 2634793f7381SRichard Henderson tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); 2635139c1837SPaolo Bonzini for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 2636139c1837SPaolo Bonzini tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 2637139c1837SPaolo Bonzini TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 2638139c1837SPaolo Bonzini } 2639139c1837SPaolo Bonzini 2640139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); 2641139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0); 2642139c1837SPaolo Bonzini} 2643139c1837SPaolo Bonzini 26449358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s) 26459358fbbfSRichard Henderson{ 2646f63e7089SHuang Shiyuan init_setting_vtype(s); 2647f63e7089SHuang Shiyuan} 2648f63e7089SHuang Shiyuan 2649f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype) 2650f63e7089SHuang Shiyuan{ 2651f63e7089SHuang Shiyuan unsigned long tmp; 2652f63e7089SHuang Shiyuan 2653f63e7089SHuang Shiyuan /* vsetvl tmp, zero, vtype */ 2654f63e7089SHuang Shiyuan asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype)); 2655f63e7089SHuang Shiyuan return tmp != 0; 2656f63e7089SHuang Shiyuan} 2657f63e7089SHuang Shiyuan 2658f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew) 2659f63e7089SHuang Shiyuan{ 2660f63e7089SHuang Shiyuan VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew]; 2661f63e7089SHuang Shiyuan unsigned avl = tcg_type_size(type) >> vsew; 2662f63e7089SHuang Shiyuan int lmul = type - riscv_lg2_vlenb; 2663f63e7089SHuang Shiyuan unsigned vtype = encode_vtype(true, true, vsew, lmul & 7); 2664f63e7089SHuang Shiyuan bool lmul_eq_avl = true; 2665f63e7089SHuang Shiyuan 2666f63e7089SHuang Shiyuan /* Guaranteed by Zve64x. */ 2667f63e7089SHuang Shiyuan assert(lmul < 3); 2668f63e7089SHuang Shiyuan 2669f63e7089SHuang Shiyuan /* 2670f63e7089SHuang Shiyuan * For LMUL < -3, the host vector size is so large that TYPE 2671f63e7089SHuang Shiyuan * is smaller than the minimum 1/8 fraction. 2672f63e7089SHuang Shiyuan * 2673f63e7089SHuang Shiyuan * For other fractional LMUL settings, implementations must 2674f63e7089SHuang Shiyuan * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive. 2675f63e7089SHuang Shiyuan * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32, 2676f63e7089SHuang Shiyuan * but e64 may not be supported. In other words, the hardware only 2677f63e7089SHuang Shiyuan * guarantees SEW_MIN <= SEW <= LMUL * ELEN. Check. 2678f63e7089SHuang Shiyuan */ 2679f63e7089SHuang Shiyuan if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) { 2680f63e7089SHuang Shiyuan vtype = encode_vtype(true, true, vsew, VLMUL_M1); 2681f63e7089SHuang Shiyuan lmul_eq_avl = false; 2682f63e7089SHuang Shiyuan } 2683f63e7089SHuang Shiyuan 2684f63e7089SHuang Shiyuan if (avl < 32) { 2685f63e7089SHuang Shiyuan p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype); 2686f63e7089SHuang Shiyuan } else if (lmul_eq_avl) { 2687f63e7089SHuang Shiyuan /* rd != 0 and rs1 == 0 uses vlmax */ 2688f63e7089SHuang Shiyuan p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype); 2689f63e7089SHuang Shiyuan } else { 2690f63e7089SHuang Shiyuan p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl); 2691f63e7089SHuang Shiyuan p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype); 2692f63e7089SHuang Shiyuan } 2693f63e7089SHuang Shiyuan} 2694f63e7089SHuang Shiyuan 2695f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void) 2696f63e7089SHuang Shiyuan{ 2697f63e7089SHuang Shiyuan /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */ 2698f63e7089SHuang Shiyuan QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3); 2699f63e7089SHuang Shiyuan 2700f63e7089SHuang Shiyuan for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) { 2701f63e7089SHuang Shiyuan for (MemOp e = MO_8; e <= MO_64; e++) { 2702f63e7089SHuang Shiyuan probe_frac_lmul_1(t, e); 2703f63e7089SHuang Shiyuan } 2704f63e7089SHuang Shiyuan } 27059358fbbfSRichard Henderson} 27069358fbbfSRichard Henderson 2707139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s) 2708139c1837SPaolo Bonzini{ 2709139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff; 2710139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff; 2711139c1837SPaolo Bonzini 2712f63e7089SHuang Shiyuan tcg_target_call_clobber_regs = -1; 2713139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); 2714139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); 2715139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); 2716139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); 2717139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); 2718139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); 2719139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); 2720139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); 2721139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); 2722139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); 2723139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10); 2724139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11); 2725139c1837SPaolo Bonzini 2726139c1837SPaolo Bonzini s->reserved_regs = 0; 2727139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); 2728139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); 2729139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); 2730139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); 2731139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); 2732139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); 2733139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); 2734f63e7089SHuang Shiyuan 2735f63e7089SHuang Shiyuan if (cpuinfo & CPUINFO_ZVE64X) { 2736f63e7089SHuang Shiyuan switch (riscv_lg2_vlenb) { 2737f63e7089SHuang Shiyuan case TCG_TYPE_V64: 2738f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2739f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS; 2740f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS; 2741f63e7089SHuang Shiyuan s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS); 2742f63e7089SHuang Shiyuan break; 2743f63e7089SHuang Shiyuan case TCG_TYPE_V128: 2744f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2745f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS; 2746f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS; 2747f63e7089SHuang Shiyuan s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS); 2748f63e7089SHuang Shiyuan break; 2749f63e7089SHuang Shiyuan default: 2750f63e7089SHuang Shiyuan /* Guaranteed by Zve64x. */ 2751f63e7089SHuang Shiyuan tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256); 2752f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2753f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS; 2754f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS; 2755f63e7089SHuang Shiyuan break; 2756f63e7089SHuang Shiyuan } 2757f63e7089SHuang Shiyuan tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0); 2758f63e7089SHuang Shiyuan probe_frac_lmul(); 2759f63e7089SHuang Shiyuan } 2760139c1837SPaolo Bonzini} 2761139c1837SPaolo Bonzini 2762139c1837SPaolo Bonzinitypedef struct { 2763139c1837SPaolo Bonzini DebugFrameHeader h; 2764139c1837SPaolo Bonzini uint8_t fde_def_cfa[4]; 2765139c1837SPaolo Bonzini uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; 2766139c1837SPaolo Bonzini} DebugFrame; 2767139c1837SPaolo Bonzini 2768139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV 2769139c1837SPaolo Bonzini 2770139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = { 2771139c1837SPaolo Bonzini .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ 2772139c1837SPaolo Bonzini .h.cie.id = -1, 2773139c1837SPaolo Bonzini .h.cie.version = 1, 2774139c1837SPaolo Bonzini .h.cie.code_align = 1, 2775139c1837SPaolo Bonzini .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ 2776139c1837SPaolo Bonzini .h.cie.return_column = TCG_REG_RA, 2777139c1837SPaolo Bonzini 2778139c1837SPaolo Bonzini /* Total FDE size does not include the "len" member. */ 2779139c1837SPaolo Bonzini .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), 2780139c1837SPaolo Bonzini 2781139c1837SPaolo Bonzini .fde_def_cfa = { 2782139c1837SPaolo Bonzini 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ 2783139c1837SPaolo Bonzini (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ 2784139c1837SPaolo Bonzini (FRAME_SIZE >> 7) 2785139c1837SPaolo Bonzini }, 2786139c1837SPaolo Bonzini .fde_reg_ofs = { 2787139c1837SPaolo Bonzini 0x80 + 9, 12, /* DW_CFA_offset, s1, -96 */ 2788139c1837SPaolo Bonzini 0x80 + 18, 11, /* DW_CFA_offset, s2, -88 */ 2789139c1837SPaolo Bonzini 0x80 + 19, 10, /* DW_CFA_offset, s3, -80 */ 2790139c1837SPaolo Bonzini 0x80 + 20, 9, /* DW_CFA_offset, s4, -72 */ 2791139c1837SPaolo Bonzini 0x80 + 21, 8, /* DW_CFA_offset, s5, -64 */ 2792139c1837SPaolo Bonzini 0x80 + 22, 7, /* DW_CFA_offset, s6, -56 */ 2793139c1837SPaolo Bonzini 0x80 + 23, 6, /* DW_CFA_offset, s7, -48 */ 2794139c1837SPaolo Bonzini 0x80 + 24, 5, /* DW_CFA_offset, s8, -40 */ 2795139c1837SPaolo Bonzini 0x80 + 25, 4, /* DW_CFA_offset, s9, -32 */ 2796139c1837SPaolo Bonzini 0x80 + 26, 3, /* DW_CFA_offset, s10, -24 */ 2797139c1837SPaolo Bonzini 0x80 + 27, 2, /* DW_CFA_offset, s11, -16 */ 2798139c1837SPaolo Bonzini 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ 2799139c1837SPaolo Bonzini } 2800139c1837SPaolo Bonzini}; 2801139c1837SPaolo Bonzini 2802755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size) 2803139c1837SPaolo Bonzini{ 2804139c1837SPaolo Bonzini tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); 2805139c1837SPaolo Bonzini} 2806