target/riscv: Move gen_arith_imm() decoding into trans_* functions

gen_arith_imm() does a lot of decoding manually, which was hard to read
in case of the shift instructions and is not necessary anymore with
decodetree.

Backports commit 7a50d3e2ae7f13b24fe55990ea0b8ddcbbb43130 from qemu
This commit is contained in:
Bastian Koppelmann 2019-03-19 05:13:26 -04:00 committed by Lioncash
parent 6190837e2f
commit cb7c94fbc4
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 117 additions and 101 deletions

View file

@ -35,12 +35,13 @@
# Argument sets:
&b imm rs2 rs1
&i imm rs1 rd
&shift shamt rs1 rd
&atomic aq rl rs2 rs1 rd
# Formats 32:
@r ....... ..... ..... ... ..... ....... %rs2 %rs1 %rd
@i ............ ..... ... ..... ....... imm=%imm_i %rs1 %rd
@i ............ ..... ... ..... ....... &i imm=%imm_i %rs1 %rd
@b ....... ..... ..... ... ..... ....... &b imm=%imm_b %rs2 %rs1
@s ....... ..... ..... ... ..... ....... imm=%imm_s %rs2 %rs1
@u .................... ..... ....... imm=%imm_u %rd

View file

@ -225,52 +225,101 @@ static bool trans_sd(DisasContext *ctx, arg_sd *a)
static bool trans_addi(DisasContext *ctx, arg_addi *a)
{
gen_arith_imm(ctx, OPC_RISC_ADDI, a->rd, a->rs1, a->imm);
return true;
return gen_arith_imm(ctx, a, &tcg_gen_add_tl);
}
static bool trans_slti(DisasContext *ctx, arg_slti *a)
{
gen_arith_imm(ctx, OPC_RISC_SLTI, a->rd, a->rs1, a->imm);
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv source1;
source1 = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, source1, a->rs1);
tcg_gen_setcondi_tl(tcg_ctx, TCG_COND_LT, source1, source1, a->imm);
gen_set_gpr(ctx, a->rd, source1);
tcg_temp_free(tcg_ctx, source1);
return true;
}
static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
{
gen_arith_imm(ctx, OPC_RISC_SLTIU, a->rd, a->rs1, a->imm);
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv source1;
source1 = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, source1, a->rs1);
tcg_gen_setcondi_tl(tcg_ctx, TCG_COND_LTU, source1, source1, a->imm);
gen_set_gpr(ctx, a->rd, source1);
tcg_temp_free(tcg_ctx, source1);
return true;
}
static bool trans_xori(DisasContext *ctx, arg_xori *a)
{
gen_arith_imm(ctx, OPC_RISC_XORI, a->rd, a->rs1, a->imm);
return true;
return gen_arith_imm(ctx, a, &tcg_gen_xor_tl);
}
static bool trans_ori(DisasContext *ctx, arg_ori *a)
{
gen_arith_imm(ctx, OPC_RISC_ORI, a->rd, a->rs1, a->imm);
return true;
return gen_arith_imm(ctx, a, &tcg_gen_or_tl);
}
static bool trans_andi(DisasContext *ctx, arg_andi *a)
{
gen_arith_imm(ctx, OPC_RISC_ANDI, a->rd, a->rs1, a->imm);
return true;
return gen_arith_imm(ctx, a, &tcg_gen_and_tl);
}
static bool trans_slli(DisasContext *ctx, arg_slli *a)
{
gen_arith_imm(ctx, OPC_RISC_SLLI, a->rd, a->rs1, a->shamt);
if (a->shamt >= TARGET_LONG_BITS) {
return false;
}
if (a->rd != 0) {
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv t = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, t, a->rs1);
tcg_gen_shli_tl(tcg_ctx, t, t, a->shamt);
gen_set_gpr(ctx, a->rd, t);
tcg_temp_free(tcg_ctx, t);
} /* NOP otherwise */
return true;
}
static bool trans_srli(DisasContext *ctx, arg_srli *a)
{
gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, a->rd, a->rs1, a->shamt);
if (a->shamt >= TARGET_LONG_BITS) {
return false;
}
if (a->rd != 0) {
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv t = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, t, a->rs1);
tcg_gen_shri_tl(tcg_ctx, t, t, a->shamt);
gen_set_gpr(ctx, a->rd, t);
tcg_temp_free(tcg_ctx, t);
} /* NOP otherwise */
return true;
}
static bool trans_srai(DisasContext *ctx, arg_srai *a)
{
gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_I, a->rd, a->rs1, a->shamt | 0x400);
if (a->shamt >= TARGET_LONG_BITS) {
return false;
}
if (a->rd != 0) {
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv t = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, t, a->rs1);
tcg_gen_sari_tl(tcg_ctx, t, t, a->shamt);
gen_set_gpr(ctx, a->rd, t);
tcg_temp_free(tcg_ctx, t);
} /* NOP otherwise */
return true;
}
@ -337,26 +386,45 @@ static bool trans_and(DisasContext *ctx, arg_and *a)
#ifdef TARGET_RISCV64
static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
{
gen_arith_imm(ctx, OPC_RISC_ADDIW, a->rd, a->rs1, a->imm);
return true;
return gen_arith_imm(ctx, a, &gen_addw);
}
static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
{
gen_arith_imm(ctx, OPC_RISC_SLLIW, a->rd, a->rs1, a->shamt);
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv source1;
source1 = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, source1, a->rs1);
tcg_gen_shli_tl(tcg_ctx, source1, source1, a->shamt);
tcg_gen_ext32s_tl(tcg_ctx, source1, source1);
gen_set_gpr(ctx, a->rd, source1);
tcg_temp_free(tcg_ctx, source1);
return true;
}
static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
{
gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_IW, a->rd, a->rs1, a->shamt);
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv t = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, t, a->rs1);
tcg_gen_extract_tl(tcg_ctx, t, t, a->shamt, 32 - a->shamt);
/* sign-extend for W instructions */
tcg_gen_ext32s_tl(tcg_ctx, t, t);
gen_set_gpr(ctx, a->rd, t);
tcg_temp_free(tcg_ctx, t);
return true;
}
static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a)
{
gen_arith_imm(ctx, OPC_RISC_SHIFT_RIGHT_IW , a->rd, a->rs1,
a->shamt | 0x400);
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv t = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, t, a->rs1);
tcg_gen_sextract_tl(tcg_ctx, t, t, a->shamt, 32 - a->shamt);
gen_set_gpr(ctx, a->rd, t);
tcg_temp_free(tcg_ctx, t);
return true;
}

View file

@ -447,87 +447,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
tcg_temp_free(tcg_ctx, source2);
}
static void gen_arith_imm(DisasContext *ctx, uint32_t opc, int rd,
int rs1, target_long imm)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv source1 = tcg_temp_new(tcg_ctx);
int shift_len = TARGET_LONG_BITS;
int shift_a;
gen_get_gpr(ctx, source1, rs1);
switch (opc) {
case OPC_RISC_ADDI:
#if defined(TARGET_RISCV64)
case OPC_RISC_ADDIW:
#endif
tcg_gen_addi_tl(tcg_ctx, source1, source1, imm);
break;
case OPC_RISC_SLTI:
tcg_gen_setcondi_tl(tcg_ctx, TCG_COND_LT, source1, source1, imm);
break;
case OPC_RISC_SLTIU:
tcg_gen_setcondi_tl(tcg_ctx, TCG_COND_LTU, source1, source1, imm);
break;
case OPC_RISC_XORI:
tcg_gen_xori_tl(tcg_ctx, source1, source1, imm);
break;
case OPC_RISC_ORI:
tcg_gen_ori_tl(tcg_ctx, source1, source1, imm);
break;
case OPC_RISC_ANDI:
tcg_gen_andi_tl(tcg_ctx, source1, source1, imm);
break;
#if defined(TARGET_RISCV64)
case OPC_RISC_SLLIW:
shift_len = 32;
/* FALLTHRU */
#endif
case OPC_RISC_SLLI:
if (imm >= shift_len) {
goto do_illegal;
}
tcg_gen_shli_tl(tcg_ctx, source1, source1, imm);
break;
#if defined(TARGET_RISCV64)
case OPC_RISC_SHIFT_RIGHT_IW:
shift_len = 32;
/* FALLTHRU */
#endif
case OPC_RISC_SHIFT_RIGHT_I:
/* differentiate on IMM */
shift_a = imm & 0x400;
imm &= 0x3ff;
if (imm >= shift_len) {
goto do_illegal;
}
if (imm != 0) {
if (shift_a) {
/* SRAI[W] */
tcg_gen_sextract_tl(tcg_ctx, source1, source1, imm, shift_len - imm);
} else {
/* SRLI[W] */
tcg_gen_extract_tl(tcg_ctx, source1, source1, imm, shift_len - imm);
}
/* No further sign-extension needed for W instructions. */
opc &= ~0x8;
}
break;
default:
do_illegal:
gen_exception_illegal(ctx);
return;
}
if (opc & 0x8) { /* sign-extend for W instructions */
tcg_gen_ext32s_tl(tcg_ctx, source1, source1);
}
gen_set_gpr(ctx, rd, source1);
tcg_temp_free(tcg_ctx, source1);
}
static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
{
target_ulong next_pc;
@ -809,6 +728,34 @@ static int ex_rvc_register(int reg)
bool decode_insn32(DisasContext *ctx, uint32_t insn);
/* Include the auto-generated decoder for 32 bit insn */
#include "decode_insn32.inc.c"
static bool gen_arith_imm(DisasContext *ctx, arg_i *a,
void(*func)(TCGContext *, TCGv, TCGv, TCGv))
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv source1, source2;
source1 = tcg_temp_new(tcg_ctx);
source2 = tcg_temp_new(tcg_ctx);
gen_get_gpr(ctx, source1, a->rs1);
tcg_gen_movi_tl(tcg_ctx, source2, a->imm);
(*func)(tcg_ctx, source1, source1, source2);
gen_set_gpr(ctx, a->rd, source1);
tcg_temp_free(tcg_ctx, source1);
tcg_temp_free(tcg_ctx, source2);
return true;
}
#ifdef TARGET_RISCV64
static void gen_addw(TCGContext *tcg_ctx, TCGv ret, TCGv arg1, TCGv arg2)
{
tcg_gen_add_tl(tcg_ctx, ret, arg1, arg2);
tcg_gen_ext32s_tl(tcg_ctx, ret, ret);
}
#endif
/* Include insn module translation function */
#include "insn_trans/trans_rvi.inc.c"
#include "insn_trans/trans_rvm.inc.c"