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:
parent
287b11520b
commit
3d3c06737b
@ -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 ----- - -------------
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user