@@ -1359,6 +1359,40 @@ float64_compare (SIM_CPU *cpu, int rd, int rs1, int rs2, int flags)
}
}
+/* Handle double precision floating point math instructions. */
+static void
+float64_math (SIM_CPU *cpu, int rd, int rs1, int rs2, int flags)
+{
+ struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
+ double a, b, result = 0;
+ uint64_t rs1_bits, rs2_bits, rd_bits;
+ const char *frd_name = riscv_fpr_names_abi[rd];
+ const char *frs1_name = riscv_fpr_names_abi[rs1];
+ const char *frs2_name = riscv_fpr_names_abi[rs2];
+
+ rs1_bits = (uint64_t) riscv_cpu->fpregs[rs1];
+ memcpy (&a, &rs1_bits, sizeof (a));
+ rs2_bits = (uint64_t) riscv_cpu->fpregs[rs2];
+ memcpy (&b, &rs2_bits, sizeof (b));
+
+ switch (flags)
+ {
+ case FMAX:
+ TRACE_INSN (cpu, "fmax.d %s, %s, %s;", frd_name, frs1_name, frs2_name);
+ result = fmax (a, b);
+ break;
+ case FMIN:
+ TRACE_INSN (cpu, "fmin.d %s, %s, %s;", frd_name, frs1_name, frs2_name);
+ result = fmin (a, b);
+ break;
+ }
+
+ /* Store result. */
+ memcpy (&rd_bits, &result, sizeof (result));
+ store_fp (cpu, rd, rd_bits);
+
+}
+
/* Simulate single precision floating point instructions. */
static sim_cia
execute_f (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
@@ -1668,6 +1702,37 @@ execute_d (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
store_fp (cpu, rd, rs1_bits);
break;
}
+ case MATCH_FSGNJN_D:
+ {
+ uint64_t rs1_bits, rs2_bits;
+ TRACE_INSN (cpu, "fsgnjn.d %s, %s, %s;", frd_name, frs1_name,
+ frs2_name);
+ rs1_bits = (uint64_t) riscv_cpu->fpregs[rs1];
+ rs2_bits = ~((uint64_t) riscv_cpu->fpregs[rs2]);
+ rs1_bits = (rs2_bits & 0x8000000000000000ull)
+ | (rs1_bits & 0x7fffffffffffffffull);
+ store_fp (cpu, rd, rs1_bits);
+ break;
+ }
+ case MATCH_FSGNJX_D:
+ {
+ uint64_t rs1_bits, rs2_bits;
+ TRACE_INSN (cpu, "fsgnjx.d %s, %s, %s;", frd_name, frs1_name,
+ frs2_name);
+ rs1_bits = (uint64_t) riscv_cpu->fpregs[rs1];
+ rs2_bits = (uint64_t) riscv_cpu->fpregs[rs2];
+ rs1_bits = ((rs1_bits & 0x8000000000000000ull)
+ ^ (rs2_bits & 0x8000000000000000ull))
+ | (rs1_bits & 0x7fffffffffffffffull);
+ store_fp (cpu, rd, rs1_bits);
+ break;
+ }
+ case MATCH_FMIN_D:
+ float64_math (cpu, rd, rs1, rs2, FMIN);
+ break;
+ case MATCH_FMAX_D:
+ float64_math (cpu, rd, rs1, rs2, FMAX);
+ break;
default:
TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
@@ -20,11 +20,16 @@ _arg2:
.double 0.5
.double 2.2
+_expected:
+ .double 0.5
+ .double 2.2
+
start
.option push
.option norelax
la a0,_arg1
la a1,_arg2
+ la a2,_expected
li a3,1
.option pop
@@ -65,6 +70,23 @@ _arg2:
fclass.d a4,fa0
bne a3,a4,test_fail
+ # Test fmin.d instruction.
+ fld fa0,0(a0)
+ fld fa1,8(a1)
+ fld fa2,0(a2)
+ fmin.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ li a3,1
+ bne a4,a3,test_fail
+
+ # Test fmax.d instruction.
+ fld fa0,0(a0)
+ fld fa1,8(a1)
+ fld fa2,8(a2)
+ fmax.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+
test_pass:
pass
new file mode 100644
@@ -0,0 +1,87 @@
+# Double precision sign-injection instructions.
+# mach: riscv64
+# sim(riscv64): --model RV64ID
+# ld(riscv64): -m elf64lriscv
+# as(riscv64): -march=rv64id
+
+.include "testutils.inc"
+
+ .section .data
+ .align 3
+
+_arg1:
+ .double 2.0
+ .double -2.0
+
+_arg2:
+ .double 1.0
+ .double -1.0
+
+_expected:
+ .double 2.0
+ .double -2.0
+
+ start
+ .option push
+ .option norelax
+ la a0,_arg1
+ la a1,_arg2
+ la a2,_expected
+ li a3,1
+ .option pop
+
+ # Test fsgnj.d instruction.
+ fld fa0,0(a0)
+ fld fa1,0(a1)
+ fld fa2,0(a2)
+ fsgnj.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+ fld fa1,8(a1)
+ fld fa2,8(a2)
+ fsgnj.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+
+ # Test fsgnjn.d (fneg.d) instruction.
+ fld fa0,0(a0)
+ fld fa1,0(a1)
+ fld fa2,8(a2)
+ fsgnjn.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+ fld fa1,8(a1)
+ fld fa2,0(a2)
+ fsgnjn.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+ fld fa0,0(a0)
+ fld fa2,8(a2)
+ fneg.d fa3,fa0
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+
+ # Test fsgnjx.d (fabs.d) instruction.
+ fld fa0,0(a0)
+ fld fa1,8(a1)
+ fld fa2,8(a2)
+ fsgnjx.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+ fld fa0,8(a0)
+ fld fa1,8(a1)
+ fld fa2,0(a2)
+ fsgnjx.d fa3,fa0,fa1
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+ fld fa0,8(a0)
+ fld fa2,0(a2)
+ fabs.d fa3,fa0
+ feq.d a4,fa3,fa2
+ bne a4,a3,test_fail
+
+test_pass:
+ pass
+
+test_fail:
+ fail