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 | 5 +++
target/sparc/translate.c | 69 +++++++++++++++++++++++----------------
2 files changed, 45 insertions(+), 29 deletions(-)
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
index 18a840709f..0552f1447d 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -391,6 +391,11 @@ FCMPEq 10 000 cc:2 110101 rs1:5 0 0101 0111 rs2:5
FORNOTs 10 ..... 110110 ..... 0 0111 1011 ..... @r_r_r_swap # ... 1s
FORd 10 ..... 110110 ..... 0 0111 1100 ..... @r_r_r
FORs 10 ..... 110110 ..... 0 0111 1101 ..... @r_r_r
+
+ FZEROd 10 rd:5 110110 00000 0 0110 0000 00000
+ FZEROs 10 rd:5 110110 00000 0 0110 0001 00000
+ FONEd 10 rd:5 110110 00000 0 0111 1110 00000
+ FONEs 10 rd:5 110110 00000 0 0111 1111 00000
]
NCP 10 ----- 110110 ----- --------- ----- # v8 CPop1
}
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 15c91c6caa..62c77ae5e1 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -4586,6 +4586,45 @@ static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
+static bool do_fc(DisasContext *dc, int rd, bool c)
+{
+ uint64_t mask;
+
+ if (gen_trap_ifnofpu(dc)) {
+ return true;
+ }
+
+ if (rd & 1) {
+ mask = MAKE_64BIT_MASK(0, 32);
+ } else {
+ mask = MAKE_64BIT_MASK(32, 32);
+ }
+ if (c) {
+ tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask);
+ } else {
+ tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask);
+ }
+ gen_update_fprs_dirty(dc, rd);
+ return advance_pc(dc);
+}
+
+TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
+TRANS(FONEs, VIS1, do_fc, a->rd, 1)
+
+static bool do_dc(DisasContext *dc, int rd, int64_t c)
+{
+ if (gen_trap_ifnofpu(dc)) {
+ return true;
+ }
+
+ tcg_gen_movi_i64(cpu_fpr[rd / 2], c);
+ gen_update_fprs_dirty(dc, rd);
+ return advance_pc(dc);
+}
+
+TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
+TRANS(FONEd, VIS1, do_dc, a->rd, -1)
+
static bool do_ff(DisasContext *dc, arg_r_r *a,
void (*func)(TCGv_i32, TCGv_i32))
{
@@ -5303,10 +5342,7 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
} else if (xop == 0x36) {
#ifdef TARGET_SPARC64
/* VIS */
- TCGv_i64 cpu_dst_64;
- TCGv_i32 cpu_dst_32;
int opf = GET_FIELD_SP(insn, 5, 13);
- int rd = GET_FIELD(insn, 2, 6);
if (gen_trap_ifnofpu(dc)) {
goto jmp_insn;
@@ -5390,31 +5426,11 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
case 0x02e: /* VIS I fcmpeq32 */
case 0x03b: /* VIS I fpack16 */
case 0x03d: /* VIS I fpackfix */
- g_assert_not_reached(); /* in decodetree */
case 0x060: /* VIS I fzero */
- CHECK_FPU_FEATURE(dc, VIS1);
- cpu_dst_64 = gen_dest_fpr_D(dc, rd);
- tcg_gen_movi_i64(cpu_dst_64, 0);
- gen_store_fpr_D(dc, rd, cpu_dst_64);
- break;
case 0x061: /* VIS I fzeros */
- CHECK_FPU_FEATURE(dc, VIS1);
- cpu_dst_32 = gen_dest_fpr_F(dc);
- tcg_gen_movi_i32(cpu_dst_32, 0);
- gen_store_fpr_F(dc, rd, cpu_dst_32);
- break;
case 0x07e: /* VIS I fone */
- CHECK_FPU_FEATURE(dc, VIS1);
- cpu_dst_64 = gen_dest_fpr_D(dc, rd);
- tcg_gen_movi_i64(cpu_dst_64, -1);
- gen_store_fpr_D(dc, rd, cpu_dst_64);
- break;
case 0x07f: /* VIS I fones */
- CHECK_FPU_FEATURE(dc, VIS1);
- cpu_dst_32 = gen_dest_fpr_F(dc);
- tcg_gen_movi_i32(cpu_dst_32, -1);
- gen_store_fpr_F(dc, rd, cpu_dst_32);
- break;
+ g_assert_not_reached(); /* in decodetree */
case 0x080: /* VIS I shutdown */
case 0x081: /* VIS II siam */
// XXX
@@ -5439,11 +5455,6 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
illegal_insn:
gen_exception(dc, TT_ILL_INSN);
return;
-#ifdef TARGET_SPARC64
- nfpu_insn:
- gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
- return;
-#endif
}
static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
--
2.34.1