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] = { 35*f63e7089SHuang Shiyuan "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", 36*f63e7089SHuang Shiyuan "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", 37*f63e7089SHuang Shiyuan "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", 38*f63e7089SHuang Shiyuan "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", 39*f63e7089SHuang Shiyuan "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 40*f63e7089SHuang Shiyuan "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 41*f63e7089SHuang Shiyuan "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 42*f63e7089SHuang 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, 79*f63e7089SHuang Shiyuan 80*f63e7089SHuang Shiyuan /* Vector registers and TCG_REG_V0 reserved for mask. */ 81*f63e7089SHuang Shiyuan TCG_REG_V1, TCG_REG_V2, TCG_REG_V3, TCG_REG_V4, 82*f63e7089SHuang Shiyuan TCG_REG_V5, TCG_REG_V6, TCG_REG_V7, TCG_REG_V8, 83*f63e7089SHuang Shiyuan TCG_REG_V9, TCG_REG_V10, TCG_REG_V11, TCG_REG_V12, 84*f63e7089SHuang Shiyuan TCG_REG_V13, TCG_REG_V14, TCG_REG_V15, TCG_REG_V16, 85*f63e7089SHuang Shiyuan TCG_REG_V17, TCG_REG_V18, TCG_REG_V19, TCG_REG_V20, 86*f63e7089SHuang Shiyuan TCG_REG_V21, TCG_REG_V22, TCG_REG_V23, TCG_REG_V24, 87*f63e7089SHuang Shiyuan TCG_REG_V25, TCG_REG_V26, TCG_REG_V27, TCG_REG_V28, 88*f63e7089SHuang 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 114139c1837SPaolo Bonzini 115fc63a4c5SRichard Henderson#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) 116*f63e7089SHuang Shiyuan#define ALL_VECTOR_REGS MAKE_64BIT_MASK(32, 32) 117*f63e7089SHuang Shiyuan#define ALL_DVECTOR_REG_GROUPS 0x5555555500000000 118*f63e7089SHuang Shiyuan#define ALL_QVECTOR_REG_GROUPS 0x1111111100000000 119fc63a4c5SRichard Henderson 120aeb6326eSRichard Henderson#define sextreg sextract64 121139c1837SPaolo Bonzini 122139c1837SPaolo Bonzini/* test if a constant matches the constraint */ 12321e9a8aeSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct, 12421e9a8aeSRichard Henderson TCGType type, TCGCond cond, int vece) 125139c1837SPaolo Bonzini{ 126139c1837SPaolo Bonzini if (ct & TCG_CT_CONST) { 127139c1837SPaolo Bonzini return 1; 128139c1837SPaolo Bonzini } 129139c1837SPaolo Bonzini if ((ct & TCG_CT_CONST_ZERO) && val == 0) { 130139c1837SPaolo Bonzini return 1; 131139c1837SPaolo Bonzini } 13262722763SRichard Henderson /* 13362722763SRichard Henderson * Sign extended from 12 bits: [-0x800, 0x7ff]. 13462722763SRichard Henderson * Used for most arithmetic, as this is the isa field. 13562722763SRichard Henderson */ 13662722763SRichard Henderson if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) { 137139c1837SPaolo Bonzini return 1; 138139c1837SPaolo Bonzini } 13962722763SRichard Henderson /* 14062722763SRichard Henderson * Sign extended from 12 bits, negated: [-0x7ff, 0x800]. 14162722763SRichard Henderson * Used for subtraction, where a constant must be handled by ADDI. 14262722763SRichard Henderson */ 14362722763SRichard Henderson if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) { 144139c1837SPaolo Bonzini return 1; 145139c1837SPaolo Bonzini } 14662722763SRichard Henderson /* 14762722763SRichard Henderson * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff]. 148a18d783eSRichard Henderson * Used by addsub2 and movcond, which may need the negative value, 14962722763SRichard Henderson * and requires the modified constant to be representable. 15062722763SRichard Henderson */ 15162722763SRichard Henderson if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) { 152139c1837SPaolo Bonzini return 1; 153139c1837SPaolo Bonzini } 15499f4ec6eSRichard Henderson /* 15599f4ec6eSRichard Henderson * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff]. 15699f4ec6eSRichard Henderson * Used to map ANDN back to ANDI, etc. 15799f4ec6eSRichard Henderson */ 15899f4ec6eSRichard Henderson if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) { 15999f4ec6eSRichard Henderson return 1; 16099f4ec6eSRichard Henderson } 161139c1837SPaolo Bonzini return 0; 162139c1837SPaolo Bonzini} 163139c1837SPaolo Bonzini 164139c1837SPaolo Bonzini/* 165139c1837SPaolo Bonzini * RISC-V Base ISA opcodes (IM) 166139c1837SPaolo Bonzini */ 167139c1837SPaolo Bonzini 168*f63e7089SHuang Shiyuan#define V_OPIVV (0x0 << 12) 169*f63e7089SHuang Shiyuan#define V_OPFVV (0x1 << 12) 170*f63e7089SHuang Shiyuan#define V_OPMVV (0x2 << 12) 171*f63e7089SHuang Shiyuan#define V_OPIVI (0x3 << 12) 172*f63e7089SHuang Shiyuan#define V_OPIVX (0x4 << 12) 173*f63e7089SHuang Shiyuan#define V_OPFVF (0x5 << 12) 174*f63e7089SHuang Shiyuan#define V_OPMVX (0x6 << 12) 175*f63e7089SHuang Shiyuan#define V_OPCFG (0x7 << 12) 176*f63e7089SHuang Shiyuan 177*f63e7089SHuang Shiyuan/* NF <= 7 && NF >= 0 */ 178*f63e7089SHuang Shiyuan#define V_NF(x) (x << 29) 179*f63e7089SHuang Shiyuan#define V_UNIT_STRIDE (0x0 << 20) 180*f63e7089SHuang Shiyuan#define V_UNIT_STRIDE_WHOLE_REG (0x8 << 20) 181*f63e7089SHuang Shiyuan 182*f63e7089SHuang Shiyuantypedef enum { 183*f63e7089SHuang Shiyuan VLMUL_M1 = 0, /* LMUL=1 */ 184*f63e7089SHuang Shiyuan VLMUL_M2, /* LMUL=2 */ 185*f63e7089SHuang Shiyuan VLMUL_M4, /* LMUL=4 */ 186*f63e7089SHuang Shiyuan VLMUL_M8, /* LMUL=8 */ 187*f63e7089SHuang Shiyuan VLMUL_RESERVED, 188*f63e7089SHuang Shiyuan VLMUL_MF8, /* LMUL=1/8 */ 189*f63e7089SHuang Shiyuan VLMUL_MF4, /* LMUL=1/4 */ 190*f63e7089SHuang Shiyuan VLMUL_MF2, /* LMUL=1/2 */ 191*f63e7089SHuang Shiyuan} RISCVVlmul; 192*f63e7089SHuang Shiyuan 193139c1837SPaolo Bonzinitypedef enum { 194139c1837SPaolo Bonzini OPC_ADD = 0x33, 195139c1837SPaolo Bonzini OPC_ADDI = 0x13, 196139c1837SPaolo Bonzini OPC_AND = 0x7033, 197139c1837SPaolo Bonzini OPC_ANDI = 0x7013, 198139c1837SPaolo Bonzini OPC_AUIPC = 0x17, 199139c1837SPaolo Bonzini OPC_BEQ = 0x63, 200139c1837SPaolo Bonzini OPC_BGE = 0x5063, 201139c1837SPaolo Bonzini OPC_BGEU = 0x7063, 202139c1837SPaolo Bonzini OPC_BLT = 0x4063, 203139c1837SPaolo Bonzini OPC_BLTU = 0x6063, 204139c1837SPaolo Bonzini OPC_BNE = 0x1063, 205139c1837SPaolo Bonzini OPC_DIV = 0x2004033, 206139c1837SPaolo Bonzini OPC_DIVU = 0x2005033, 207139c1837SPaolo Bonzini OPC_JAL = 0x6f, 208139c1837SPaolo Bonzini OPC_JALR = 0x67, 209139c1837SPaolo Bonzini OPC_LB = 0x3, 210139c1837SPaolo Bonzini OPC_LBU = 0x4003, 211139c1837SPaolo Bonzini OPC_LD = 0x3003, 212139c1837SPaolo Bonzini OPC_LH = 0x1003, 213139c1837SPaolo Bonzini OPC_LHU = 0x5003, 214139c1837SPaolo Bonzini OPC_LUI = 0x37, 215139c1837SPaolo Bonzini OPC_LW = 0x2003, 216139c1837SPaolo Bonzini OPC_LWU = 0x6003, 217139c1837SPaolo Bonzini OPC_MUL = 0x2000033, 218139c1837SPaolo Bonzini OPC_MULH = 0x2001033, 219139c1837SPaolo Bonzini OPC_MULHSU = 0x2002033, 220139c1837SPaolo Bonzini OPC_MULHU = 0x2003033, 221139c1837SPaolo Bonzini OPC_OR = 0x6033, 222139c1837SPaolo Bonzini OPC_ORI = 0x6013, 223139c1837SPaolo Bonzini OPC_REM = 0x2006033, 224139c1837SPaolo Bonzini OPC_REMU = 0x2007033, 225139c1837SPaolo Bonzini OPC_SB = 0x23, 226139c1837SPaolo Bonzini OPC_SD = 0x3023, 227139c1837SPaolo Bonzini OPC_SH = 0x1023, 228139c1837SPaolo Bonzini OPC_SLL = 0x1033, 229139c1837SPaolo Bonzini OPC_SLLI = 0x1013, 230139c1837SPaolo Bonzini OPC_SLT = 0x2033, 231139c1837SPaolo Bonzini OPC_SLTI = 0x2013, 232139c1837SPaolo Bonzini OPC_SLTIU = 0x3013, 233139c1837SPaolo Bonzini OPC_SLTU = 0x3033, 234139c1837SPaolo Bonzini OPC_SRA = 0x40005033, 235139c1837SPaolo Bonzini OPC_SRAI = 0x40005013, 236139c1837SPaolo Bonzini OPC_SRL = 0x5033, 237139c1837SPaolo Bonzini OPC_SRLI = 0x5013, 238139c1837SPaolo Bonzini OPC_SUB = 0x40000033, 239139c1837SPaolo Bonzini OPC_SW = 0x2023, 240139c1837SPaolo Bonzini OPC_XOR = 0x4033, 241139c1837SPaolo Bonzini OPC_XORI = 0x4013, 242139c1837SPaolo Bonzini 243139c1837SPaolo Bonzini OPC_ADDIW = 0x1b, 244139c1837SPaolo Bonzini OPC_ADDW = 0x3b, 245139c1837SPaolo Bonzini OPC_DIVUW = 0x200503b, 246139c1837SPaolo Bonzini OPC_DIVW = 0x200403b, 247139c1837SPaolo Bonzini OPC_MULW = 0x200003b, 248139c1837SPaolo Bonzini OPC_REMUW = 0x200703b, 249139c1837SPaolo Bonzini OPC_REMW = 0x200603b, 250139c1837SPaolo Bonzini OPC_SLLIW = 0x101b, 251139c1837SPaolo Bonzini OPC_SLLW = 0x103b, 252139c1837SPaolo Bonzini OPC_SRAIW = 0x4000501b, 253139c1837SPaolo Bonzini OPC_SRAW = 0x4000503b, 254139c1837SPaolo Bonzini OPC_SRLIW = 0x501b, 255139c1837SPaolo Bonzini OPC_SRLW = 0x503b, 256139c1837SPaolo Bonzini OPC_SUBW = 0x4000003b, 257139c1837SPaolo Bonzini 258139c1837SPaolo Bonzini OPC_FENCE = 0x0000000f, 2599ae958e4SRichard Henderson OPC_NOP = OPC_ADDI, /* nop = addi r0,r0,0 */ 2609e3e0bc6SRichard Henderson 2619e3e0bc6SRichard Henderson /* Zba: Bit manipulation extension, address generation */ 2629e3e0bc6SRichard Henderson OPC_ADD_UW = 0x0800003b, 2639e3e0bc6SRichard Henderson 2644daad8d9SMichael Tokarev /* Zbb: Bit manipulation extension, basic bit manipulation */ 2659e3e0bc6SRichard Henderson OPC_ANDN = 0x40007033, 2669e3e0bc6SRichard Henderson OPC_CLZ = 0x60001013, 2679e3e0bc6SRichard Henderson OPC_CLZW = 0x6000101b, 2689e3e0bc6SRichard Henderson OPC_CPOP = 0x60201013, 2699e3e0bc6SRichard Henderson OPC_CPOPW = 0x6020101b, 2709e3e0bc6SRichard Henderson OPC_CTZ = 0x60101013, 2719e3e0bc6SRichard Henderson OPC_CTZW = 0x6010101b, 2729e3e0bc6SRichard Henderson OPC_ORN = 0x40006033, 2739e3e0bc6SRichard Henderson OPC_REV8 = 0x6b805013, 2749e3e0bc6SRichard Henderson OPC_ROL = 0x60001033, 2759e3e0bc6SRichard Henderson OPC_ROLW = 0x6000103b, 2769e3e0bc6SRichard Henderson OPC_ROR = 0x60005033, 2779e3e0bc6SRichard Henderson OPC_RORW = 0x6000503b, 2789e3e0bc6SRichard Henderson OPC_RORI = 0x60005013, 2799e3e0bc6SRichard Henderson OPC_RORIW = 0x6000501b, 2809e3e0bc6SRichard Henderson OPC_SEXT_B = 0x60401013, 2819e3e0bc6SRichard Henderson OPC_SEXT_H = 0x60501013, 2829e3e0bc6SRichard Henderson OPC_XNOR = 0x40004033, 2839e3e0bc6SRichard Henderson OPC_ZEXT_H = 0x0800403b, 2849e3e0bc6SRichard Henderson 2859e3e0bc6SRichard Henderson /* Zicond: integer conditional operations */ 2869e3e0bc6SRichard Henderson OPC_CZERO_EQZ = 0x0e005033, 2879e3e0bc6SRichard Henderson OPC_CZERO_NEZ = 0x0e007033, 288*f63e7089SHuang Shiyuan 289*f63e7089SHuang Shiyuan /* V: Vector extension 1.0 */ 290*f63e7089SHuang Shiyuan OPC_VSETVLI = 0x57 | V_OPCFG, 291*f63e7089SHuang Shiyuan OPC_VSETIVLI = 0xc0000057 | V_OPCFG, 292*f63e7089SHuang Shiyuan OPC_VSETVL = 0x80000057 | V_OPCFG, 293*f63e7089SHuang Shiyuan 294*f63e7089SHuang Shiyuan OPC_VLE8_V = 0x7 | V_UNIT_STRIDE, 295*f63e7089SHuang Shiyuan OPC_VLE16_V = 0x5007 | V_UNIT_STRIDE, 296*f63e7089SHuang Shiyuan OPC_VLE32_V = 0x6007 | V_UNIT_STRIDE, 297*f63e7089SHuang Shiyuan OPC_VLE64_V = 0x7007 | V_UNIT_STRIDE, 298*f63e7089SHuang Shiyuan OPC_VSE8_V = 0x27 | V_UNIT_STRIDE, 299*f63e7089SHuang Shiyuan OPC_VSE16_V = 0x5027 | V_UNIT_STRIDE, 300*f63e7089SHuang Shiyuan OPC_VSE32_V = 0x6027 | V_UNIT_STRIDE, 301*f63e7089SHuang Shiyuan OPC_VSE64_V = 0x7027 | V_UNIT_STRIDE, 302*f63e7089SHuang Shiyuan 303*f63e7089SHuang Shiyuan OPC_VL1RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0), 304*f63e7089SHuang Shiyuan OPC_VL2RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1), 305*f63e7089SHuang Shiyuan OPC_VL4RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3), 306*f63e7089SHuang Shiyuan OPC_VL8RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7), 307*f63e7089SHuang Shiyuan 308*f63e7089SHuang Shiyuan OPC_VS1R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0), 309*f63e7089SHuang Shiyuan OPC_VS2R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1), 310*f63e7089SHuang Shiyuan OPC_VS4R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3), 311*f63e7089SHuang Shiyuan OPC_VS8R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7), 312139c1837SPaolo Bonzini} RISCVInsn; 313139c1837SPaolo Bonzini 314139c1837SPaolo Bonzini/* 315139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC) 316139c1837SPaolo Bonzini */ 317139c1837SPaolo Bonzini 318139c1837SPaolo Bonzini/* Type-R */ 319139c1837SPaolo Bonzini 320139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2) 321139c1837SPaolo Bonzini{ 322139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20; 323139c1837SPaolo Bonzini} 324139c1837SPaolo Bonzini 325139c1837SPaolo Bonzini/* Type-I */ 326139c1837SPaolo Bonzini 327139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm) 328139c1837SPaolo Bonzini{ 329139c1837SPaolo Bonzini return (imm & 0xfff) << 20; 330139c1837SPaolo Bonzini} 331139c1837SPaolo Bonzini 332139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm) 333139c1837SPaolo Bonzini{ 334139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm); 335139c1837SPaolo Bonzini} 336139c1837SPaolo Bonzini 337139c1837SPaolo Bonzini/* Type-S */ 338139c1837SPaolo Bonzini 339139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm) 340139c1837SPaolo Bonzini{ 341139c1837SPaolo Bonzini int32_t ret = 0; 342139c1837SPaolo Bonzini 343139c1837SPaolo Bonzini ret |= (imm & 0xFE0) << 20; 344139c1837SPaolo Bonzini ret |= (imm & 0x1F) << 7; 345139c1837SPaolo Bonzini 346139c1837SPaolo Bonzini return ret; 347139c1837SPaolo Bonzini} 348139c1837SPaolo Bonzini 349139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) 350139c1837SPaolo Bonzini{ 351139c1837SPaolo Bonzini return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm); 352139c1837SPaolo Bonzini} 353139c1837SPaolo Bonzini 354139c1837SPaolo Bonzini/* Type-SB */ 355139c1837SPaolo Bonzini 356139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm) 357139c1837SPaolo Bonzini{ 358139c1837SPaolo Bonzini int32_t ret = 0; 359139c1837SPaolo Bonzini 360139c1837SPaolo Bonzini ret |= (imm & 0x1000) << 19; 361139c1837SPaolo Bonzini ret |= (imm & 0x7e0) << 20; 362139c1837SPaolo Bonzini ret |= (imm & 0x1e) << 7; 363139c1837SPaolo Bonzini ret |= (imm & 0x800) >> 4; 364139c1837SPaolo Bonzini 365139c1837SPaolo Bonzini return ret; 366139c1837SPaolo Bonzini} 367139c1837SPaolo Bonzini 368139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm) 369139c1837SPaolo Bonzini{ 370139c1837SPaolo Bonzini return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm); 371139c1837SPaolo Bonzini} 372139c1837SPaolo Bonzini 373139c1837SPaolo Bonzini/* Type-U */ 374139c1837SPaolo Bonzini 375139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm) 376139c1837SPaolo Bonzini{ 377139c1837SPaolo Bonzini return imm & 0xfffff000; 378139c1837SPaolo Bonzini} 379139c1837SPaolo Bonzini 380139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm) 381139c1837SPaolo Bonzini{ 382139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | encode_uimm20(imm); 383139c1837SPaolo Bonzini} 384139c1837SPaolo Bonzini 385139c1837SPaolo Bonzini/* Type-UJ */ 386139c1837SPaolo Bonzini 387139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm) 388139c1837SPaolo Bonzini{ 389139c1837SPaolo Bonzini int32_t ret = 0; 390139c1837SPaolo Bonzini 391139c1837SPaolo Bonzini ret |= (imm & 0x0007fe) << (21 - 1); 392139c1837SPaolo Bonzini ret |= (imm & 0x000800) << (20 - 11); 393139c1837SPaolo Bonzini ret |= (imm & 0x0ff000) << (12 - 12); 394139c1837SPaolo Bonzini ret |= (imm & 0x100000) << (31 - 20); 395139c1837SPaolo Bonzini 396139c1837SPaolo Bonzini return ret; 397139c1837SPaolo Bonzini} 398139c1837SPaolo Bonzini 399139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm) 400139c1837SPaolo Bonzini{ 401139c1837SPaolo Bonzini return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm); 402139c1837SPaolo Bonzini} 403139c1837SPaolo Bonzini 404*f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */ 405*f63e7089SHuang Shiyuan 406*f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1, 407*f63e7089SHuang Shiyuan TCGReg s2, bool vm) 408*f63e7089SHuang Shiyuan{ 409*f63e7089SHuang Shiyuan return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 | 410*f63e7089SHuang Shiyuan (s2 & 0x1f) << 20 | (vm << 25); 411*f63e7089SHuang Shiyuan} 412*f63e7089SHuang Shiyuan 413*f63e7089SHuang Shiyuan/* Vector vtype */ 414*f63e7089SHuang Shiyuan 415*f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma, 416*f63e7089SHuang Shiyuan MemOp vsew, RISCVVlmul vlmul) 417*f63e7089SHuang Shiyuan{ 418*f63e7089SHuang Shiyuan return vma << 7 | vta << 6 | vsew << 3 | vlmul; 419*f63e7089SHuang Shiyuan} 420*f63e7089SHuang Shiyuan 421*f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd, 422*f63e7089SHuang Shiyuan TCGArg rs1, uint32_t vtype) 423*f63e7089SHuang Shiyuan{ 424*f63e7089SHuang Shiyuan return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20; 425*f63e7089SHuang Shiyuan} 426*f63e7089SHuang Shiyuan 427*f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd, 428*f63e7089SHuang Shiyuan uint32_t uimm, uint32_t vtype) 429*f63e7089SHuang Shiyuan{ 430*f63e7089SHuang Shiyuan return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20; 431*f63e7089SHuang Shiyuan} 432*f63e7089SHuang Shiyuan 433139c1837SPaolo Bonzini/* 434139c1837SPaolo Bonzini * RISC-V instruction emitters 435139c1837SPaolo Bonzini */ 436139c1837SPaolo Bonzini 437139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc, 438139c1837SPaolo Bonzini TCGReg rd, TCGReg rs1, TCGReg rs2) 439139c1837SPaolo Bonzini{ 440139c1837SPaolo Bonzini tcg_out32(s, encode_r(opc, rd, rs1, rs2)); 441139c1837SPaolo Bonzini} 442139c1837SPaolo Bonzini 443139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc, 444139c1837SPaolo Bonzini TCGReg rd, TCGReg rs1, TCGArg imm) 445139c1837SPaolo Bonzini{ 446139c1837SPaolo Bonzini tcg_out32(s, encode_i(opc, rd, rs1, imm)); 447139c1837SPaolo Bonzini} 448139c1837SPaolo Bonzini 449139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc, 450139c1837SPaolo Bonzini TCGReg rs1, TCGReg rs2, uint32_t imm) 451139c1837SPaolo Bonzini{ 452139c1837SPaolo Bonzini tcg_out32(s, encode_s(opc, rs1, rs2, imm)); 453139c1837SPaolo Bonzini} 454139c1837SPaolo Bonzini 455139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc, 456139c1837SPaolo Bonzini TCGReg rs1, TCGReg rs2, uint32_t imm) 457139c1837SPaolo Bonzini{ 458139c1837SPaolo Bonzini tcg_out32(s, encode_sb(opc, rs1, rs2, imm)); 459139c1837SPaolo Bonzini} 460139c1837SPaolo Bonzini 461139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc, 462139c1837SPaolo Bonzini TCGReg rd, uint32_t imm) 463139c1837SPaolo Bonzini{ 464139c1837SPaolo Bonzini tcg_out32(s, encode_u(opc, rd, imm)); 465139c1837SPaolo Bonzini} 466139c1837SPaolo Bonzini 467139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc, 468139c1837SPaolo Bonzini TCGReg rd, uint32_t imm) 469139c1837SPaolo Bonzini{ 470139c1837SPaolo Bonzini tcg_out32(s, encode_uj(opc, rd, imm)); 471139c1837SPaolo Bonzini} 472139c1837SPaolo Bonzini 473139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count) 474139c1837SPaolo Bonzini{ 475139c1837SPaolo Bonzini int i; 476139c1837SPaolo Bonzini for (i = 0; i < count; ++i) { 4779ae958e4SRichard Henderson p[i] = OPC_NOP; 478139c1837SPaolo Bonzini } 479139c1837SPaolo Bonzini} 480139c1837SPaolo Bonzini 481139c1837SPaolo Bonzini/* 482139c1837SPaolo Bonzini * Relocations 483139c1837SPaolo Bonzini */ 484139c1837SPaolo Bonzini 485793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 486139c1837SPaolo Bonzini{ 487793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 488793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 489139c1837SPaolo Bonzini 490844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 491844d0442SRichard Henderson if (offset == sextreg(offset, 0, 12)) { 492793f7381SRichard Henderson *src_rw |= encode_sbimm12(offset); 493139c1837SPaolo Bonzini return true; 494139c1837SPaolo Bonzini } 495139c1837SPaolo Bonzini 496139c1837SPaolo Bonzini return false; 497139c1837SPaolo Bonzini} 498139c1837SPaolo Bonzini 499793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 500139c1837SPaolo Bonzini{ 501793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 502793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 503139c1837SPaolo Bonzini 504844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 505844d0442SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 506793f7381SRichard Henderson *src_rw |= encode_ujimm20(offset); 507139c1837SPaolo Bonzini return true; 508139c1837SPaolo Bonzini } 509139c1837SPaolo Bonzini 510139c1837SPaolo Bonzini return false; 511139c1837SPaolo Bonzini} 512139c1837SPaolo Bonzini 513793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target) 514139c1837SPaolo Bonzini{ 515793f7381SRichard Henderson const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); 516793f7381SRichard Henderson intptr_t offset = (intptr_t)target - (intptr_t)src_rx; 517139c1837SPaolo Bonzini int32_t lo = sextreg(offset, 0, 12); 518139c1837SPaolo Bonzini int32_t hi = offset - lo; 519139c1837SPaolo Bonzini 520139c1837SPaolo Bonzini if (offset == hi + lo) { 521793f7381SRichard Henderson src_rw[0] |= encode_uimm20(hi); 522793f7381SRichard Henderson src_rw[1] |= encode_imm12(lo); 523139c1837SPaolo Bonzini return true; 524139c1837SPaolo Bonzini } 525139c1837SPaolo Bonzini 526139c1837SPaolo Bonzini return false; 527139c1837SPaolo Bonzini} 528139c1837SPaolo Bonzini 529139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type, 530139c1837SPaolo Bonzini intptr_t value, intptr_t addend) 531139c1837SPaolo Bonzini{ 532139c1837SPaolo Bonzini tcg_debug_assert(addend == 0); 533139c1837SPaolo Bonzini switch (type) { 534139c1837SPaolo Bonzini case R_RISCV_BRANCH: 535139c1837SPaolo Bonzini return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value); 536139c1837SPaolo Bonzini case R_RISCV_JAL: 537139c1837SPaolo Bonzini return reloc_jimm20(code_ptr, (tcg_insn_unit *)value); 538139c1837SPaolo Bonzini case R_RISCV_CALL: 539139c1837SPaolo Bonzini return reloc_call(code_ptr, (tcg_insn_unit *)value); 540139c1837SPaolo Bonzini default: 5414b6a52d0SRichard Henderson g_assert_not_reached(); 542139c1837SPaolo Bonzini } 543139c1837SPaolo Bonzini} 544139c1837SPaolo Bonzini 545139c1837SPaolo Bonzini/* 546*f63e7089SHuang Shiyuan * RISC-V vector instruction emitters 547*f63e7089SHuang Shiyuan */ 548*f63e7089SHuang Shiyuan 549*f63e7089SHuang Shiyuantypedef struct VsetCache { 550*f63e7089SHuang Shiyuan uint32_t movi_insn; 551*f63e7089SHuang Shiyuan uint32_t vset_insn; 552*f63e7089SHuang Shiyuan} VsetCache; 553*f63e7089SHuang Shiyuan 554*f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4]; 555*f63e7089SHuang Shiyuan 556*f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew) 557*f63e7089SHuang Shiyuan{ 558*f63e7089SHuang Shiyuan const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew]; 559*f63e7089SHuang Shiyuan 560*f63e7089SHuang Shiyuan s->riscv_cur_type = type; 561*f63e7089SHuang Shiyuan s->riscv_cur_vsew = vsew; 562*f63e7089SHuang Shiyuan 563*f63e7089SHuang Shiyuan if (p->movi_insn) { 564*f63e7089SHuang Shiyuan tcg_out32(s, p->movi_insn); 565*f63e7089SHuang Shiyuan } 566*f63e7089SHuang Shiyuan tcg_out32(s, p->vset_insn); 567*f63e7089SHuang Shiyuan} 568*f63e7089SHuang Shiyuan 569*f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type) 570*f63e7089SHuang Shiyuan{ 571*f63e7089SHuang Shiyuan if (type != s->riscv_cur_type) { 572*f63e7089SHuang Shiyuan set_vtype(s, type, MO_64); 573*f63e7089SHuang Shiyuan } 574*f63e7089SHuang Shiyuan return s->riscv_cur_vsew; 575*f63e7089SHuang Shiyuan} 576*f63e7089SHuang Shiyuan 577*f63e7089SHuang Shiyuan/* 578139c1837SPaolo Bonzini * TCG intrinsics 579139c1837SPaolo Bonzini */ 580139c1837SPaolo Bonzini 581139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 582139c1837SPaolo Bonzini{ 583139c1837SPaolo Bonzini if (ret == arg) { 584139c1837SPaolo Bonzini return true; 585139c1837SPaolo Bonzini } 586139c1837SPaolo Bonzini switch (type) { 587139c1837SPaolo Bonzini case TCG_TYPE_I32: 588139c1837SPaolo Bonzini case TCG_TYPE_I64: 589139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0); 590139c1837SPaolo Bonzini break; 591139c1837SPaolo Bonzini default: 592139c1837SPaolo Bonzini g_assert_not_reached(); 593139c1837SPaolo Bonzini } 594139c1837SPaolo Bonzini return true; 595139c1837SPaolo Bonzini} 596139c1837SPaolo Bonzini 597139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, 598139c1837SPaolo Bonzini tcg_target_long val) 599139c1837SPaolo Bonzini{ 600139c1837SPaolo Bonzini tcg_target_long lo, hi, tmp; 601139c1837SPaolo Bonzini int shift, ret; 602139c1837SPaolo Bonzini 603aeb6326eSRichard Henderson if (type == TCG_TYPE_I32) { 604139c1837SPaolo Bonzini val = (int32_t)val; 605139c1837SPaolo Bonzini } 606139c1837SPaolo Bonzini 607139c1837SPaolo Bonzini lo = sextreg(val, 0, 12); 608139c1837SPaolo Bonzini if (val == lo) { 609139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo); 610139c1837SPaolo Bonzini return; 611139c1837SPaolo Bonzini } 612139c1837SPaolo Bonzini 613139c1837SPaolo Bonzini hi = val - lo; 614aeb6326eSRichard Henderson if (val == (int32_t)val) { 615139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, hi); 616139c1837SPaolo Bonzini if (lo != 0) { 617139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo); 618139c1837SPaolo Bonzini } 619139c1837SPaolo Bonzini return; 620139c1837SPaolo Bonzini } 621139c1837SPaolo Bonzini 622139c1837SPaolo Bonzini tmp = tcg_pcrel_diff(s, (void *)val); 623139c1837SPaolo Bonzini if (tmp == (int32_t)tmp) { 624139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); 625139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0); 626793f7381SRichard Henderson ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val); 627139c1837SPaolo Bonzini tcg_debug_assert(ret == true); 628139c1837SPaolo Bonzini return; 629139c1837SPaolo Bonzini } 630139c1837SPaolo Bonzini 631139c1837SPaolo Bonzini /* Look for a single 20-bit section. */ 632139c1837SPaolo Bonzini shift = ctz64(val); 633139c1837SPaolo Bonzini tmp = val >> shift; 634139c1837SPaolo Bonzini if (tmp == sextreg(tmp, 0, 20)) { 635139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12); 636139c1837SPaolo Bonzini if (shift > 12) { 637139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12); 638139c1837SPaolo Bonzini } else { 639139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift); 640139c1837SPaolo Bonzini } 641139c1837SPaolo Bonzini return; 642139c1837SPaolo Bonzini } 643139c1837SPaolo Bonzini 644139c1837SPaolo Bonzini /* Look for a few high zero bits, with lots of bits set in the middle. */ 645139c1837SPaolo Bonzini shift = clz64(val); 646139c1837SPaolo Bonzini tmp = val << shift; 647139c1837SPaolo Bonzini if (tmp == sextreg(tmp, 12, 20) << 12) { 648139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_LUI, rd, tmp); 649139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift); 650139c1837SPaolo Bonzini return; 651139c1837SPaolo Bonzini } else if (tmp == sextreg(tmp, 0, 12)) { 652139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp); 653139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift); 654139c1837SPaolo Bonzini return; 655139c1837SPaolo Bonzini } 656139c1837SPaolo Bonzini 657139c1837SPaolo Bonzini /* Drop into the constant pool. */ 658139c1837SPaolo Bonzini new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0); 659139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, rd, 0); 660139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_LD, rd, rd, 0); 661139c1837SPaolo Bonzini} 662139c1837SPaolo Bonzini 663767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2) 664767c2503SRichard Henderson{ 665767c2503SRichard Henderson return false; 666767c2503SRichard Henderson} 667767c2503SRichard Henderson 6686a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs, 6696a6d772eSRichard Henderson tcg_target_long imm) 6706a6d772eSRichard Henderson{ 6716a6d772eSRichard Henderson /* This function is only used for passing structs by reference. */ 6726a6d772eSRichard Henderson g_assert_not_reached(); 6736a6d772eSRichard Henderson} 6746a6d772eSRichard Henderson 675139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) 676139c1837SPaolo Bonzini{ 677139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff); 678139c1837SPaolo Bonzini} 679139c1837SPaolo Bonzini 680139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) 681139c1837SPaolo Bonzini{ 682b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 683d1c3f4e9SRichard Henderson tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO); 684d1c3f4e9SRichard Henderson } else { 685139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); 686139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16); 687139c1837SPaolo Bonzini } 688d1c3f4e9SRichard Henderson} 689139c1837SPaolo Bonzini 690139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) 691139c1837SPaolo Bonzini{ 692b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBA) { 693d1c3f4e9SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO); 694d1c3f4e9SRichard Henderson } else { 695139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32); 696139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32); 697139c1837SPaolo Bonzini } 698d1c3f4e9SRichard Henderson} 699139c1837SPaolo Bonzini 700678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 701139c1837SPaolo Bonzini{ 702b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 703d1c3f4e9SRichard Henderson tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0); 704d1c3f4e9SRichard Henderson } else { 705139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24); 706139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24); 707139c1837SPaolo Bonzini } 708d1c3f4e9SRichard Henderson} 709139c1837SPaolo Bonzini 710753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) 711139c1837SPaolo Bonzini{ 712b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZBB) { 713d1c3f4e9SRichard Henderson tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0); 714d1c3f4e9SRichard Henderson } else { 715139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); 716139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16); 717139c1837SPaolo Bonzini } 718d1c3f4e9SRichard Henderson} 719139c1837SPaolo Bonzini 720139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) 721139c1837SPaolo Bonzini{ 722139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0); 723139c1837SPaolo Bonzini} 724139c1837SPaolo Bonzini 7259c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg) 7269c6aa274SRichard Henderson{ 7273ea9be33SRichard Henderson if (ret != arg) { 7289c6aa274SRichard Henderson tcg_out_ext32s(s, ret, arg); 7299c6aa274SRichard Henderson } 7303ea9be33SRichard Henderson} 7319c6aa274SRichard Henderson 732b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg) 733b9bfe000SRichard Henderson{ 734b9bfe000SRichard Henderson tcg_out_ext32u(s, ret, arg); 735b9bfe000SRichard Henderson} 736b9bfe000SRichard Henderson 737b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg) 738b8b94ac6SRichard Henderson{ 739b8b94ac6SRichard Henderson tcg_out_ext32s(s, ret, arg); 740b8b94ac6SRichard Henderson} 741b8b94ac6SRichard Henderson 742139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, 743139c1837SPaolo Bonzini TCGReg addr, intptr_t offset) 744139c1837SPaolo Bonzini{ 745139c1837SPaolo Bonzini intptr_t imm12 = sextreg(offset, 0, 12); 746139c1837SPaolo Bonzini 747139c1837SPaolo Bonzini if (offset != imm12) { 7489d9db413SRichard Henderson intptr_t diff = tcg_pcrel_diff(s, (void *)offset); 749139c1837SPaolo Bonzini 750139c1837SPaolo Bonzini if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { 751139c1837SPaolo Bonzini imm12 = sextreg(diff, 0, 12); 752139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12); 753139c1837SPaolo Bonzini } else { 754139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); 755139c1837SPaolo Bonzini if (addr != TCG_REG_ZERO) { 756139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr); 757139c1837SPaolo Bonzini } 758139c1837SPaolo Bonzini } 759139c1837SPaolo Bonzini addr = TCG_REG_TMP2; 760139c1837SPaolo Bonzini } 761139c1837SPaolo Bonzini 762139c1837SPaolo Bonzini switch (opc) { 763139c1837SPaolo Bonzini case OPC_SB: 764139c1837SPaolo Bonzini case OPC_SH: 765139c1837SPaolo Bonzini case OPC_SW: 766139c1837SPaolo Bonzini case OPC_SD: 767139c1837SPaolo Bonzini tcg_out_opc_store(s, opc, addr, data, imm12); 768139c1837SPaolo Bonzini break; 769139c1837SPaolo Bonzini case OPC_LB: 770139c1837SPaolo Bonzini case OPC_LBU: 771139c1837SPaolo Bonzini case OPC_LH: 772139c1837SPaolo Bonzini case OPC_LHU: 773139c1837SPaolo Bonzini case OPC_LW: 774139c1837SPaolo Bonzini case OPC_LWU: 775139c1837SPaolo Bonzini case OPC_LD: 776139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc, data, addr, imm12); 777139c1837SPaolo Bonzini break; 778139c1837SPaolo Bonzini default: 779139c1837SPaolo Bonzini g_assert_not_reached(); 780139c1837SPaolo Bonzini } 781139c1837SPaolo Bonzini} 782139c1837SPaolo Bonzini 783*f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data, 784*f63e7089SHuang Shiyuan TCGReg addr, intptr_t offset) 785*f63e7089SHuang Shiyuan{ 786*f63e7089SHuang Shiyuan tcg_debug_assert(data >= TCG_REG_V0); 787*f63e7089SHuang Shiyuan tcg_debug_assert(addr < TCG_REG_V0); 788*f63e7089SHuang Shiyuan 789*f63e7089SHuang Shiyuan if (offset) { 790*f63e7089SHuang Shiyuan tcg_debug_assert(addr != TCG_REG_ZERO); 791*f63e7089SHuang Shiyuan if (offset == sextreg(offset, 0, 12)) { 792*f63e7089SHuang Shiyuan tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset); 793*f63e7089SHuang Shiyuan } else { 794*f63e7089SHuang Shiyuan tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset); 795*f63e7089SHuang Shiyuan tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr); 796*f63e7089SHuang Shiyuan } 797*f63e7089SHuang Shiyuan addr = TCG_REG_TMP0; 798*f63e7089SHuang Shiyuan } 799*f63e7089SHuang Shiyuan tcg_out32(s, encode_v(opc, data, addr, 0, true)); 800*f63e7089SHuang Shiyuan} 801*f63e7089SHuang Shiyuan 802139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, 803139c1837SPaolo Bonzini TCGReg arg1, intptr_t arg2) 804139c1837SPaolo Bonzini{ 805*f63e7089SHuang Shiyuan RISCVInsn insn; 806*f63e7089SHuang Shiyuan 807*f63e7089SHuang Shiyuan switch (type) { 808*f63e7089SHuang Shiyuan case TCG_TYPE_I32: 809*f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_LW, arg, arg1, arg2); 810*f63e7089SHuang Shiyuan break; 811*f63e7089SHuang Shiyuan case TCG_TYPE_I64: 812*f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_LD, arg, arg1, arg2); 813*f63e7089SHuang Shiyuan break; 814*f63e7089SHuang Shiyuan case TCG_TYPE_V64: 815*f63e7089SHuang Shiyuan case TCG_TYPE_V128: 816*f63e7089SHuang Shiyuan case TCG_TYPE_V256: 817*f63e7089SHuang Shiyuan if (type >= riscv_lg2_vlenb) { 818*f63e7089SHuang Shiyuan static const RISCVInsn whole_reg_ld[] = { 819*f63e7089SHuang Shiyuan OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V 820*f63e7089SHuang Shiyuan }; 821*f63e7089SHuang Shiyuan unsigned idx = type - riscv_lg2_vlenb; 822*f63e7089SHuang Shiyuan 823*f63e7089SHuang Shiyuan tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld)); 824*f63e7089SHuang Shiyuan insn = whole_reg_ld[idx]; 825*f63e7089SHuang Shiyuan } else { 826*f63e7089SHuang Shiyuan static const RISCVInsn unit_stride_ld[] = { 827*f63e7089SHuang Shiyuan OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V 828*f63e7089SHuang Shiyuan }; 829*f63e7089SHuang Shiyuan MemOp prev_vsew = set_vtype_len(s, type); 830*f63e7089SHuang Shiyuan 831*f63e7089SHuang Shiyuan tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld)); 832*f63e7089SHuang Shiyuan insn = unit_stride_ld[prev_vsew]; 833*f63e7089SHuang Shiyuan } 834*f63e7089SHuang Shiyuan tcg_out_vec_ldst(s, insn, arg, arg1, arg2); 835*f63e7089SHuang Shiyuan break; 836*f63e7089SHuang Shiyuan default: 837*f63e7089SHuang Shiyuan g_assert_not_reached(); 838*f63e7089SHuang Shiyuan } 839139c1837SPaolo Bonzini} 840139c1837SPaolo Bonzini 841139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, 842139c1837SPaolo Bonzini TCGReg arg1, intptr_t arg2) 843139c1837SPaolo Bonzini{ 844*f63e7089SHuang Shiyuan RISCVInsn insn; 845*f63e7089SHuang Shiyuan 846*f63e7089SHuang Shiyuan switch (type) { 847*f63e7089SHuang Shiyuan case TCG_TYPE_I32: 848*f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_SW, arg, arg1, arg2); 849*f63e7089SHuang Shiyuan break; 850*f63e7089SHuang Shiyuan case TCG_TYPE_I64: 851*f63e7089SHuang Shiyuan tcg_out_ldst(s, OPC_SD, arg, arg1, arg2); 852*f63e7089SHuang Shiyuan break; 853*f63e7089SHuang Shiyuan case TCG_TYPE_V64: 854*f63e7089SHuang Shiyuan case TCG_TYPE_V128: 855*f63e7089SHuang Shiyuan case TCG_TYPE_V256: 856*f63e7089SHuang Shiyuan if (type >= riscv_lg2_vlenb) { 857*f63e7089SHuang Shiyuan static const RISCVInsn whole_reg_st[] = { 858*f63e7089SHuang Shiyuan OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V 859*f63e7089SHuang Shiyuan }; 860*f63e7089SHuang Shiyuan unsigned idx = type - riscv_lg2_vlenb; 861*f63e7089SHuang Shiyuan 862*f63e7089SHuang Shiyuan tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st)); 863*f63e7089SHuang Shiyuan insn = whole_reg_st[idx]; 864*f63e7089SHuang Shiyuan } else { 865*f63e7089SHuang Shiyuan static const RISCVInsn unit_stride_st[] = { 866*f63e7089SHuang Shiyuan OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V 867*f63e7089SHuang Shiyuan }; 868*f63e7089SHuang Shiyuan MemOp prev_vsew = set_vtype_len(s, type); 869*f63e7089SHuang Shiyuan 870*f63e7089SHuang Shiyuan tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st)); 871*f63e7089SHuang Shiyuan insn = unit_stride_st[prev_vsew]; 872*f63e7089SHuang Shiyuan } 873*f63e7089SHuang Shiyuan tcg_out_vec_ldst(s, insn, arg, arg1, arg2); 874*f63e7089SHuang Shiyuan break; 875*f63e7089SHuang Shiyuan default: 876*f63e7089SHuang Shiyuan g_assert_not_reached(); 877*f63e7089SHuang Shiyuan } 878139c1837SPaolo Bonzini} 879139c1837SPaolo Bonzini 880139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, 881139c1837SPaolo Bonzini TCGReg base, intptr_t ofs) 882139c1837SPaolo Bonzini{ 883139c1837SPaolo Bonzini if (val == 0) { 884139c1837SPaolo Bonzini tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); 885139c1837SPaolo Bonzini return true; 886139c1837SPaolo Bonzini } 887139c1837SPaolo Bonzini return false; 888139c1837SPaolo Bonzini} 889139c1837SPaolo Bonzini 890139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s, 891139c1837SPaolo Bonzini TCGReg rl, TCGReg rh, 892139c1837SPaolo Bonzini TCGReg al, TCGReg ah, 893139c1837SPaolo Bonzini TCGArg bl, TCGArg bh, 894139c1837SPaolo Bonzini bool cbl, bool cbh, bool is_sub, bool is32bit) 895139c1837SPaolo Bonzini{ 896139c1837SPaolo Bonzini const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD; 897139c1837SPaolo Bonzini const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI; 898139c1837SPaolo Bonzini const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB; 899139c1837SPaolo Bonzini TCGReg th = TCG_REG_TMP1; 900139c1837SPaolo Bonzini 901139c1837SPaolo Bonzini /* If we have a negative constant such that negating it would 902139c1837SPaolo Bonzini make the high part zero, we can (usually) eliminate one insn. */ 903139c1837SPaolo Bonzini if (cbl && cbh && bh == -1 && bl != 0) { 904139c1837SPaolo Bonzini bl = -bl; 905139c1837SPaolo Bonzini bh = 0; 906139c1837SPaolo Bonzini is_sub = !is_sub; 907139c1837SPaolo Bonzini } 908139c1837SPaolo Bonzini 909139c1837SPaolo Bonzini /* By operating on the high part first, we get to use the final 910139c1837SPaolo Bonzini carry operation to move back from the temporary. */ 911139c1837SPaolo Bonzini if (!cbh) { 912139c1837SPaolo Bonzini tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh); 913139c1837SPaolo Bonzini } else if (bh != 0 || ah == rl) { 914139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh)); 915139c1837SPaolo Bonzini } else { 916139c1837SPaolo Bonzini th = ah; 917139c1837SPaolo Bonzini } 918139c1837SPaolo Bonzini 919139c1837SPaolo Bonzini /* Note that tcg optimization should eliminate the bl == 0 case. */ 920139c1837SPaolo Bonzini if (is_sub) { 921139c1837SPaolo Bonzini if (cbl) { 922139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl); 923139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, rl, al, -bl); 924139c1837SPaolo Bonzini } else { 925139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl); 926139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_sub, rl, al, bl); 927139c1837SPaolo Bonzini } 928139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0); 929139c1837SPaolo Bonzini } else { 930139c1837SPaolo Bonzini if (cbl) { 931139c1837SPaolo Bonzini tcg_out_opc_imm(s, opc_addi, rl, al, bl); 932139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl); 9339b246685SRichard Henderson } else if (al == bl) { 9349b246685SRichard Henderson /* 9359b246685SRichard Henderson * If the input regs overlap, this is a simple doubling 9369b246685SRichard Henderson * and carry-out is the input msb. This special case is 9379b246685SRichard Henderson * required when the output reg overlaps the input, 9389b246685SRichard Henderson * but we might as well use it always. 9399b246685SRichard Henderson */ 940139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0); 9419b246685SRichard Henderson tcg_out_opc_reg(s, opc_add, rl, al, al); 942139c1837SPaolo Bonzini } else { 943139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_add, rl, al, bl); 944139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, 945139c1837SPaolo Bonzini rl, (rl == bl ? al : bl)); 946139c1837SPaolo Bonzini } 947139c1837SPaolo Bonzini tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0); 948139c1837SPaolo Bonzini } 949139c1837SPaolo Bonzini} 950139c1837SPaolo Bonzini 951*f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece, 952*f63e7089SHuang Shiyuan TCGReg dst, TCGReg src) 953*f63e7089SHuang Shiyuan{ 954*f63e7089SHuang Shiyuan return false; 955*f63e7089SHuang Shiyuan} 956*f63e7089SHuang Shiyuan 957*f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece, 958*f63e7089SHuang Shiyuan TCGReg dst, TCGReg base, intptr_t offset) 959*f63e7089SHuang Shiyuan{ 960*f63e7089SHuang Shiyuan return false; 961*f63e7089SHuang Shiyuan} 962*f63e7089SHuang Shiyuan 963*f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece, 964*f63e7089SHuang Shiyuan TCGReg dst, int64_t arg) 965*f63e7089SHuang Shiyuan{ 966*f63e7089SHuang Shiyuan} 967*f63e7089SHuang Shiyuan 968139c1837SPaolo Bonzinistatic const struct { 969139c1837SPaolo Bonzini RISCVInsn op; 970139c1837SPaolo Bonzini bool swap; 971139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = { 972139c1837SPaolo Bonzini [TCG_COND_EQ] = { OPC_BEQ, false }, 973139c1837SPaolo Bonzini [TCG_COND_NE] = { OPC_BNE, false }, 974139c1837SPaolo Bonzini [TCG_COND_LT] = { OPC_BLT, false }, 975139c1837SPaolo Bonzini [TCG_COND_GE] = { OPC_BGE, false }, 976139c1837SPaolo Bonzini [TCG_COND_LE] = { OPC_BGE, true }, 977139c1837SPaolo Bonzini [TCG_COND_GT] = { OPC_BLT, true }, 978139c1837SPaolo Bonzini [TCG_COND_LTU] = { OPC_BLTU, false }, 979139c1837SPaolo Bonzini [TCG_COND_GEU] = { OPC_BGEU, false }, 980139c1837SPaolo Bonzini [TCG_COND_LEU] = { OPC_BGEU, true }, 981139c1837SPaolo Bonzini [TCG_COND_GTU] = { OPC_BLTU, true } 982139c1837SPaolo Bonzini}; 983139c1837SPaolo Bonzini 984139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, 985139c1837SPaolo Bonzini TCGReg arg2, TCGLabel *l) 986139c1837SPaolo Bonzini{ 987139c1837SPaolo Bonzini RISCVInsn op = tcg_brcond_to_riscv[cond].op; 988139c1837SPaolo Bonzini 989139c1837SPaolo Bonzini tcg_debug_assert(op != 0); 990139c1837SPaolo Bonzini 991139c1837SPaolo Bonzini if (tcg_brcond_to_riscv[cond].swap) { 992139c1837SPaolo Bonzini TCGReg t = arg1; 993139c1837SPaolo Bonzini arg1 = arg2; 994139c1837SPaolo Bonzini arg2 = t; 995139c1837SPaolo Bonzini } 996139c1837SPaolo Bonzini 997139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0); 998139c1837SPaolo Bonzini tcg_out_opc_branch(s, op, arg1, arg2, 0); 999139c1837SPaolo Bonzini} 1000139c1837SPaolo Bonzini 1001f6453695SRichard Henderson#define SETCOND_INV TCG_TARGET_NB_REGS 1002f6453695SRichard Henderson#define SETCOND_NEZ (SETCOND_INV << 1) 1003f6453695SRichard Henderson#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ) 1004f6453695SRichard Henderson 1005f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret, 1006f6453695SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 1007139c1837SPaolo Bonzini{ 1008f6453695SRichard Henderson int flags = 0; 1009f6453695SRichard Henderson 1010139c1837SPaolo Bonzini switch (cond) { 1011f6453695SRichard Henderson case TCG_COND_EQ: /* -> NE */ 1012f6453695SRichard Henderson case TCG_COND_GE: /* -> LT */ 1013f6453695SRichard Henderson case TCG_COND_GEU: /* -> LTU */ 1014f6453695SRichard Henderson case TCG_COND_GT: /* -> LE */ 1015f6453695SRichard Henderson case TCG_COND_GTU: /* -> LEU */ 1016f6453695SRichard Henderson cond = tcg_invert_cond(cond); 1017f6453695SRichard Henderson flags ^= SETCOND_INV; 1018139c1837SPaolo Bonzini break; 1019f6453695SRichard Henderson default: 1020139c1837SPaolo Bonzini break; 1021f6453695SRichard Henderson } 1022f6453695SRichard Henderson 1023f6453695SRichard Henderson switch (cond) { 1024139c1837SPaolo Bonzini case TCG_COND_LE: 1025139c1837SPaolo Bonzini case TCG_COND_LEU: 1026f6453695SRichard Henderson /* 1027f6453695SRichard Henderson * If we have a constant input, the most efficient way to implement 1028f6453695SRichard Henderson * LE is by adding 1 and using LT. Watch out for wrap around for LEU. 1029f6453695SRichard Henderson * We don't need to care for this for LE because the constant input 1030f6453695SRichard Henderson * is constrained to signed 12-bit, and 0x800 is representable in the 1031f6453695SRichard Henderson * temporary register. 1032f6453695SRichard Henderson */ 1033f6453695SRichard Henderson if (c2) { 1034f6453695SRichard Henderson if (cond == TCG_COND_LEU) { 1035f6453695SRichard Henderson /* unsigned <= -1 is true */ 1036f6453695SRichard Henderson if (arg2 == -1) { 1037f6453695SRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV)); 1038f6453695SRichard Henderson return ret; 1039f6453695SRichard Henderson } 1040f6453695SRichard Henderson cond = TCG_COND_LTU; 1041f6453695SRichard Henderson } else { 1042f6453695SRichard Henderson cond = TCG_COND_LT; 1043f6453695SRichard Henderson } 1044f6453695SRichard Henderson tcg_debug_assert(arg2 <= 0x7ff); 1045f6453695SRichard Henderson if (++arg2 == 0x800) { 1046f6453695SRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2); 1047f6453695SRichard Henderson arg2 = TCG_REG_TMP0; 1048f6453695SRichard Henderson c2 = false; 1049f6453695SRichard Henderson } 1050f6453695SRichard Henderson } else { 1051f6453695SRichard Henderson TCGReg tmp = arg2; 1052f6453695SRichard Henderson arg2 = arg1; 1053f6453695SRichard Henderson arg1 = tmp; 1054f6453695SRichard Henderson cond = tcg_swap_cond(cond); /* LE -> GE */ 1055f6453695SRichard Henderson cond = tcg_invert_cond(cond); /* GE -> LT */ 1056f6453695SRichard Henderson flags ^= SETCOND_INV; 1057f6453695SRichard Henderson } 1058139c1837SPaolo Bonzini break; 1059f6453695SRichard Henderson default: 1060f6453695SRichard Henderson break; 1061f6453695SRichard Henderson } 1062f6453695SRichard Henderson 1063f6453695SRichard Henderson switch (cond) { 1064f6453695SRichard Henderson case TCG_COND_NE: 1065f6453695SRichard Henderson flags |= SETCOND_NEZ; 1066f6453695SRichard Henderson if (!c2) { 1067f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2); 1068f6453695SRichard Henderson } else if (arg2 == 0) { 1069f6453695SRichard Henderson ret = arg1; 1070f6453695SRichard Henderson } else { 1071f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2); 1072f6453695SRichard Henderson } 1073f6453695SRichard Henderson break; 1074f6453695SRichard Henderson 1075f6453695SRichard Henderson case TCG_COND_LT: 1076f6453695SRichard Henderson if (c2) { 1077f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2); 1078f6453695SRichard Henderson } else { 1079f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); 1080f6453695SRichard Henderson } 1081f6453695SRichard Henderson break; 1082f6453695SRichard Henderson 1083f6453695SRichard Henderson case TCG_COND_LTU: 1084f6453695SRichard Henderson if (c2) { 1085f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2); 1086f6453695SRichard Henderson } else { 1087f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); 1088f6453695SRichard Henderson } 1089f6453695SRichard Henderson break; 1090f6453695SRichard Henderson 1091f6453695SRichard Henderson default: 1092f6453695SRichard Henderson g_assert_not_reached(); 1093f6453695SRichard Henderson } 1094f6453695SRichard Henderson 1095f6453695SRichard Henderson return ret | flags; 1096f6453695SRichard Henderson} 1097f6453695SRichard Henderson 1098f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, 1099f6453695SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 1100f6453695SRichard Henderson{ 1101f6453695SRichard Henderson int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); 1102f6453695SRichard Henderson 1103f6453695SRichard Henderson if (tmpflags != ret) { 1104f6453695SRichard Henderson TCGReg tmp = tmpflags & ~SETCOND_FLAGS; 1105f6453695SRichard Henderson 1106f6453695SRichard Henderson switch (tmpflags & SETCOND_FLAGS) { 1107f6453695SRichard Henderson case SETCOND_INV: 1108f6453695SRichard Henderson /* Intermediate result is boolean: simply invert. */ 1109f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1); 1110f6453695SRichard Henderson break; 1111f6453695SRichard Henderson case SETCOND_NEZ: 1112f6453695SRichard Henderson /* Intermediate result is zero/non-zero: test != 0. */ 1113f6453695SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp); 1114f6453695SRichard Henderson break; 1115f6453695SRichard Henderson case SETCOND_NEZ | SETCOND_INV: 1116f6453695SRichard Henderson /* Intermediate result is zero/non-zero: test == 0. */ 1117f6453695SRichard Henderson tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1); 1118139c1837SPaolo Bonzini break; 1119139c1837SPaolo Bonzini default: 1120139c1837SPaolo Bonzini g_assert_not_reached(); 1121f6453695SRichard Henderson } 1122139c1837SPaolo Bonzini } 1123139c1837SPaolo Bonzini} 1124139c1837SPaolo Bonzini 112541e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret, 112641e4c0a9SRichard Henderson TCGReg arg1, tcg_target_long arg2, bool c2) 112741e4c0a9SRichard Henderson{ 112841e4c0a9SRichard Henderson int tmpflags; 112941e4c0a9SRichard Henderson TCGReg tmp; 113041e4c0a9SRichard Henderson 113141e4c0a9SRichard Henderson /* For LT/GE comparison against 0, replicate the sign bit. */ 113241e4c0a9SRichard Henderson if (c2 && arg2 == 0) { 113341e4c0a9SRichard Henderson switch (cond) { 113441e4c0a9SRichard Henderson case TCG_COND_GE: 113541e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1); 113641e4c0a9SRichard Henderson arg1 = ret; 113741e4c0a9SRichard Henderson /* fall through */ 113841e4c0a9SRichard Henderson case TCG_COND_LT: 113941e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1); 114041e4c0a9SRichard Henderson return; 114141e4c0a9SRichard Henderson default: 114241e4c0a9SRichard Henderson break; 114341e4c0a9SRichard Henderson } 114441e4c0a9SRichard Henderson } 114541e4c0a9SRichard Henderson 114641e4c0a9SRichard Henderson tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); 114741e4c0a9SRichard Henderson tmp = tmpflags & ~SETCOND_FLAGS; 114841e4c0a9SRichard Henderson 114941e4c0a9SRichard Henderson /* If intermediate result is zero/non-zero: test != 0. */ 115041e4c0a9SRichard Henderson if (tmpflags & SETCOND_NEZ) { 115141e4c0a9SRichard Henderson tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp); 115241e4c0a9SRichard Henderson tmp = ret; 115341e4c0a9SRichard Henderson } 115441e4c0a9SRichard Henderson 115541e4c0a9SRichard Henderson /* Produce the 0/-1 result. */ 115641e4c0a9SRichard Henderson if (tmpflags & SETCOND_INV) { 115741e4c0a9SRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1); 115841e4c0a9SRichard Henderson } else { 115941e4c0a9SRichard Henderson tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp); 116041e4c0a9SRichard Henderson } 116141e4c0a9SRichard Henderson} 116241e4c0a9SRichard Henderson 1163a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne, 1164a18d783eSRichard Henderson int val1, bool c_val1, 1165a18d783eSRichard Henderson int val2, bool c_val2) 1166a18d783eSRichard Henderson{ 1167a18d783eSRichard Henderson if (val1 == 0) { 1168a18d783eSRichard Henderson if (c_val2) { 1169a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2); 1170a18d783eSRichard Henderson val2 = TCG_REG_TMP1; 1171a18d783eSRichard Henderson } 1172a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne); 1173a18d783eSRichard Henderson return; 1174a18d783eSRichard Henderson } 1175a18d783eSRichard Henderson 1176a18d783eSRichard Henderson if (val2 == 0) { 1177a18d783eSRichard Henderson if (c_val1) { 1178a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1); 1179a18d783eSRichard Henderson val1 = TCG_REG_TMP1; 1180a18d783eSRichard Henderson } 1181a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne); 1182a18d783eSRichard Henderson return; 1183a18d783eSRichard Henderson } 1184a18d783eSRichard Henderson 1185a18d783eSRichard Henderson if (c_val2) { 1186a18d783eSRichard Henderson if (c_val1) { 1187a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2); 1188a18d783eSRichard Henderson } else { 1189a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2); 1190a18d783eSRichard Henderson } 1191a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne); 1192a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2); 1193a18d783eSRichard Henderson return; 1194a18d783eSRichard Henderson } 1195a18d783eSRichard Henderson 1196a18d783eSRichard Henderson if (c_val1) { 1197a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1); 1198a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne); 1199a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1); 1200a18d783eSRichard Henderson return; 1201a18d783eSRichard Henderson } 1202a18d783eSRichard Henderson 1203a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne); 1204a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne); 1205a18d783eSRichard Henderson tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1); 1206a18d783eSRichard Henderson} 1207a18d783eSRichard Henderson 1208a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret, 1209a18d783eSRichard Henderson TCGReg cmp1, TCGReg cmp2, 1210a18d783eSRichard Henderson int val, bool c_val) 1211a18d783eSRichard Henderson{ 1212a18d783eSRichard Henderson RISCVInsn op; 1213a18d783eSRichard Henderson int disp = 8; 1214a18d783eSRichard Henderson 1215a18d783eSRichard Henderson tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv)); 1216a18d783eSRichard Henderson op = tcg_brcond_to_riscv[cond].op; 1217a18d783eSRichard Henderson tcg_debug_assert(op != 0); 1218a18d783eSRichard Henderson 1219a18d783eSRichard Henderson if (tcg_brcond_to_riscv[cond].swap) { 1220a18d783eSRichard Henderson tcg_out_opc_branch(s, op, cmp2, cmp1, disp); 1221a18d783eSRichard Henderson } else { 1222a18d783eSRichard Henderson tcg_out_opc_branch(s, op, cmp1, cmp2, disp); 1223a18d783eSRichard Henderson } 1224a18d783eSRichard Henderson if (c_val) { 1225a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val); 1226a18d783eSRichard Henderson } else { 1227a18d783eSRichard Henderson tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0); 1228a18d783eSRichard Henderson } 1229a18d783eSRichard Henderson} 1230a18d783eSRichard Henderson 1231a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret, 1232a18d783eSRichard Henderson TCGReg cmp1, TCGReg cmp2, 1233a18d783eSRichard Henderson int val1, bool c_val1, 1234a18d783eSRichard Henderson int val2, bool c_val2) 1235a18d783eSRichard Henderson{ 1236a18d783eSRichard Henderson TCGReg tmp; 1237a18d783eSRichard Henderson 1238a18d783eSRichard Henderson /* TCG optimizer reorders to prefer ret matching val2. */ 1239a18d783eSRichard Henderson if (!c_val2 && ret == val2) { 1240a18d783eSRichard Henderson cond = tcg_invert_cond(cond); 1241a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1); 1242a18d783eSRichard Henderson return; 1243a18d783eSRichard Henderson } 1244a18d783eSRichard Henderson 1245a18d783eSRichard Henderson if (!c_val1 && ret == val1) { 1246a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2); 1247a18d783eSRichard Henderson return; 1248a18d783eSRichard Henderson } 1249a18d783eSRichard Henderson 1250a18d783eSRichard Henderson tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret); 1251a18d783eSRichard Henderson if (c_val1) { 1252a18d783eSRichard Henderson tcg_out_movi(s, TCG_TYPE_REG, tmp, val1); 1253a18d783eSRichard Henderson } else { 1254a18d783eSRichard Henderson tcg_out_mov(s, TCG_TYPE_REG, tmp, val1); 1255a18d783eSRichard Henderson } 1256a18d783eSRichard Henderson tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2); 1257a18d783eSRichard Henderson tcg_out_mov(s, TCG_TYPE_REG, ret, tmp); 1258a18d783eSRichard Henderson} 1259a18d783eSRichard Henderson 1260a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, 1261a18d783eSRichard Henderson TCGReg cmp1, int cmp2, bool c_cmp2, 1262a18d783eSRichard Henderson TCGReg val1, bool c_val1, 1263a18d783eSRichard Henderson TCGReg val2, bool c_val2) 1264a18d783eSRichard Henderson{ 1265a18d783eSRichard Henderson int tmpflags; 1266a18d783eSRichard Henderson TCGReg t; 1267a18d783eSRichard Henderson 1268b86c6ba6SRichard Henderson if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) { 1269a18d783eSRichard Henderson tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2, 1270a18d783eSRichard Henderson val1, c_val1, val2, c_val2); 1271a18d783eSRichard Henderson return; 1272a18d783eSRichard Henderson } 1273a18d783eSRichard Henderson 1274a18d783eSRichard Henderson tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2); 1275a18d783eSRichard Henderson t = tmpflags & ~SETCOND_FLAGS; 1276a18d783eSRichard Henderson 1277b86c6ba6SRichard Henderson if (cpuinfo & CPUINFO_ZICOND) { 1278a18d783eSRichard Henderson if (tmpflags & SETCOND_INV) { 1279a18d783eSRichard Henderson tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1); 1280a18d783eSRichard Henderson } else { 1281a18d783eSRichard Henderson tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2); 1282a18d783eSRichard Henderson } 1283a18d783eSRichard Henderson } else { 1284a18d783eSRichard Henderson cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE; 1285a18d783eSRichard Henderson tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO, 1286a18d783eSRichard Henderson val1, c_val1, val2, c_val2); 1287a18d783eSRichard Henderson } 1288a18d783eSRichard Henderson} 1289a18d783eSRichard Henderson 1290a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn, 1291a30498fcSRichard Henderson TCGReg ret, TCGReg src1, int src2, bool c_src2) 1292a30498fcSRichard Henderson{ 1293a30498fcSRichard Henderson tcg_out_opc_imm(s, insn, ret, src1, 0); 1294a30498fcSRichard Henderson 1295a30498fcSRichard Henderson if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) { 1296a30498fcSRichard Henderson /* 1297a30498fcSRichard Henderson * The requested zero result does not match the insn, so adjust. 1298a30498fcSRichard Henderson * Note that constraints put 'ret' in a new register, so the 1299a30498fcSRichard Henderson * computation above did not clobber either 'src1' or 'src2'. 1300a30498fcSRichard Henderson */ 1301a30498fcSRichard Henderson tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true, 1302a30498fcSRichard Henderson src2, c_src2, ret, false); 1303a30498fcSRichard Henderson } 1304a30498fcSRichard Henderson} 1305a30498fcSRichard Henderson 1306*f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s) 1307*f63e7089SHuang Shiyuan{ 1308*f63e7089SHuang Shiyuan s->riscv_cur_type = TCG_TYPE_COUNT; 1309*f63e7089SHuang Shiyuan} 1310*f63e7089SHuang Shiyuan 13112be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) 1312139c1837SPaolo Bonzini{ 1313139c1837SPaolo Bonzini TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; 1314139c1837SPaolo Bonzini ptrdiff_t offset = tcg_pcrel_diff(s, arg); 1315139c1837SPaolo Bonzini int ret; 1316139c1837SPaolo Bonzini 1317*f63e7089SHuang Shiyuan init_setting_vtype(s); 1318*f63e7089SHuang Shiyuan 1319844d0442SRichard Henderson tcg_debug_assert((offset & 1) == 0); 1320844d0442SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 1321139c1837SPaolo Bonzini /* short jump: -2097150 to 2097152 */ 1322139c1837SPaolo Bonzini tcg_out_opc_jump(s, OPC_JAL, link, offset); 1323aeb6326eSRichard Henderson } else if (offset == (int32_t)offset) { 1324139c1837SPaolo Bonzini /* long jump: -2147483646 to 2147483648 */ 1325139c1837SPaolo Bonzini tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0); 1326139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0); 1327844d0442SRichard Henderson ret = reloc_call(s->code_ptr - 2, arg); 1328139c1837SPaolo Bonzini tcg_debug_assert(ret == true); 1329aeb6326eSRichard Henderson } else { 1330139c1837SPaolo Bonzini /* far jump: 64-bit */ 1331139c1837SPaolo Bonzini tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12); 1332139c1837SPaolo Bonzini tcg_target_long base = (tcg_target_long)arg - imm; 1333139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base); 1334139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm); 1335139c1837SPaolo Bonzini } 1336139c1837SPaolo Bonzini} 1337139c1837SPaolo Bonzini 1338cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg, 1339cee44b03SRichard Henderson const TCGHelperInfo *info) 1340139c1837SPaolo Bonzini{ 1341139c1837SPaolo Bonzini tcg_out_call_int(s, arg, false); 1342139c1837SPaolo Bonzini} 1343139c1837SPaolo Bonzini 1344139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0) 1345139c1837SPaolo Bonzini{ 1346139c1837SPaolo Bonzini tcg_insn_unit insn = OPC_FENCE; 1347139c1837SPaolo Bonzini 1348139c1837SPaolo Bonzini if (a0 & TCG_MO_LD_LD) { 1349139c1837SPaolo Bonzini insn |= 0x02200000; 1350139c1837SPaolo Bonzini } 1351139c1837SPaolo Bonzini if (a0 & TCG_MO_ST_LD) { 1352139c1837SPaolo Bonzini insn |= 0x01200000; 1353139c1837SPaolo Bonzini } 1354139c1837SPaolo Bonzini if (a0 & TCG_MO_LD_ST) { 1355139c1837SPaolo Bonzini insn |= 0x02100000; 1356139c1837SPaolo Bonzini } 1357139c1837SPaolo Bonzini if (a0 & TCG_MO_ST_ST) { 1358139c1837SPaolo Bonzini insn |= 0x02200000; 1359139c1837SPaolo Bonzini } 1360139c1837SPaolo Bonzini tcg_out32(s, insn); 1361139c1837SPaolo Bonzini} 1362139c1837SPaolo Bonzini 1363139c1837SPaolo Bonzini/* 1364139c1837SPaolo Bonzini * Load/store and TLB 1365139c1837SPaolo Bonzini */ 1366139c1837SPaolo Bonzini 1367793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) 1368844d0442SRichard Henderson{ 1369844d0442SRichard Henderson tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0); 1370844d0442SRichard Henderson bool ok = reloc_jimm20(s->code_ptr - 1, target); 1371844d0442SRichard Henderson tcg_debug_assert(ok); 1372844d0442SRichard Henderson} 1373844d0442SRichard Henderson 13747b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop) 13757b880107SRichard Henderson{ 13767b880107SRichard Henderson return false; 13777b880107SRichard Henderson} 13787b880107SRichard Henderson 137961b6daafSRichard Henderson/* We have three temps, we might as well expose them. */ 138061b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = { 138161b6daafSRichard Henderson .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 } 138261b6daafSRichard Henderson}; 138361b6daafSRichard Henderson 1384139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1385139c1837SPaolo Bonzini{ 138661b6daafSRichard Henderson MemOp opc = get_memop(l->oi); 1387139c1837SPaolo Bonzini 1388139c1837SPaolo Bonzini /* resolve label address */ 1389793f7381SRichard Henderson if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1390139c1837SPaolo Bonzini return false; 1391139c1837SPaolo Bonzini } 1392139c1837SPaolo Bonzini 1393139c1837SPaolo Bonzini /* call load helper */ 139461b6daafSRichard Henderson tcg_out_ld_helper_args(s, l, &ldst_helper_param); 1395cee44b03SRichard Henderson tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false); 139661b6daafSRichard Henderson tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param); 1397139c1837SPaolo Bonzini 1398139c1837SPaolo Bonzini tcg_out_goto(s, l->raddr); 1399139c1837SPaolo Bonzini return true; 1400139c1837SPaolo Bonzini} 1401139c1837SPaolo Bonzini 1402139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) 1403139c1837SPaolo Bonzini{ 140461b6daafSRichard Henderson MemOp opc = get_memop(l->oi); 1405139c1837SPaolo Bonzini 1406139c1837SPaolo Bonzini /* resolve label address */ 1407793f7381SRichard Henderson if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { 1408139c1837SPaolo Bonzini return false; 1409139c1837SPaolo Bonzini } 1410139c1837SPaolo Bonzini 1411139c1837SPaolo Bonzini /* call store helper */ 141261b6daafSRichard Henderson tcg_out_st_helper_args(s, l, &ldst_helper_param); 1413cee44b03SRichard Henderson tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false); 1414139c1837SPaolo Bonzini 1415139c1837SPaolo Bonzini tcg_out_goto(s, l->raddr); 1416139c1837SPaolo Bonzini return true; 1417139c1837SPaolo Bonzini} 1418139c1837SPaolo Bonzini 1419d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV. */ 1420d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS -(1 << 11) 1421d0a9bb5eSRichard Henderson 1422001dddfeSRichard Henderson/* 14237893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare. 14247893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests. 1425001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path 1426001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path. 1427001dddfeSRichard Henderson */ 1428001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase, 1429001dddfeSRichard Henderson TCGReg addr_reg, MemOpIdx oi, 1430001dddfeSRichard Henderson bool is_ld) 1431001dddfeSRichard Henderson{ 14328aefe1fbSRichard Henderson TCGType addr_type = s->addr_type; 1433001dddfeSRichard Henderson TCGLabelQemuLdst *ldst = NULL; 1434001dddfeSRichard Henderson MemOp opc = get_memop(oi); 143537e523f0SRichard Henderson TCGAtomAlign aa; 143637e523f0SRichard Henderson unsigned a_mask; 143737e523f0SRichard Henderson 143837e523f0SRichard Henderson aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false); 143937e523f0SRichard Henderson a_mask = (1u << aa.align) - 1; 1440001dddfeSRichard Henderson 14414944d359SRichard Henderson if (tcg_use_softmmu) { 1442001dddfeSRichard Henderson unsigned s_bits = opc & MO_SIZE; 1443933b331bSRichard Henderson unsigned s_mask = (1u << s_bits) - 1; 1444001dddfeSRichard Henderson int mem_index = get_mmuidx(oi); 1445d0a9bb5eSRichard Henderson int fast_ofs = tlb_mask_table_ofs(s, mem_index); 1446001dddfeSRichard Henderson int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); 1447001dddfeSRichard Henderson int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); 1448933b331bSRichard Henderson int compare_mask; 1449933b331bSRichard Henderson TCGReg addr_adj; 1450001dddfeSRichard Henderson 1451001dddfeSRichard Henderson ldst = new_ldst_label(s); 1452001dddfeSRichard Henderson ldst->is_ld = is_ld; 1453001dddfeSRichard Henderson ldst->oi = oi; 1454001dddfeSRichard Henderson ldst->addrlo_reg = addr_reg; 1455001dddfeSRichard Henderson 1456*f63e7089SHuang Shiyuan init_setting_vtype(s); 1457*f63e7089SHuang Shiyuan 1458933b331bSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); 1459933b331bSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); 1460001dddfeSRichard Henderson 1461001dddfeSRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg, 1462aece72b7SRichard Henderson s->page_bits - CPU_TLB_ENTRY_BITS); 1463001dddfeSRichard Henderson tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); 1464001dddfeSRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); 1465001dddfeSRichard Henderson 1466933b331bSRichard Henderson /* 14674944d359SRichard Henderson * For aligned accesses, we check the first byte and include the 14684944d359SRichard Henderson * alignment bits within the address. For unaligned access, we 14694944d359SRichard Henderson * check that we don't cross pages using the address of the last 14704944d359SRichard Henderson * byte of the access. 1471933b331bSRichard Henderson */ 1472933b331bSRichard Henderson addr_adj = addr_reg; 147337e523f0SRichard Henderson if (a_mask < s_mask) { 1474933b331bSRichard Henderson addr_adj = TCG_REG_TMP0; 14758aefe1fbSRichard Henderson tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI, 1476933b331bSRichard Henderson addr_adj, addr_reg, s_mask - a_mask); 1477933b331bSRichard Henderson } 1478aece72b7SRichard Henderson compare_mask = s->page_mask | a_mask; 1479933b331bSRichard Henderson if (compare_mask == sextreg(compare_mask, 0, 12)) { 1480933b331bSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask); 1481933b331bSRichard Henderson } else { 14828aefe1fbSRichard Henderson tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask); 1483933b331bSRichard Henderson tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj); 1484933b331bSRichard Henderson } 1485933b331bSRichard Henderson 1486001dddfeSRichard Henderson /* Load the tlb comparator and the addend. */ 1487238f4380SRichard Henderson QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN); 14888aefe1fbSRichard Henderson tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2, 1489001dddfeSRichard Henderson is_ld ? offsetof(CPUTLBEntry, addr_read) 1490001dddfeSRichard Henderson : offsetof(CPUTLBEntry, addr_write)); 1491001dddfeSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, 1492001dddfeSRichard Henderson offsetof(CPUTLBEntry, addend)); 1493001dddfeSRichard Henderson 1494001dddfeSRichard Henderson /* Compare masked address with the TLB entry. */ 1495001dddfeSRichard Henderson ldst->label_ptr[0] = s->code_ptr; 1496001dddfeSRichard Henderson tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0); 1497001dddfeSRichard Henderson 1498001dddfeSRichard Henderson /* TLB Hit - translate address using addend. */ 14998aefe1fbSRichard Henderson if (addr_type != TCG_TYPE_I32) { 1500eda15159SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2); 1501b86c6ba6SRichard Henderson } else if (cpuinfo & CPUINFO_ZBA) { 15024944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, 15034944d359SRichard Henderson addr_reg, TCG_REG_TMP2); 1504eda15159SRichard Henderson } else { 1505eda15159SRichard Henderson tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg); 15064944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, 15074944d359SRichard Henderson TCG_REG_TMP0, TCG_REG_TMP2); 1508001dddfeSRichard Henderson } 1509001dddfeSRichard Henderson *pbase = TCG_REG_TMP0; 15104944d359SRichard Henderson } else { 1511eda15159SRichard Henderson TCGReg base; 1512eda15159SRichard Henderson 1513001dddfeSRichard Henderson if (a_mask) { 1514001dddfeSRichard Henderson ldst = new_ldst_label(s); 1515001dddfeSRichard Henderson ldst->is_ld = is_ld; 1516001dddfeSRichard Henderson ldst->oi = oi; 1517001dddfeSRichard Henderson ldst->addrlo_reg = addr_reg; 1518001dddfeSRichard Henderson 1519*f63e7089SHuang Shiyuan init_setting_vtype(s); 1520*f63e7089SHuang Shiyuan 152137e523f0SRichard Henderson /* We are expecting alignment max 7, so we can always use andi. */ 152237e523f0SRichard Henderson tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12)); 1523001dddfeSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask); 1524001dddfeSRichard Henderson 1525001dddfeSRichard Henderson ldst->label_ptr[0] = s->code_ptr; 1526001dddfeSRichard Henderson tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0); 1527001dddfeSRichard Henderson } 1528001dddfeSRichard Henderson 1529001dddfeSRichard Henderson if (guest_base != 0) { 1530001dddfeSRichard Henderson base = TCG_REG_TMP0; 15318aefe1fbSRichard Henderson if (addr_type != TCG_TYPE_I32) { 15324944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, 15334944d359SRichard Henderson TCG_GUEST_BASE_REG); 1534b86c6ba6SRichard Henderson } else if (cpuinfo & CPUINFO_ZBA) { 15354944d359SRichard Henderson tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, 15364944d359SRichard Henderson TCG_GUEST_BASE_REG); 1537eda15159SRichard Henderson } else { 1538eda15159SRichard Henderson tcg_out_ext32u(s, base, addr_reg); 1539eda15159SRichard Henderson tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG); 1540eda15159SRichard Henderson } 15418aefe1fbSRichard Henderson } else if (addr_type != TCG_TYPE_I32) { 1542eda15159SRichard Henderson base = addr_reg; 1543eda15159SRichard Henderson } else { 1544eda15159SRichard Henderson base = TCG_REG_TMP0; 1545eda15159SRichard Henderson tcg_out_ext32u(s, base, addr_reg); 1546001dddfeSRichard Henderson } 1547001dddfeSRichard Henderson *pbase = base; 15484944d359SRichard Henderson } 1549001dddfeSRichard Henderson 1550001dddfeSRichard Henderson return ldst; 1551001dddfeSRichard Henderson} 1552001dddfeSRichard Henderson 1553aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val, 1554f7041977SRichard Henderson TCGReg base, MemOp opc, TCGType type) 1555139c1837SPaolo Bonzini{ 1556c86bd2dcSRichard Henderson /* Byte swapping is left to middle-end expansion. */ 1557c86bd2dcSRichard Henderson tcg_debug_assert((opc & MO_BSWAP) == 0); 1558139c1837SPaolo Bonzini 1559139c1837SPaolo Bonzini switch (opc & (MO_SSIZE)) { 1560139c1837SPaolo Bonzini case MO_UB: 1561aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LBU, val, base, 0); 1562139c1837SPaolo Bonzini break; 1563139c1837SPaolo Bonzini case MO_SB: 1564aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LB, val, base, 0); 1565139c1837SPaolo Bonzini break; 1566139c1837SPaolo Bonzini case MO_UW: 1567aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LHU, val, base, 0); 1568139c1837SPaolo Bonzini break; 1569139c1837SPaolo Bonzini case MO_SW: 1570aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LH, val, base, 0); 1571139c1837SPaolo Bonzini break; 1572139c1837SPaolo Bonzini case MO_UL: 1573f7041977SRichard Henderson if (type == TCG_TYPE_I64) { 1574aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LWU, val, base, 0); 1575139c1837SPaolo Bonzini break; 1576139c1837SPaolo Bonzini } 1577139c1837SPaolo Bonzini /* FALLTHRU */ 1578139c1837SPaolo Bonzini case MO_SL: 1579aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LW, val, base, 0); 1580139c1837SPaolo Bonzini break; 1581fc313c64SFrédéric Pétrot case MO_UQ: 1582aeb6326eSRichard Henderson tcg_out_opc_imm(s, OPC_LD, val, base, 0); 1583139c1837SPaolo Bonzini break; 1584139c1837SPaolo Bonzini default: 1585139c1837SPaolo Bonzini g_assert_not_reached(); 1586139c1837SPaolo Bonzini } 1587139c1837SPaolo Bonzini} 1588139c1837SPaolo Bonzini 1589f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1590f7041977SRichard Henderson MemOpIdx oi, TCGType data_type) 1591139c1837SPaolo Bonzini{ 1592001dddfeSRichard Henderson TCGLabelQemuLdst *ldst; 15932e3a933aSRichard Henderson TCGReg base; 1594139c1837SPaolo Bonzini 1595001dddfeSRichard Henderson ldst = prepare_host_addr(s, &base, addr_reg, oi, true); 1596001dddfeSRichard Henderson tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type); 1597f7041977SRichard Henderson 1598001dddfeSRichard Henderson if (ldst) { 1599001dddfeSRichard Henderson ldst->type = data_type; 1600001dddfeSRichard Henderson ldst->datalo_reg = data_reg; 1601001dddfeSRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1602a3fb7c99SRichard Henderson } 1603139c1837SPaolo Bonzini} 1604139c1837SPaolo Bonzini 1605aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val, 1606139c1837SPaolo Bonzini TCGReg base, MemOp opc) 1607139c1837SPaolo Bonzini{ 1608c86bd2dcSRichard Henderson /* Byte swapping is left to middle-end expansion. */ 1609c86bd2dcSRichard Henderson tcg_debug_assert((opc & MO_BSWAP) == 0); 1610139c1837SPaolo Bonzini 1611139c1837SPaolo Bonzini switch (opc & (MO_SSIZE)) { 1612139c1837SPaolo Bonzini case MO_8: 1613aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SB, base, val, 0); 1614139c1837SPaolo Bonzini break; 1615139c1837SPaolo Bonzini case MO_16: 1616aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SH, base, val, 0); 1617139c1837SPaolo Bonzini break; 1618139c1837SPaolo Bonzini case MO_32: 1619aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SW, base, val, 0); 1620139c1837SPaolo Bonzini break; 1621139c1837SPaolo Bonzini case MO_64: 1622aeb6326eSRichard Henderson tcg_out_opc_store(s, OPC_SD, base, val, 0); 1623139c1837SPaolo Bonzini break; 1624139c1837SPaolo Bonzini default: 1625139c1837SPaolo Bonzini g_assert_not_reached(); 1626139c1837SPaolo Bonzini } 1627139c1837SPaolo Bonzini} 1628139c1837SPaolo Bonzini 1629f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, 1630f7041977SRichard Henderson MemOpIdx oi, TCGType data_type) 1631139c1837SPaolo Bonzini{ 1632001dddfeSRichard Henderson TCGLabelQemuLdst *ldst; 16332e3a933aSRichard Henderson TCGReg base; 1634139c1837SPaolo Bonzini 1635001dddfeSRichard Henderson ldst = prepare_host_addr(s, &base, addr_reg, oi, false); 1636001dddfeSRichard Henderson tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi)); 1637f7041977SRichard Henderson 1638001dddfeSRichard Henderson if (ldst) { 1639001dddfeSRichard Henderson ldst->type = data_type; 1640001dddfeSRichard Henderson ldst->datalo_reg = data_reg; 1641001dddfeSRichard Henderson ldst->raddr = tcg_splitwx_to_rx(s->code_ptr); 1642a3fb7c99SRichard Henderson } 1643139c1837SPaolo Bonzini} 1644139c1837SPaolo Bonzini 1645793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr; 1646139c1837SPaolo Bonzini 1647b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) 1648b55a8d9dSRichard Henderson{ 1649b55a8d9dSRichard Henderson /* Reuse the zeroing that exists for goto_ptr. */ 1650b55a8d9dSRichard Henderson if (a0 == 0) { 1651b55a8d9dSRichard Henderson tcg_out_call_int(s, tcg_code_gen_epilogue, true); 1652b55a8d9dSRichard Henderson } else { 1653b55a8d9dSRichard Henderson tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); 1654b55a8d9dSRichard Henderson tcg_out_call_int(s, tb_ret_addr, true); 1655b55a8d9dSRichard Henderson } 1656b55a8d9dSRichard Henderson} 1657b55a8d9dSRichard Henderson 1658cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which) 1659cf7d6b8eSRichard Henderson{ 1660493c9b19SRichard Henderson /* Direct branch will be patched by tb_target_set_jmp_target. */ 1661493c9b19SRichard Henderson set_jmp_insn_offset(s, which); 1662493c9b19SRichard Henderson tcg_out32(s, OPC_JAL); 1663493c9b19SRichard Henderson 1664493c9b19SRichard Henderson /* When branch is out of range, fall through to indirect. */ 1665cf7d6b8eSRichard Henderson tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, 1666cf7d6b8eSRichard Henderson get_jmp_target_addr(s, which)); 1667cf7d6b8eSRichard Henderson tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); 1668cf7d6b8eSRichard Henderson set_jmp_reset_offset(s, which); 1669cf7d6b8eSRichard Henderson} 1670cf7d6b8eSRichard Henderson 167190c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n, 167290c0fee3SRichard Henderson uintptr_t jmp_rx, uintptr_t jmp_rw) 167390c0fee3SRichard Henderson{ 1674493c9b19SRichard Henderson uintptr_t addr = tb->jmp_target_addr[n]; 1675493c9b19SRichard Henderson ptrdiff_t offset = addr - jmp_rx; 1676493c9b19SRichard Henderson tcg_insn_unit insn; 1677493c9b19SRichard Henderson 1678493c9b19SRichard Henderson /* Either directly branch, or fall through to indirect branch. */ 1679493c9b19SRichard Henderson if (offset == sextreg(offset, 0, 20)) { 1680493c9b19SRichard Henderson insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset); 1681493c9b19SRichard Henderson } else { 1682493c9b19SRichard Henderson insn = OPC_NOP; 1683493c9b19SRichard Henderson } 1684493c9b19SRichard Henderson qatomic_set((uint32_t *)jmp_rw, insn); 1685493c9b19SRichard Henderson flush_idcache_range(jmp_rx, jmp_rw, 4); 168690c0fee3SRichard Henderson} 168790c0fee3SRichard Henderson 1688139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc, 16895e8892dbSMiroslav Rezanina const TCGArg args[TCG_MAX_OP_ARGS], 16905e8892dbSMiroslav Rezanina const int const_args[TCG_MAX_OP_ARGS]) 1691139c1837SPaolo Bonzini{ 1692139c1837SPaolo Bonzini TCGArg a0 = args[0]; 1693139c1837SPaolo Bonzini TCGArg a1 = args[1]; 1694139c1837SPaolo Bonzini TCGArg a2 = args[2]; 1695139c1837SPaolo Bonzini int c2 = const_args[2]; 1696139c1837SPaolo Bonzini 1697139c1837SPaolo Bonzini switch (opc) { 1698139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 1699139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0); 1700139c1837SPaolo Bonzini break; 1701139c1837SPaolo Bonzini 1702139c1837SPaolo Bonzini case INDEX_op_br: 1703139c1837SPaolo Bonzini tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0); 1704139c1837SPaolo Bonzini tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0); 1705139c1837SPaolo Bonzini break; 1706139c1837SPaolo Bonzini 1707139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 1708139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 1709139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LBU, a0, a1, a2); 1710139c1837SPaolo Bonzini break; 1711139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 1712139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 1713139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LB, a0, a1, a2); 1714139c1837SPaolo Bonzini break; 1715139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 1716139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 1717139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LHU, a0, a1, a2); 1718139c1837SPaolo Bonzini break; 1719139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 1720139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 1721139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LH, a0, a1, a2); 1722139c1837SPaolo Bonzini break; 1723139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 1724139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LWU, a0, a1, a2); 1725139c1837SPaolo Bonzini break; 1726139c1837SPaolo Bonzini case INDEX_op_ld_i32: 1727139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 1728139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LW, a0, a1, a2); 1729139c1837SPaolo Bonzini break; 1730139c1837SPaolo Bonzini case INDEX_op_ld_i64: 1731139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_LD, a0, a1, a2); 1732139c1837SPaolo Bonzini break; 1733139c1837SPaolo Bonzini 1734139c1837SPaolo Bonzini case INDEX_op_st8_i32: 1735139c1837SPaolo Bonzini case INDEX_op_st8_i64: 1736139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SB, a0, a1, a2); 1737139c1837SPaolo Bonzini break; 1738139c1837SPaolo Bonzini case INDEX_op_st16_i32: 1739139c1837SPaolo Bonzini case INDEX_op_st16_i64: 1740139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SH, a0, a1, a2); 1741139c1837SPaolo Bonzini break; 1742139c1837SPaolo Bonzini case INDEX_op_st_i32: 1743139c1837SPaolo Bonzini case INDEX_op_st32_i64: 1744139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SW, a0, a1, a2); 1745139c1837SPaolo Bonzini break; 1746139c1837SPaolo Bonzini case INDEX_op_st_i64: 1747139c1837SPaolo Bonzini tcg_out_ldst(s, OPC_SD, a0, a1, a2); 1748139c1837SPaolo Bonzini break; 1749139c1837SPaolo Bonzini 1750139c1837SPaolo Bonzini case INDEX_op_add_i32: 1751139c1837SPaolo Bonzini if (c2) { 1752139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2); 1753139c1837SPaolo Bonzini } else { 1754139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2); 1755139c1837SPaolo Bonzini } 1756139c1837SPaolo Bonzini break; 1757139c1837SPaolo Bonzini case INDEX_op_add_i64: 1758139c1837SPaolo Bonzini if (c2) { 1759139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2); 1760139c1837SPaolo Bonzini } else { 1761139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2); 1762139c1837SPaolo Bonzini } 1763139c1837SPaolo Bonzini break; 1764139c1837SPaolo Bonzini 1765139c1837SPaolo Bonzini case INDEX_op_sub_i32: 1766139c1837SPaolo Bonzini if (c2) { 1767139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2); 1768139c1837SPaolo Bonzini } else { 1769139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2); 1770139c1837SPaolo Bonzini } 1771139c1837SPaolo Bonzini break; 1772139c1837SPaolo Bonzini case INDEX_op_sub_i64: 1773139c1837SPaolo Bonzini if (c2) { 1774139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2); 1775139c1837SPaolo Bonzini } else { 1776139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2); 1777139c1837SPaolo Bonzini } 1778139c1837SPaolo Bonzini break; 1779139c1837SPaolo Bonzini 1780139c1837SPaolo Bonzini case INDEX_op_and_i32: 1781139c1837SPaolo Bonzini case INDEX_op_and_i64: 1782139c1837SPaolo Bonzini if (c2) { 1783139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2); 1784139c1837SPaolo Bonzini } else { 1785139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_AND, a0, a1, a2); 1786139c1837SPaolo Bonzini } 1787139c1837SPaolo Bonzini break; 1788139c1837SPaolo Bonzini 1789139c1837SPaolo Bonzini case INDEX_op_or_i32: 1790139c1837SPaolo Bonzini case INDEX_op_or_i64: 1791139c1837SPaolo Bonzini if (c2) { 1792139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2); 1793139c1837SPaolo Bonzini } else { 1794139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_OR, a0, a1, a2); 1795139c1837SPaolo Bonzini } 1796139c1837SPaolo Bonzini break; 1797139c1837SPaolo Bonzini 1798139c1837SPaolo Bonzini case INDEX_op_xor_i32: 1799139c1837SPaolo Bonzini case INDEX_op_xor_i64: 1800139c1837SPaolo Bonzini if (c2) { 1801139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2); 1802139c1837SPaolo Bonzini } else { 1803139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2); 1804139c1837SPaolo Bonzini } 1805139c1837SPaolo Bonzini break; 1806139c1837SPaolo Bonzini 180799f4ec6eSRichard Henderson case INDEX_op_andc_i32: 180899f4ec6eSRichard Henderson case INDEX_op_andc_i64: 180999f4ec6eSRichard Henderson if (c2) { 181099f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2); 181199f4ec6eSRichard Henderson } else { 181299f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2); 181399f4ec6eSRichard Henderson } 181499f4ec6eSRichard Henderson break; 181599f4ec6eSRichard Henderson case INDEX_op_orc_i32: 181699f4ec6eSRichard Henderson case INDEX_op_orc_i64: 181799f4ec6eSRichard Henderson if (c2) { 181899f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2); 181999f4ec6eSRichard Henderson } else { 182099f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2); 182199f4ec6eSRichard Henderson } 182299f4ec6eSRichard Henderson break; 182399f4ec6eSRichard Henderson case INDEX_op_eqv_i32: 182499f4ec6eSRichard Henderson case INDEX_op_eqv_i64: 182599f4ec6eSRichard Henderson if (c2) { 182699f4ec6eSRichard Henderson tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2); 182799f4ec6eSRichard Henderson } else { 182899f4ec6eSRichard Henderson tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2); 182999f4ec6eSRichard Henderson } 183099f4ec6eSRichard Henderson break; 183199f4ec6eSRichard Henderson 1832139c1837SPaolo Bonzini case INDEX_op_not_i32: 1833139c1837SPaolo Bonzini case INDEX_op_not_i64: 1834139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1); 1835139c1837SPaolo Bonzini break; 1836139c1837SPaolo Bonzini 1837139c1837SPaolo Bonzini case INDEX_op_neg_i32: 1838139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1); 1839139c1837SPaolo Bonzini break; 1840139c1837SPaolo Bonzini case INDEX_op_neg_i64: 1841139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1); 1842139c1837SPaolo Bonzini break; 1843139c1837SPaolo Bonzini 1844139c1837SPaolo Bonzini case INDEX_op_mul_i32: 1845139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2); 1846139c1837SPaolo Bonzini break; 1847139c1837SPaolo Bonzini case INDEX_op_mul_i64: 1848139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2); 1849139c1837SPaolo Bonzini break; 1850139c1837SPaolo Bonzini 1851139c1837SPaolo Bonzini case INDEX_op_div_i32: 1852139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2); 1853139c1837SPaolo Bonzini break; 1854139c1837SPaolo Bonzini case INDEX_op_div_i64: 1855139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2); 1856139c1837SPaolo Bonzini break; 1857139c1837SPaolo Bonzini 1858139c1837SPaolo Bonzini case INDEX_op_divu_i32: 1859139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2); 1860139c1837SPaolo Bonzini break; 1861139c1837SPaolo Bonzini case INDEX_op_divu_i64: 1862139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2); 1863139c1837SPaolo Bonzini break; 1864139c1837SPaolo Bonzini 1865139c1837SPaolo Bonzini case INDEX_op_rem_i32: 1866139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2); 1867139c1837SPaolo Bonzini break; 1868139c1837SPaolo Bonzini case INDEX_op_rem_i64: 1869139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REM, a0, a1, a2); 1870139c1837SPaolo Bonzini break; 1871139c1837SPaolo Bonzini 1872139c1837SPaolo Bonzini case INDEX_op_remu_i32: 1873139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2); 1874139c1837SPaolo Bonzini break; 1875139c1837SPaolo Bonzini case INDEX_op_remu_i64: 1876139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2); 1877139c1837SPaolo Bonzini break; 1878139c1837SPaolo Bonzini 1879139c1837SPaolo Bonzini case INDEX_op_shl_i32: 1880139c1837SPaolo Bonzini if (c2) { 1881d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f); 1882139c1837SPaolo Bonzini } else { 1883139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2); 1884139c1837SPaolo Bonzini } 1885139c1837SPaolo Bonzini break; 1886139c1837SPaolo Bonzini case INDEX_op_shl_i64: 1887139c1837SPaolo Bonzini if (c2) { 1888d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f); 1889139c1837SPaolo Bonzini } else { 1890139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2); 1891139c1837SPaolo Bonzini } 1892139c1837SPaolo Bonzini break; 1893139c1837SPaolo Bonzini 1894139c1837SPaolo Bonzini case INDEX_op_shr_i32: 1895139c1837SPaolo Bonzini if (c2) { 1896d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f); 1897139c1837SPaolo Bonzini } else { 1898139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2); 1899139c1837SPaolo Bonzini } 1900139c1837SPaolo Bonzini break; 1901139c1837SPaolo Bonzini case INDEX_op_shr_i64: 1902139c1837SPaolo Bonzini if (c2) { 1903d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f); 1904139c1837SPaolo Bonzini } else { 1905139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2); 1906139c1837SPaolo Bonzini } 1907139c1837SPaolo Bonzini break; 1908139c1837SPaolo Bonzini 1909139c1837SPaolo Bonzini case INDEX_op_sar_i32: 1910139c1837SPaolo Bonzini if (c2) { 1911d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f); 1912139c1837SPaolo Bonzini } else { 1913139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2); 1914139c1837SPaolo Bonzini } 1915139c1837SPaolo Bonzini break; 1916139c1837SPaolo Bonzini case INDEX_op_sar_i64: 1917139c1837SPaolo Bonzini if (c2) { 1918d2f3066eSZihao Yu tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f); 1919139c1837SPaolo Bonzini } else { 1920139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2); 1921139c1837SPaolo Bonzini } 1922139c1837SPaolo Bonzini break; 1923139c1837SPaolo Bonzini 192419d016adSRichard Henderson case INDEX_op_rotl_i32: 192519d016adSRichard Henderson if (c2) { 192619d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f); 192719d016adSRichard Henderson } else { 192819d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2); 192919d016adSRichard Henderson } 193019d016adSRichard Henderson break; 193119d016adSRichard Henderson case INDEX_op_rotl_i64: 193219d016adSRichard Henderson if (c2) { 193319d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f); 193419d016adSRichard Henderson } else { 193519d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2); 193619d016adSRichard Henderson } 193719d016adSRichard Henderson break; 193819d016adSRichard Henderson 193919d016adSRichard Henderson case INDEX_op_rotr_i32: 194019d016adSRichard Henderson if (c2) { 194119d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f); 194219d016adSRichard Henderson } else { 194319d016adSRichard Henderson tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2); 194419d016adSRichard Henderson } 194519d016adSRichard Henderson break; 194619d016adSRichard Henderson case INDEX_op_rotr_i64: 194719d016adSRichard Henderson if (c2) { 194819d016adSRichard Henderson tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f); 194919d016adSRichard Henderson } else { 195019d016adSRichard Henderson tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2); 195119d016adSRichard Henderson } 195219d016adSRichard Henderson break; 195319d016adSRichard Henderson 19547b4d5274SRichard Henderson case INDEX_op_bswap64_i64: 19557b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 19567b4d5274SRichard Henderson break; 19577b4d5274SRichard Henderson case INDEX_op_bswap32_i32: 19587b4d5274SRichard Henderson a2 = 0; 19597b4d5274SRichard Henderson /* fall through */ 19607b4d5274SRichard Henderson case INDEX_op_bswap32_i64: 19617b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 19627b4d5274SRichard Henderson if (a2 & TCG_BSWAP_OZ) { 19637b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32); 19647b4d5274SRichard Henderson } else { 19657b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32); 19667b4d5274SRichard Henderson } 19677b4d5274SRichard Henderson break; 19687b4d5274SRichard Henderson case INDEX_op_bswap16_i64: 19697b4d5274SRichard Henderson case INDEX_op_bswap16_i32: 19707b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); 19717b4d5274SRichard Henderson if (a2 & TCG_BSWAP_OZ) { 19727b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48); 19737b4d5274SRichard Henderson } else { 19747b4d5274SRichard Henderson tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48); 19757b4d5274SRichard Henderson } 19767b4d5274SRichard Henderson break; 19777b4d5274SRichard Henderson 19780956ecdaSRichard Henderson case INDEX_op_ctpop_i32: 19790956ecdaSRichard Henderson tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0); 19800956ecdaSRichard Henderson break; 19810956ecdaSRichard Henderson case INDEX_op_ctpop_i64: 19820956ecdaSRichard Henderson tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0); 19830956ecdaSRichard Henderson break; 19840956ecdaSRichard Henderson 1985a30498fcSRichard Henderson case INDEX_op_clz_i32: 1986a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2); 1987a30498fcSRichard Henderson break; 1988a30498fcSRichard Henderson case INDEX_op_clz_i64: 1989a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2); 1990a30498fcSRichard Henderson break; 1991a30498fcSRichard Henderson case INDEX_op_ctz_i32: 1992a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2); 1993a30498fcSRichard Henderson break; 1994a30498fcSRichard Henderson case INDEX_op_ctz_i64: 1995a30498fcSRichard Henderson tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2); 1996a30498fcSRichard Henderson break; 1997a30498fcSRichard Henderson 1998139c1837SPaolo Bonzini case INDEX_op_add2_i32: 1999139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2000139c1837SPaolo Bonzini const_args[4], const_args[5], false, true); 2001139c1837SPaolo Bonzini break; 2002139c1837SPaolo Bonzini case INDEX_op_add2_i64: 2003139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2004139c1837SPaolo Bonzini const_args[4], const_args[5], false, false); 2005139c1837SPaolo Bonzini break; 2006139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 2007139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2008139c1837SPaolo Bonzini const_args[4], const_args[5], true, true); 2009139c1837SPaolo Bonzini break; 2010139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 2011139c1837SPaolo Bonzini tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], 2012139c1837SPaolo Bonzini const_args[4], const_args[5], true, false); 2013139c1837SPaolo Bonzini break; 2014139c1837SPaolo Bonzini 2015139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 2016139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 2017139c1837SPaolo Bonzini tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); 2018139c1837SPaolo Bonzini break; 2019139c1837SPaolo Bonzini 2020139c1837SPaolo Bonzini case INDEX_op_setcond_i32: 2021139c1837SPaolo Bonzini case INDEX_op_setcond_i64: 2022f6453695SRichard Henderson tcg_out_setcond(s, args[3], a0, a1, a2, c2); 2023139c1837SPaolo Bonzini break; 2024139c1837SPaolo Bonzini 202541e4c0a9SRichard Henderson case INDEX_op_negsetcond_i32: 202641e4c0a9SRichard Henderson case INDEX_op_negsetcond_i64: 202741e4c0a9SRichard Henderson tcg_out_negsetcond(s, args[3], a0, a1, a2, c2); 202841e4c0a9SRichard Henderson break; 202941e4c0a9SRichard Henderson 2030a18d783eSRichard Henderson case INDEX_op_movcond_i32: 2031a18d783eSRichard Henderson case INDEX_op_movcond_i64: 2032a18d783eSRichard Henderson tcg_out_movcond(s, args[5], a0, a1, a2, c2, 2033a18d783eSRichard Henderson args[3], const_args[3], args[4], const_args[4]); 2034a18d783eSRichard Henderson break; 2035a18d783eSRichard Henderson 2036fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 2037fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 2038f7041977SRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); 2039139c1837SPaolo Bonzini break; 2040fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 2041fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 2042f7041977SRichard Henderson tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64); 2043139c1837SPaolo Bonzini break; 2044fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 2045fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 2046f7041977SRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32); 2047139c1837SPaolo Bonzini break; 2048fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 2049fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 2050f7041977SRichard Henderson tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64); 2051139c1837SPaolo Bonzini break; 2052139c1837SPaolo Bonzini 2053139c1837SPaolo Bonzini case INDEX_op_extrh_i64_i32: 2054139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32); 2055139c1837SPaolo Bonzini break; 2056139c1837SPaolo Bonzini 2057139c1837SPaolo Bonzini case INDEX_op_mulsh_i32: 2058139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 2059139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2); 2060139c1837SPaolo Bonzini break; 2061139c1837SPaolo Bonzini 2062139c1837SPaolo Bonzini case INDEX_op_muluh_i32: 2063139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 2064139c1837SPaolo Bonzini tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2); 2065139c1837SPaolo Bonzini break; 2066139c1837SPaolo Bonzini 2067139c1837SPaolo Bonzini case INDEX_op_mb: 2068139c1837SPaolo Bonzini tcg_out_mb(s, a0); 2069139c1837SPaolo Bonzini break; 2070139c1837SPaolo Bonzini 2071139c1837SPaolo Bonzini case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ 2072139c1837SPaolo Bonzini case INDEX_op_mov_i64: 2073139c1837SPaolo Bonzini case INDEX_op_call: /* Always emitted via tcg_out_call. */ 2074b55a8d9dSRichard Henderson case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ 2075cf7d6b8eSRichard Henderson case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ 2076678155b2SRichard Henderson case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */ 2077678155b2SRichard Henderson case INDEX_op_ext8s_i64: 2078d0e66c89SRichard Henderson case INDEX_op_ext8u_i32: 2079d0e66c89SRichard Henderson case INDEX_op_ext8u_i64: 2080753e42eaSRichard Henderson case INDEX_op_ext16s_i32: 2081753e42eaSRichard Henderson case INDEX_op_ext16s_i64: 2082379afdffSRichard Henderson case INDEX_op_ext16u_i32: 2083379afdffSRichard Henderson case INDEX_op_ext16u_i64: 208452bf3398SRichard Henderson case INDEX_op_ext32s_i64: 20859ecf5f61SRichard Henderson case INDEX_op_ext32u_i64: 20869c6aa274SRichard Henderson case INDEX_op_ext_i32_i64: 2087b9bfe000SRichard Henderson case INDEX_op_extu_i32_i64: 2088b8b94ac6SRichard Henderson case INDEX_op_extrl_i64_i32: 2089139c1837SPaolo Bonzini default: 2090139c1837SPaolo Bonzini g_assert_not_reached(); 2091139c1837SPaolo Bonzini } 2092139c1837SPaolo Bonzini} 2093139c1837SPaolo Bonzini 2094*f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, 2095*f63e7089SHuang Shiyuan unsigned vecl, unsigned vece, 2096*f63e7089SHuang Shiyuan const TCGArg args[TCG_MAX_OP_ARGS], 2097*f63e7089SHuang Shiyuan const int const_args[TCG_MAX_OP_ARGS]) 2098*f63e7089SHuang Shiyuan{ 2099*f63e7089SHuang Shiyuan TCGType type = vecl + TCG_TYPE_V64; 2100*f63e7089SHuang Shiyuan TCGArg a0, a1, a2; 2101*f63e7089SHuang Shiyuan 2102*f63e7089SHuang Shiyuan a0 = args[0]; 2103*f63e7089SHuang Shiyuan a1 = args[1]; 2104*f63e7089SHuang Shiyuan a2 = args[2]; 2105*f63e7089SHuang Shiyuan 2106*f63e7089SHuang Shiyuan switch (opc) { 2107*f63e7089SHuang Shiyuan case INDEX_op_ld_vec: 2108*f63e7089SHuang Shiyuan tcg_out_ld(s, type, a0, a1, a2); 2109*f63e7089SHuang Shiyuan break; 2110*f63e7089SHuang Shiyuan case INDEX_op_st_vec: 2111*f63e7089SHuang Shiyuan tcg_out_st(s, type, a0, a1, a2); 2112*f63e7089SHuang Shiyuan break; 2113*f63e7089SHuang Shiyuan case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */ 2114*f63e7089SHuang Shiyuan case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */ 2115*f63e7089SHuang Shiyuan default: 2116*f63e7089SHuang Shiyuan g_assert_not_reached(); 2117*f63e7089SHuang Shiyuan } 2118*f63e7089SHuang Shiyuan} 2119*f63e7089SHuang Shiyuan 2120*f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece, 2121*f63e7089SHuang Shiyuan TCGArg a0, ...) 2122*f63e7089SHuang Shiyuan{ 2123*f63e7089SHuang Shiyuan g_assert_not_reached(); 2124*f63e7089SHuang Shiyuan} 2125*f63e7089SHuang Shiyuan 2126*f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece) 2127*f63e7089SHuang Shiyuan{ 2128*f63e7089SHuang Shiyuan switch (opc) { 2129*f63e7089SHuang Shiyuan default: 2130*f63e7089SHuang Shiyuan return 0; 2131*f63e7089SHuang Shiyuan } 2132*f63e7089SHuang Shiyuan} 2133*f63e7089SHuang Shiyuan 2134665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) 2135139c1837SPaolo Bonzini{ 2136139c1837SPaolo Bonzini switch (op) { 2137139c1837SPaolo Bonzini case INDEX_op_goto_ptr: 2138665be288SRichard Henderson return C_O0_I1(r); 2139139c1837SPaolo Bonzini 2140139c1837SPaolo Bonzini case INDEX_op_ld8u_i32: 2141139c1837SPaolo Bonzini case INDEX_op_ld8s_i32: 2142139c1837SPaolo Bonzini case INDEX_op_ld16u_i32: 2143139c1837SPaolo Bonzini case INDEX_op_ld16s_i32: 2144139c1837SPaolo Bonzini case INDEX_op_ld_i32: 2145139c1837SPaolo Bonzini case INDEX_op_not_i32: 2146139c1837SPaolo Bonzini case INDEX_op_neg_i32: 2147139c1837SPaolo Bonzini case INDEX_op_ld8u_i64: 2148139c1837SPaolo Bonzini case INDEX_op_ld8s_i64: 2149139c1837SPaolo Bonzini case INDEX_op_ld16u_i64: 2150139c1837SPaolo Bonzini case INDEX_op_ld16s_i64: 2151139c1837SPaolo Bonzini case INDEX_op_ld32s_i64: 2152139c1837SPaolo Bonzini case INDEX_op_ld32u_i64: 2153139c1837SPaolo Bonzini case INDEX_op_ld_i64: 2154139c1837SPaolo Bonzini case INDEX_op_not_i64: 2155139c1837SPaolo Bonzini case INDEX_op_neg_i64: 2156139c1837SPaolo Bonzini case INDEX_op_ext8u_i32: 2157139c1837SPaolo Bonzini case INDEX_op_ext8u_i64: 2158139c1837SPaolo Bonzini case INDEX_op_ext16u_i32: 2159139c1837SPaolo Bonzini case INDEX_op_ext16u_i64: 2160139c1837SPaolo Bonzini case INDEX_op_ext32u_i64: 2161139c1837SPaolo Bonzini case INDEX_op_extu_i32_i64: 2162139c1837SPaolo Bonzini case INDEX_op_ext8s_i32: 2163139c1837SPaolo Bonzini case INDEX_op_ext8s_i64: 2164139c1837SPaolo Bonzini case INDEX_op_ext16s_i32: 2165139c1837SPaolo Bonzini case INDEX_op_ext16s_i64: 2166139c1837SPaolo Bonzini case INDEX_op_ext32s_i64: 2167139c1837SPaolo Bonzini case INDEX_op_extrl_i64_i32: 2168139c1837SPaolo Bonzini case INDEX_op_extrh_i64_i32: 2169139c1837SPaolo Bonzini case INDEX_op_ext_i32_i64: 21707b4d5274SRichard Henderson case INDEX_op_bswap16_i32: 21717b4d5274SRichard Henderson case INDEX_op_bswap32_i32: 21727b4d5274SRichard Henderson case INDEX_op_bswap16_i64: 21737b4d5274SRichard Henderson case INDEX_op_bswap32_i64: 21747b4d5274SRichard Henderson case INDEX_op_bswap64_i64: 21750956ecdaSRichard Henderson case INDEX_op_ctpop_i32: 21760956ecdaSRichard Henderson case INDEX_op_ctpop_i64: 2177665be288SRichard Henderson return C_O1_I1(r, r); 2178139c1837SPaolo Bonzini 2179139c1837SPaolo Bonzini case INDEX_op_st8_i32: 2180139c1837SPaolo Bonzini case INDEX_op_st16_i32: 2181139c1837SPaolo Bonzini case INDEX_op_st_i32: 2182139c1837SPaolo Bonzini case INDEX_op_st8_i64: 2183139c1837SPaolo Bonzini case INDEX_op_st16_i64: 2184139c1837SPaolo Bonzini case INDEX_op_st32_i64: 2185139c1837SPaolo Bonzini case INDEX_op_st_i64: 2186665be288SRichard Henderson return C_O0_I2(rZ, r); 2187139c1837SPaolo Bonzini 2188139c1837SPaolo Bonzini case INDEX_op_add_i32: 2189139c1837SPaolo Bonzini case INDEX_op_and_i32: 2190139c1837SPaolo Bonzini case INDEX_op_or_i32: 2191139c1837SPaolo Bonzini case INDEX_op_xor_i32: 2192139c1837SPaolo Bonzini case INDEX_op_add_i64: 2193139c1837SPaolo Bonzini case INDEX_op_and_i64: 2194139c1837SPaolo Bonzini case INDEX_op_or_i64: 2195139c1837SPaolo Bonzini case INDEX_op_xor_i64: 2196f6453695SRichard Henderson case INDEX_op_setcond_i32: 2197f6453695SRichard Henderson case INDEX_op_setcond_i64: 219841e4c0a9SRichard Henderson case INDEX_op_negsetcond_i32: 219941e4c0a9SRichard Henderson case INDEX_op_negsetcond_i64: 2200665be288SRichard Henderson return C_O1_I2(r, r, rI); 2201139c1837SPaolo Bonzini 220299f4ec6eSRichard Henderson case INDEX_op_andc_i32: 220399f4ec6eSRichard Henderson case INDEX_op_andc_i64: 220499f4ec6eSRichard Henderson case INDEX_op_orc_i32: 220599f4ec6eSRichard Henderson case INDEX_op_orc_i64: 220699f4ec6eSRichard Henderson case INDEX_op_eqv_i32: 220799f4ec6eSRichard Henderson case INDEX_op_eqv_i64: 220899f4ec6eSRichard Henderson return C_O1_I2(r, r, rJ); 220999f4ec6eSRichard Henderson 2210139c1837SPaolo Bonzini case INDEX_op_sub_i32: 2211139c1837SPaolo Bonzini case INDEX_op_sub_i64: 2212665be288SRichard Henderson return C_O1_I2(r, rZ, rN); 2213139c1837SPaolo Bonzini 2214139c1837SPaolo Bonzini case INDEX_op_mul_i32: 2215139c1837SPaolo Bonzini case INDEX_op_mulsh_i32: 2216139c1837SPaolo Bonzini case INDEX_op_muluh_i32: 2217139c1837SPaolo Bonzini case INDEX_op_div_i32: 2218139c1837SPaolo Bonzini case INDEX_op_divu_i32: 2219139c1837SPaolo Bonzini case INDEX_op_rem_i32: 2220139c1837SPaolo Bonzini case INDEX_op_remu_i32: 2221139c1837SPaolo Bonzini case INDEX_op_mul_i64: 2222139c1837SPaolo Bonzini case INDEX_op_mulsh_i64: 2223139c1837SPaolo Bonzini case INDEX_op_muluh_i64: 2224139c1837SPaolo Bonzini case INDEX_op_div_i64: 2225139c1837SPaolo Bonzini case INDEX_op_divu_i64: 2226139c1837SPaolo Bonzini case INDEX_op_rem_i64: 2227139c1837SPaolo Bonzini case INDEX_op_remu_i64: 2228665be288SRichard Henderson return C_O1_I2(r, rZ, rZ); 2229139c1837SPaolo Bonzini 2230139c1837SPaolo Bonzini case INDEX_op_shl_i32: 2231139c1837SPaolo Bonzini case INDEX_op_shr_i32: 2232139c1837SPaolo Bonzini case INDEX_op_sar_i32: 223319d016adSRichard Henderson case INDEX_op_rotl_i32: 223419d016adSRichard Henderson case INDEX_op_rotr_i32: 2235139c1837SPaolo Bonzini case INDEX_op_shl_i64: 2236139c1837SPaolo Bonzini case INDEX_op_shr_i64: 2237139c1837SPaolo Bonzini case INDEX_op_sar_i64: 223819d016adSRichard Henderson case INDEX_op_rotl_i64: 223919d016adSRichard Henderson case INDEX_op_rotr_i64: 2240665be288SRichard Henderson return C_O1_I2(r, r, ri); 2241139c1837SPaolo Bonzini 2242a30498fcSRichard Henderson case INDEX_op_clz_i32: 2243a30498fcSRichard Henderson case INDEX_op_clz_i64: 2244a30498fcSRichard Henderson case INDEX_op_ctz_i32: 2245a30498fcSRichard Henderson case INDEX_op_ctz_i64: 2246a30498fcSRichard Henderson return C_N1_I2(r, r, rM); 2247a30498fcSRichard Henderson 2248139c1837SPaolo Bonzini case INDEX_op_brcond_i32: 2249139c1837SPaolo Bonzini case INDEX_op_brcond_i64: 2250665be288SRichard Henderson return C_O0_I2(rZ, rZ); 2251139c1837SPaolo Bonzini 2252a18d783eSRichard Henderson case INDEX_op_movcond_i32: 2253a18d783eSRichard Henderson case INDEX_op_movcond_i64: 2254a18d783eSRichard Henderson return C_O1_I4(r, r, rI, rM, rM); 2255a18d783eSRichard Henderson 2256139c1837SPaolo Bonzini case INDEX_op_add2_i32: 2257139c1837SPaolo Bonzini case INDEX_op_add2_i64: 2258139c1837SPaolo Bonzini case INDEX_op_sub2_i32: 2259139c1837SPaolo Bonzini case INDEX_op_sub2_i64: 2260665be288SRichard Henderson return C_O2_I4(r, r, rZ, rZ, rM, rM); 2261139c1837SPaolo Bonzini 2262fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32: 2263fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32: 2264fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64: 2265fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64: 2266f0f43534SRichard Henderson return C_O1_I1(r, r); 2267fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32: 2268fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32: 2269fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64: 2270fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64: 2271f0f43534SRichard Henderson return C_O0_I2(rZ, r); 2272139c1837SPaolo Bonzini 2273*f63e7089SHuang Shiyuan case INDEX_op_st_vec: 2274*f63e7089SHuang Shiyuan return C_O0_I2(v, r); 2275*f63e7089SHuang Shiyuan case INDEX_op_ld_vec: 2276*f63e7089SHuang Shiyuan return C_O1_I1(v, r); 2277139c1837SPaolo Bonzini default: 2278665be288SRichard Henderson g_assert_not_reached(); 2279139c1837SPaolo Bonzini } 2280139c1837SPaolo Bonzini} 2281139c1837SPaolo Bonzini 2282139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = { 2283139c1837SPaolo Bonzini TCG_REG_S0, /* used for the global env (TCG_AREG0) */ 2284139c1837SPaolo Bonzini TCG_REG_S1, 2285139c1837SPaolo Bonzini TCG_REG_S2, 2286139c1837SPaolo Bonzini TCG_REG_S3, 2287139c1837SPaolo Bonzini TCG_REG_S4, 2288139c1837SPaolo Bonzini TCG_REG_S5, 2289139c1837SPaolo Bonzini TCG_REG_S6, 2290139c1837SPaolo Bonzini TCG_REG_S7, 2291139c1837SPaolo Bonzini TCG_REG_S8, 2292139c1837SPaolo Bonzini TCG_REG_S9, 2293139c1837SPaolo Bonzini TCG_REG_S10, 2294139c1837SPaolo Bonzini TCG_REG_S11, 2295139c1837SPaolo Bonzini TCG_REG_RA, /* should be last for ABI compliance */ 2296139c1837SPaolo Bonzini}; 2297139c1837SPaolo Bonzini 2298139c1837SPaolo Bonzini/* Stack frame parameters. */ 2299139c1837SPaolo Bonzini#define REG_SIZE (TCG_TARGET_REG_BITS / 8) 2300139c1837SPaolo Bonzini#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) 2301139c1837SPaolo Bonzini#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) 2302139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ 2303139c1837SPaolo Bonzini + TCG_TARGET_STACK_ALIGN - 1) \ 2304139c1837SPaolo Bonzini & -TCG_TARGET_STACK_ALIGN) 2305139c1837SPaolo Bonzini#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) 2306139c1837SPaolo Bonzini 2307139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation. */ 2308139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); 2309139c1837SPaolo Bonzini 2310139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */ 2311139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s) 2312139c1837SPaolo Bonzini{ 2313139c1837SPaolo Bonzini int i; 2314139c1837SPaolo Bonzini 2315139c1837SPaolo Bonzini tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); 2316139c1837SPaolo Bonzini 2317139c1837SPaolo Bonzini /* TB prologue */ 2318139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); 2319139c1837SPaolo Bonzini for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 2320139c1837SPaolo Bonzini tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 2321139c1837SPaolo Bonzini TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 2322139c1837SPaolo Bonzini } 2323139c1837SPaolo Bonzini 23244944d359SRichard Henderson if (!tcg_use_softmmu && guest_base) { 2325139c1837SPaolo Bonzini tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); 2326139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); 2327cf0ed30eSRichard Henderson } 2328139c1837SPaolo Bonzini 2329139c1837SPaolo Bonzini /* Call generated code */ 2330139c1837SPaolo Bonzini tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); 2331139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); 2332139c1837SPaolo Bonzini 2333139c1837SPaolo Bonzini /* Return path for goto_ptr. Set return value to 0 */ 2334c8bc1168SRichard Henderson tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); 2335139c1837SPaolo Bonzini tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); 2336139c1837SPaolo Bonzini 2337139c1837SPaolo Bonzini /* TB epilogue */ 2338793f7381SRichard Henderson tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); 2339139c1837SPaolo Bonzini for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { 2340139c1837SPaolo Bonzini tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], 2341139c1837SPaolo Bonzini TCG_REG_SP, SAVE_OFS + i * REG_SIZE); 2342139c1837SPaolo Bonzini } 2343139c1837SPaolo Bonzini 2344139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); 2345139c1837SPaolo Bonzini tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0); 2346139c1837SPaolo Bonzini} 2347139c1837SPaolo Bonzini 23489358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s) 23499358fbbfSRichard Henderson{ 2350*f63e7089SHuang Shiyuan init_setting_vtype(s); 2351*f63e7089SHuang Shiyuan} 2352*f63e7089SHuang Shiyuan 2353*f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype) 2354*f63e7089SHuang Shiyuan{ 2355*f63e7089SHuang Shiyuan unsigned long tmp; 2356*f63e7089SHuang Shiyuan 2357*f63e7089SHuang Shiyuan /* vsetvl tmp, zero, vtype */ 2358*f63e7089SHuang Shiyuan asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype)); 2359*f63e7089SHuang Shiyuan return tmp != 0; 2360*f63e7089SHuang Shiyuan} 2361*f63e7089SHuang Shiyuan 2362*f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew) 2363*f63e7089SHuang Shiyuan{ 2364*f63e7089SHuang Shiyuan VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew]; 2365*f63e7089SHuang Shiyuan unsigned avl = tcg_type_size(type) >> vsew; 2366*f63e7089SHuang Shiyuan int lmul = type - riscv_lg2_vlenb; 2367*f63e7089SHuang Shiyuan unsigned vtype = encode_vtype(true, true, vsew, lmul & 7); 2368*f63e7089SHuang Shiyuan bool lmul_eq_avl = true; 2369*f63e7089SHuang Shiyuan 2370*f63e7089SHuang Shiyuan /* Guaranteed by Zve64x. */ 2371*f63e7089SHuang Shiyuan assert(lmul < 3); 2372*f63e7089SHuang Shiyuan 2373*f63e7089SHuang Shiyuan /* 2374*f63e7089SHuang Shiyuan * For LMUL < -3, the host vector size is so large that TYPE 2375*f63e7089SHuang Shiyuan * is smaller than the minimum 1/8 fraction. 2376*f63e7089SHuang Shiyuan * 2377*f63e7089SHuang Shiyuan * For other fractional LMUL settings, implementations must 2378*f63e7089SHuang Shiyuan * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive. 2379*f63e7089SHuang Shiyuan * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32, 2380*f63e7089SHuang Shiyuan * but e64 may not be supported. In other words, the hardware only 2381*f63e7089SHuang Shiyuan * guarantees SEW_MIN <= SEW <= LMUL * ELEN. Check. 2382*f63e7089SHuang Shiyuan */ 2383*f63e7089SHuang Shiyuan if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) { 2384*f63e7089SHuang Shiyuan vtype = encode_vtype(true, true, vsew, VLMUL_M1); 2385*f63e7089SHuang Shiyuan lmul_eq_avl = false; 2386*f63e7089SHuang Shiyuan } 2387*f63e7089SHuang Shiyuan 2388*f63e7089SHuang Shiyuan if (avl < 32) { 2389*f63e7089SHuang Shiyuan p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype); 2390*f63e7089SHuang Shiyuan } else if (lmul_eq_avl) { 2391*f63e7089SHuang Shiyuan /* rd != 0 and rs1 == 0 uses vlmax */ 2392*f63e7089SHuang Shiyuan p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype); 2393*f63e7089SHuang Shiyuan } else { 2394*f63e7089SHuang Shiyuan p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl); 2395*f63e7089SHuang Shiyuan p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype); 2396*f63e7089SHuang Shiyuan } 2397*f63e7089SHuang Shiyuan} 2398*f63e7089SHuang Shiyuan 2399*f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void) 2400*f63e7089SHuang Shiyuan{ 2401*f63e7089SHuang Shiyuan /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */ 2402*f63e7089SHuang Shiyuan QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3); 2403*f63e7089SHuang Shiyuan 2404*f63e7089SHuang Shiyuan for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) { 2405*f63e7089SHuang Shiyuan for (MemOp e = MO_8; e <= MO_64; e++) { 2406*f63e7089SHuang Shiyuan probe_frac_lmul_1(t, e); 2407*f63e7089SHuang Shiyuan } 2408*f63e7089SHuang Shiyuan } 24099358fbbfSRichard Henderson} 24109358fbbfSRichard Henderson 2411139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s) 2412139c1837SPaolo Bonzini{ 2413139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff; 2414139c1837SPaolo Bonzini tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff; 2415139c1837SPaolo Bonzini 2416*f63e7089SHuang Shiyuan tcg_target_call_clobber_regs = -1; 2417139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); 2418139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); 2419139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); 2420139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); 2421139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); 2422139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); 2423139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); 2424139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); 2425139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); 2426139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); 2427139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10); 2428139c1837SPaolo Bonzini tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11); 2429139c1837SPaolo Bonzini 2430139c1837SPaolo Bonzini s->reserved_regs = 0; 2431139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); 2432139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); 2433139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); 2434139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); 2435139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); 2436139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); 2437139c1837SPaolo Bonzini tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); 2438*f63e7089SHuang Shiyuan 2439*f63e7089SHuang Shiyuan if (cpuinfo & CPUINFO_ZVE64X) { 2440*f63e7089SHuang Shiyuan switch (riscv_lg2_vlenb) { 2441*f63e7089SHuang Shiyuan case TCG_TYPE_V64: 2442*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2443*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS; 2444*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS; 2445*f63e7089SHuang Shiyuan s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS); 2446*f63e7089SHuang Shiyuan break; 2447*f63e7089SHuang Shiyuan case TCG_TYPE_V128: 2448*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2449*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS; 2450*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS; 2451*f63e7089SHuang Shiyuan s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS); 2452*f63e7089SHuang Shiyuan break; 2453*f63e7089SHuang Shiyuan default: 2454*f63e7089SHuang Shiyuan /* Guaranteed by Zve64x. */ 2455*f63e7089SHuang Shiyuan tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256); 2456*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS; 2457*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS; 2458*f63e7089SHuang Shiyuan tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS; 2459*f63e7089SHuang Shiyuan break; 2460*f63e7089SHuang Shiyuan } 2461*f63e7089SHuang Shiyuan tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0); 2462*f63e7089SHuang Shiyuan probe_frac_lmul(); 2463*f63e7089SHuang Shiyuan } 2464139c1837SPaolo Bonzini} 2465139c1837SPaolo Bonzini 2466139c1837SPaolo Bonzinitypedef struct { 2467139c1837SPaolo Bonzini DebugFrameHeader h; 2468139c1837SPaolo Bonzini uint8_t fde_def_cfa[4]; 2469139c1837SPaolo Bonzini uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; 2470139c1837SPaolo Bonzini} DebugFrame; 2471139c1837SPaolo Bonzini 2472139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV 2473139c1837SPaolo Bonzini 2474139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = { 2475139c1837SPaolo Bonzini .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ 2476139c1837SPaolo Bonzini .h.cie.id = -1, 2477139c1837SPaolo Bonzini .h.cie.version = 1, 2478139c1837SPaolo Bonzini .h.cie.code_align = 1, 2479139c1837SPaolo Bonzini .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ 2480139c1837SPaolo Bonzini .h.cie.return_column = TCG_REG_RA, 2481139c1837SPaolo Bonzini 2482139c1837SPaolo Bonzini /* Total FDE size does not include the "len" member. */ 2483139c1837SPaolo Bonzini .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), 2484139c1837SPaolo Bonzini 2485139c1837SPaolo Bonzini .fde_def_cfa = { 2486139c1837SPaolo Bonzini 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ 2487139c1837SPaolo Bonzini (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ 2488139c1837SPaolo Bonzini (FRAME_SIZE >> 7) 2489139c1837SPaolo Bonzini }, 2490139c1837SPaolo Bonzini .fde_reg_ofs = { 2491139c1837SPaolo Bonzini 0x80 + 9, 12, /* DW_CFA_offset, s1, -96 */ 2492139c1837SPaolo Bonzini 0x80 + 18, 11, /* DW_CFA_offset, s2, -88 */ 2493139c1837SPaolo Bonzini 0x80 + 19, 10, /* DW_CFA_offset, s3, -80 */ 2494139c1837SPaolo Bonzini 0x80 + 20, 9, /* DW_CFA_offset, s4, -72 */ 2495139c1837SPaolo Bonzini 0x80 + 21, 8, /* DW_CFA_offset, s5, -64 */ 2496139c1837SPaolo Bonzini 0x80 + 22, 7, /* DW_CFA_offset, s6, -56 */ 2497139c1837SPaolo Bonzini 0x80 + 23, 6, /* DW_CFA_offset, s7, -48 */ 2498139c1837SPaolo Bonzini 0x80 + 24, 5, /* DW_CFA_offset, s8, -40 */ 2499139c1837SPaolo Bonzini 0x80 + 25, 4, /* DW_CFA_offset, s9, -32 */ 2500139c1837SPaolo Bonzini 0x80 + 26, 3, /* DW_CFA_offset, s10, -24 */ 2501139c1837SPaolo Bonzini 0x80 + 27, 2, /* DW_CFA_offset, s11, -16 */ 2502139c1837SPaolo Bonzini 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ 2503139c1837SPaolo Bonzini } 2504139c1837SPaolo Bonzini}; 2505139c1837SPaolo Bonzini 2506755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size) 2507139c1837SPaolo Bonzini{ 2508139c1837SPaolo Bonzini tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); 2509139c1837SPaolo Bonzini} 2510