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>
---
target/sparc/insns.decode | 4 +
target/sparc/translate.c | 152 +++++++++++++++-----------------------
2 files changed, 64 insertions(+), 92 deletions(-)
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
index 45eb6a967f..5df3b1add4 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -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 ----- - -------------
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index ebffcd7393..4c0e7cde4a 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -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:
--
2.34.1