[v3,1/2] sim: riscv: fix a divw division by -1 bug
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Test passed
|
Commit Message
There is a bug in divw for riscv64 target
with dividing by -1, the result was always 0,
when it should in fact be sign-extended -dividend.
It did not affect the rv32 target, because
these instructions are rv64 only.
Since 1 << 31 is an integer overflow this avoids
an undefined behaviour bug at the same time.
This caused test failures in the gcc testsuite like:
FAIL: gcc.c-torture/execute/arith-rand-ll.c -O0 execution test
FAIL: gcc.c-torture/execute/arith-rand-ll.c -O1 execution test
FAIL: gcc.c-torture/execute/arith-rand-ll.c -O2 execution test
FAIL: gcc.c-torture/execute/arith-rand-ll.c -O3 execution test
FAIL: gcc.c-torture/execute/arith-rand.c -O0 execution test
FAIL: gcc.c-torture/execute/arith-rand.c -O1 execution test
FAIL: gcc.c-torture/execute/arith-rand.c -O2 execution test
FAIL: gcc.c-torture/execute/arith-rand.c -O3 execution test
...
---
sim/riscv/sim-main.c | 2 +-
sim/testsuite/riscv/allinsn.exp | 17 ++++++++++++++++-
sim/testsuite/riscv/divw.s | 31 +++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+), 2 deletions(-)
create mode 100644 sim/testsuite/riscv/divw.s
v2: added a test case
v3: the target architecture detection code added with v2
caused timeouts when running the testsuite with other
targets, therefore added a check that "sim/riscv/run"
exists before trying to execute it
@@ -724,7 +724,7 @@ execute_m (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
if (EXTEND32 (riscv_cpu->regs[rs2]) == -1)
- tmp = 1 << 31;
+ tmp = EXTEND32 (-(uint32_t) riscv_cpu->regs[rs1]);
else if (EXTEND32 (riscv_cpu->regs[rs2]))
tmp = EXTEND32 (riscv_cpu->regs[rs1]) / EXTEND32 (riscv_cpu->regs[rs2]);
else
@@ -3,7 +3,22 @@
sim_init
# all machines
-set all_machs "riscv32 riscv64"
+set all_machs ""
+
+if [file exists $sim_path] {
+ remote_spawn host "$sim_path --model RV32GC --help"
+ set result [remote_wait host 240]
+ set return_code [lindex $result 0]
+ if { $return_code == 0 } {
+ set all_machs "$all_machs riscv32"
+ }
+ remote_spawn host "$sim_path --model RV64GC --help"
+ set result [remote_wait host 240]
+ set return_code [lindex $result 0]
+ if { $return_code == 0 } {
+ set all_machs "$all_machs riscv64"
+ }
+}
foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.s]] {
# If we're only testing specific files and this isn't one of them, skip it.
new file mode 100644
@@ -0,0 +1,31 @@
+# Basic divw tests.
+# mach: riscv64
+# sim(riscv64): --model RV64GC
+# ld(riscv64): -m elf64lriscv
+# as(riscv64): -march=rv64gc
+
+.include "testutils.inc"
+
+ .macro test_divw dividend, divisor, answer
+ # Setup inputs.
+ li a1, \dividend
+ li a2, \divisor
+
+ # Do the divide.
+ divw a3, a1, a2
+
+ # Check answer is correct.
+ li a4, \answer
+ bne a3, a4, test_failed
+ .endm
+
+
+ start
+
+ test_divw 1, -1, -1
+ test_divw 6, 2, 3
+
+ pass
+
+test_failed:
+ fail