target/sparc: Move LDFSR, STFSR to decodetree

Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-10-05 02:12:59 -07:00
parent 287b11520b
commit 3d3c06737b
2 changed files with 64 additions and 92 deletions

View File

@ -306,10 +306,14 @@ STX 11 ..... 011110 ..... . ............. @r_r_r_asi # STXA
STX 11 ..... 011110 ..... . ............. @r_r_i_asi # STXA
LDF 11 ..... 100000 ..... . ............. @r_r_ri_na
LDFSR 11 00000 100001 ..... . ............. @n_r_ri
LDXFSR 11 00001 100001 ..... . ............. @n_r_ri
LDQF 11 ..... 100010 ..... . ............. @q_r_ri_na
LDDF 11 ..... 100011 ..... . ............. @d_r_ri_na
STF 11 ..... 100100 ..... . ............. @r_r_ri_na
STFSR 11 00000 100101 ..... . ............. @n_r_ri
STXFSR 11 00001 100101 ..... . ............. @n_r_ri
{
STQF 11 ..... 100110 ..... . ............. @q_r_ri_na
STDFQ 11 ----- 100110 ----- - -------------

View File

@ -45,6 +45,7 @@
# define gen_helper_clear_softint(E, S) qemu_build_not_reached()
# define gen_helper_done(E) qemu_build_not_reached()
# define gen_helper_flushw(E) qemu_build_not_reached()
# define gen_helper_ldxfsr(D, E, A, B) qemu_build_not_reached()
# define gen_helper_rdccr(D, E) qemu_build_not_reached()
# define gen_helper_rdcwp(D, E) qemu_build_not_reached()
# define gen_helper_restored(E) qemu_build_not_reached()
@ -164,12 +165,6 @@ typedef struct {
#define UA2005_HTRAP_MASK 0xff
#define V8_TRAP_MASK 0x7f
static int sign_extend(int x, int len)
{
len = 32 - len;
return (x << len) >> len;
}
#define IS_IMM (insn & (1<<13))
static void gen_update_fprs_dirty(DisasContext *dc, int rd)
@ -2655,13 +2650,13 @@ static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
}
}
#ifdef TARGET_SPARC64
static TCGv get_src1(DisasContext *dc, unsigned int insn)
{
unsigned int rs1 = GET_FIELD(insn, 13, 17);
return gen_load_gpr(dc, rs1);
}
#ifdef TARGET_SPARC64
static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
{
TCGv_i32 c32, zero, dst, s1, s2;
@ -4680,6 +4675,61 @@ static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
return true;
}
static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a)
{
TCGv addr;
TCGv_i32 tmp;
addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
if (addr == NULL) {
return false;
}
if (gen_trap_ifnofpu(dc)) {
return true;
}
tmp = tcg_temp_new_i32();
tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN);
gen_helper_ldfsr(cpu_fsr, tcg_env, cpu_fsr, tmp);
return advance_pc(dc);
}
static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a)
{
TCGv addr;
TCGv_i64 tmp;
if (!avail_64(dc)) {
return false;
}
addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
if (addr == NULL) {
return false;
}
if (gen_trap_ifnofpu(dc)) {
return true;
}
tmp = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(tmp, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN);
gen_helper_ldxfsr(cpu_fsr, tcg_env, cpu_fsr, tmp);
return advance_pc(dc);
}
static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
{
TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
if (addr == NULL) {
return false;
}
if (gen_trap_ifnofpu(dc)) {
return true;
}
tcg_gen_qemu_st_tl(cpu_fsr, addr, dc->mem_idx, mop | MO_ALIGN);
return advance_pc(dc);
}
TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
#define CHECK_IU_FEATURE(dc, FEATURE) \
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
goto illegal_insn;
@ -4693,10 +4743,10 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
unsigned int opc, rs1, rs2, rd;
TCGv cpu_src1 __attribute__((unused));
TCGv cpu_src2 __attribute__((unused));
TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
TCGv_i32 cpu_src1_32, cpu_src2_32;
TCGv_i64 cpu_src1_64, cpu_src2_64;
TCGv_i32 cpu_dst_32 __attribute__((unused));
TCGv_i64 cpu_dst_64 __attribute__((unused));
target_long simm;
opc = GET_FIELD(insn, 0, 1);
rd = GET_FIELD(insn, 2, 6);
@ -5477,89 +5527,7 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
}
break;
case 3: /* load/store instructions */
{
unsigned int xop = GET_FIELD(insn, 7, 12);
/* ??? gen_address_mask prevents us from using a source
register directly. Always generate a temporary. */
TCGv cpu_addr = tcg_temp_new();
tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn));
if (IS_IMM) { /* immediate */
simm = GET_FIELDs(insn, 19, 31);
if (simm != 0) {
tcg_gen_addi_tl(cpu_addr, cpu_addr, simm);
}
} else { /* register */
rs2 = GET_FIELD(insn, 27, 31);
if (rs2 != 0) {
tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2));
}
}
if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) ||
(xop > 0x17 && xop <= 0x1d ) ||
(xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) {
goto illegal_insn; /* in decodetree */
} else if (xop >= 0x20 && xop < 0x24) {
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
switch (xop) {
case 0x20: /* ldf, load fpreg */
case 0x22: /* ldqf, load quad fpreg */
case 0x23: /* lddf, load double fpreg */
g_assert_not_reached(); /* in decodetree */
case 0x21: /* ldfsr, V9 ldxfsr */
#ifdef TARGET_SPARC64
gen_address_mask(dc, cpu_addr);
if (rd == 1) {
TCGv_i64 t64 = tcg_temp_new_i64();
tcg_gen_qemu_ld_i64(t64, cpu_addr,
dc->mem_idx, MO_TEUQ | MO_ALIGN);
gen_helper_ldxfsr(cpu_fsr, tcg_env, cpu_fsr, t64);
break;
}
#endif
cpu_dst_32 = tcg_temp_new_i32();
tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr,
dc->mem_idx, MO_TEUL | MO_ALIGN);
gen_helper_ldfsr(cpu_fsr, tcg_env, cpu_fsr, cpu_dst_32);
break;
default:
goto illegal_insn;
}
} else if (xop > 0x23 && xop < 0x28) {
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
}
switch (xop) {
case 0x24: /* stf, store fpreg */
case 0x26: /* v9 stqf, v8 stdfq */
case 0x27: /* stdf, store double fpreg */
g_assert_not_reached();
case 0x25: /* stfsr, V9 stxfsr */
{
#ifdef TARGET_SPARC64
gen_address_mask(dc, cpu_addr);
if (rd == 1) {
tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr,
dc->mem_idx, MO_TEUQ | MO_ALIGN);
break;
}
#endif
tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr,
dc->mem_idx, MO_TEUL | MO_ALIGN);
}
break;
default:
goto illegal_insn;
}
} else if (xop > 0x33 && xop < 0x3f) {
goto illegal_insn; /* in decodetree */
} else {
goto illegal_insn;
}
}
break;
goto illegal_insn; /* in decodetree */
}
advance_pc(dc);
jmp_insn: