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
|
STX 11 ..... 011110 ..... . ............. @r_r_i_asi # STXA
|
||||||
|
|
||||||
LDF 11 ..... 100000 ..... . ............. @r_r_ri_na
|
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
|
LDQF 11 ..... 100010 ..... . ............. @q_r_ri_na
|
||||||
LDDF 11 ..... 100011 ..... . ............. @d_r_ri_na
|
LDDF 11 ..... 100011 ..... . ............. @d_r_ri_na
|
||||||
|
|
||||||
STF 11 ..... 100100 ..... . ............. @r_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
|
STQF 11 ..... 100110 ..... . ............. @q_r_ri_na
|
||||||
STDFQ 11 ----- 100110 ----- - -------------
|
STDFQ 11 ----- 100110 ----- - -------------
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
# define gen_helper_clear_softint(E, S) qemu_build_not_reached()
|
# define gen_helper_clear_softint(E, S) qemu_build_not_reached()
|
||||||
# define gen_helper_done(E) 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_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_rdccr(D, E) qemu_build_not_reached()
|
||||||
# define gen_helper_rdcwp(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()
|
# define gen_helper_restored(E) qemu_build_not_reached()
|
||||||
@ -164,12 +165,6 @@ typedef struct {
|
|||||||
#define UA2005_HTRAP_MASK 0xff
|
#define UA2005_HTRAP_MASK 0xff
|
||||||
#define V8_TRAP_MASK 0x7f
|
#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))
|
#define IS_IMM (insn & (1<<13))
|
||||||
|
|
||||||
static void gen_update_fprs_dirty(DisasContext *dc, int rd)
|
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)
|
static TCGv get_src1(DisasContext *dc, unsigned int insn)
|
||||||
{
|
{
|
||||||
unsigned int rs1 = GET_FIELD(insn, 13, 17);
|
unsigned int rs1 = GET_FIELD(insn, 13, 17);
|
||||||
return gen_load_gpr(dc, rs1);
|
return gen_load_gpr(dc, rs1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_SPARC64
|
|
||||||
static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
|
static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
|
||||||
{
|
{
|
||||||
TCGv_i32 c32, zero, dst, s1, s2;
|
TCGv_i32 c32, zero, dst, s1, s2;
|
||||||
@ -4680,6 +4675,61 @@ static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
|
|||||||
return true;
|
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) \
|
#define CHECK_IU_FEATURE(dc, FEATURE) \
|
||||||
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
|
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
|
||||||
goto illegal_insn;
|
goto illegal_insn;
|
||||||
@ -4693,10 +4743,10 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
|
|||||||
unsigned int opc, rs1, rs2, rd;
|
unsigned int opc, rs1, rs2, rd;
|
||||||
TCGv cpu_src1 __attribute__((unused));
|
TCGv cpu_src1 __attribute__((unused));
|
||||||
TCGv cpu_src2 __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_i64 cpu_src1_64, cpu_src2_64;
|
||||||
|
TCGv_i32 cpu_dst_32 __attribute__((unused));
|
||||||
TCGv_i64 cpu_dst_64 __attribute__((unused));
|
TCGv_i64 cpu_dst_64 __attribute__((unused));
|
||||||
target_long simm;
|
|
||||||
|
|
||||||
opc = GET_FIELD(insn, 0, 1);
|
opc = GET_FIELD(insn, 0, 1);
|
||||||
rd = GET_FIELD(insn, 2, 6);
|
rd = GET_FIELD(insn, 2, 6);
|
||||||
@ -5477,89 +5527,7 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: /* load/store instructions */
|
case 3: /* load/store instructions */
|
||||||
{
|
goto illegal_insn; /* in decodetree */
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
advance_pc(dc);
|
advance_pc(dc);
|
||||||
jmp_insn:
|
jmp_insn:
|
||||||
|
Loading…
Reference in New Issue
Block a user