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:
Alistair Francis 2018-12-19 19:17:32 +00:00 committed by Richard Henderson
parent 505e75c592
commit 8ce23a1312
1 changed files with 168 additions and 0 deletions

View File

@ -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;