Fix for v850e divq instruction
authorJeff Law <jeffreyalaw@gmail.com>
Wed, 6 Apr 2022 15:10:40 +0000 (11:10 -0400)
committerJeff Law <jeffreyalaw@gmail.com>
Wed, 6 Apr 2022 15:10:40 +0000 (11:10 -0400)
This is the last of the correctness fixes I've been carrying around for the
v850.

Like the other recent fixes, this is another case where we haven't been as
careful as we should WRT host vs target types.   For the divq instruction
both operands are 32 bit types.  Yet in the simulator code we convert them
from unsigned int to signed long by assignment.  So 0xfffffffb (aka -5)
turns into 4294967291 and naturally that changes the result of our division.

The fix is simple, insert a cast to int32_t to force interpretation as a
signed value.

Testcase for the simulator is included.  It has a trivial dependency on the
bins patch.

sim/testsuite/v850/divq.cgs [new file with mode: 0644]
sim/v850/simops.c

diff --git a/sim/testsuite/v850/divq.cgs b/sim/testsuite/v850/divq.cgs
new file mode 100644 (file)
index 0000000..8461f86
--- /dev/null
@@ -0,0 +1,11 @@
+# v850 bins
+# mach: v850e3v5
+# as: -mv850e3v5
+
+       .include "testutils.inc"
+       seti    0xfffffffb r11
+       seti    0x32 r10
+       divq    r11, r10, r11
+       reg     r10, 0xfffffff6
+       reg     r11, 0x0
+       pass
index e9a5d489d887b29f019d7ce51c5e527eae37a17e..f90a0f7573cfb837d940a0f198f9e4755b652452 100644 (file)
@@ -3135,8 +3135,8 @@ v850_div (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, u
   bfd_boolean     overflow = FALSE;
   
   /* Compute the result.  */
-  divide_by   = op0;
-  divide_this = op1;
+  divide_by   = (int32_t)op0;
+  divide_this = (int32_t)op1;
 
   if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
     {