mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 03:43:37 +08:00
tcg/riscv: Add support for the constraints
Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Michael Clark <mjc@sifive.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <dba7315e4e20e879933f72d47ccf98f1cc612b8a.1545246859.git.alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
505e75c592
commit
8ce23a1312
@ -116,3 +116,171 @@ static const int tcg_target_call_oarg_regs[] = {
|
||||
TCG_REG_A0,
|
||||
TCG_REG_A1,
|
||||
};
|
||||
|
||||
#define TCG_CT_CONST_ZERO 0x100
|
||||
#define TCG_CT_CONST_S12 0x200
|
||||
#define TCG_CT_CONST_N12 0x400
|
||||
#define TCG_CT_CONST_M12 0x800
|
||||
|
||||
static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
|
||||
{
|
||||
if (TCG_TARGET_REG_BITS == 32) {
|
||||
return sextract32(val, pos, len);
|
||||
} else {
|
||||
return sextract64(val, pos, len);
|
||||
}
|
||||
}
|
||||
|
||||
/* parse target specific constraints */
|
||||
static const char *target_parse_constraint(TCGArgConstraint *ct,
|
||||
const char *ct_str, TCGType type)
|
||||
{
|
||||
switch (*ct_str++) {
|
||||
case 'r':
|
||||
ct->ct |= TCG_CT_REG;
|
||||
ct->u.regs = 0xffffffff;
|
||||
break;
|
||||
case 'L':
|
||||
/* qemu_ld/qemu_st constraint */
|
||||
ct->ct |= TCG_CT_REG;
|
||||
ct->u.regs = 0xffffffff;
|
||||
/* qemu_ld/qemu_st uses TCG_REG_TMP0 */
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
|
||||
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
|
||||
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
|
||||
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]);
|
||||
tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]);
|
||||
#endif
|
||||
break;
|
||||
case 'I':
|
||||
ct->ct |= TCG_CT_CONST_S12;
|
||||
break;
|
||||
case 'N':
|
||||
ct->ct |= TCG_CT_CONST_N12;
|
||||
break;
|
||||
case 'M':
|
||||
ct->ct |= TCG_CT_CONST_M12;
|
||||
break;
|
||||
case 'Z':
|
||||
/* we can use a zero immediate as a zero register argument. */
|
||||
ct->ct |= TCG_CT_CONST_ZERO;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return ct_str;
|
||||
}
|
||||
|
||||
/* test if a constant matches the constraint */
|
||||
static int tcg_target_const_match(tcg_target_long val, TCGType type,
|
||||
const TCGArgConstraint *arg_ct)
|
||||
{
|
||||
int ct = arg_ct->ct;
|
||||
if (ct & TCG_CT_CONST) {
|
||||
return 1;
|
||||
}
|
||||
if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
|
||||
return 1;
|
||||
}
|
||||
if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
|
||||
return 1;
|
||||
}
|
||||
if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
|
||||
return 1;
|
||||
}
|
||||
if ((ct & TCG_CT_CONST_M12) && val >= -0xfff && val <= 0xfff) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RISC-V Base ISA opcodes (IM)
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
OPC_ADD = 0x33,
|
||||
OPC_ADDI = 0x13,
|
||||
OPC_AND = 0x7033,
|
||||
OPC_ANDI = 0x7013,
|
||||
OPC_AUIPC = 0x17,
|
||||
OPC_BEQ = 0x63,
|
||||
OPC_BGE = 0x5063,
|
||||
OPC_BGEU = 0x7063,
|
||||
OPC_BLT = 0x4063,
|
||||
OPC_BLTU = 0x6063,
|
||||
OPC_BNE = 0x1063,
|
||||
OPC_DIV = 0x2004033,
|
||||
OPC_DIVU = 0x2005033,
|
||||
OPC_JAL = 0x6f,
|
||||
OPC_JALR = 0x67,
|
||||
OPC_LB = 0x3,
|
||||
OPC_LBU = 0x4003,
|
||||
OPC_LD = 0x3003,
|
||||
OPC_LH = 0x1003,
|
||||
OPC_LHU = 0x5003,
|
||||
OPC_LUI = 0x37,
|
||||
OPC_LW = 0x2003,
|
||||
OPC_LWU = 0x6003,
|
||||
OPC_MUL = 0x2000033,
|
||||
OPC_MULH = 0x2001033,
|
||||
OPC_MULHSU = 0x2002033,
|
||||
OPC_MULHU = 0x2003033,
|
||||
OPC_OR = 0x6033,
|
||||
OPC_ORI = 0x6013,
|
||||
OPC_REM = 0x2006033,
|
||||
OPC_REMU = 0x2007033,
|
||||
OPC_SB = 0x23,
|
||||
OPC_SD = 0x3023,
|
||||
OPC_SH = 0x1023,
|
||||
OPC_SLL = 0x1033,
|
||||
OPC_SLLI = 0x1013,
|
||||
OPC_SLT = 0x2033,
|
||||
OPC_SLTI = 0x2013,
|
||||
OPC_SLTIU = 0x3013,
|
||||
OPC_SLTU = 0x3033,
|
||||
OPC_SRA = 0x40005033,
|
||||
OPC_SRAI = 0x40005013,
|
||||
OPC_SRL = 0x5033,
|
||||
OPC_SRLI = 0x5013,
|
||||
OPC_SUB = 0x40000033,
|
||||
OPC_SW = 0x2023,
|
||||
OPC_XOR = 0x4033,
|
||||
OPC_XORI = 0x4013,
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
OPC_ADDIW = 0x1b,
|
||||
OPC_ADDW = 0x3b,
|
||||
OPC_DIVUW = 0x200503b,
|
||||
OPC_DIVW = 0x200403b,
|
||||
OPC_MULW = 0x200003b,
|
||||
OPC_REMUW = 0x200703b,
|
||||
OPC_REMW = 0x200603b,
|
||||
OPC_SLLIW = 0x101b,
|
||||
OPC_SLLW = 0x103b,
|
||||
OPC_SRAIW = 0x4000501b,
|
||||
OPC_SRAW = 0x4000503b,
|
||||
OPC_SRLIW = 0x501b,
|
||||
OPC_SRLW = 0x503b,
|
||||
OPC_SUBW = 0x4000003b,
|
||||
#else
|
||||
/* Simplify code throughout by defining aliases for RV32. */
|
||||
OPC_ADDIW = OPC_ADDI,
|
||||
OPC_ADDW = OPC_ADD,
|
||||
OPC_DIVUW = OPC_DIVU,
|
||||
OPC_DIVW = OPC_DIV,
|
||||
OPC_MULW = OPC_MUL,
|
||||
OPC_REMUW = OPC_REMU,
|
||||
OPC_REMW = OPC_REM,
|
||||
OPC_SLLIW = OPC_SLLI,
|
||||
OPC_SLLW = OPC_SLL,
|
||||
OPC_SRAIW = OPC_SRAI,
|
||||
OPC_SRAW = OPC_SRA,
|
||||
OPC_SRLIW = OPC_SRLI,
|
||||
OPC_SRLW = OPC_SRL,
|
||||
OPC_SUBW = OPC_SUB,
|
||||
#endif
|
||||
|
||||
OPC_FENCE = 0x0000000f,
|
||||
} RISCVInsn;
|
||||
|
Loading…
Reference in New Issue
Block a user