summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>1996-07-01 12:39:13 +0000
committerXavier Leroy <xavier.leroy@inria.fr>1996-07-01 12:39:13 +0000
commit51a3a69a47e3714ae13a73758d8ff2cccb1d7df2 (patch)
treed75791702ea8f793259d26a9df22f504c0e4a021
parente844057f4c00725fcd00f080b6e1008fe06491a4 (diff)
Normalisation de la semantique de div et mod sur les nombres negatifs
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@911 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--byterun/interp.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/byterun/interp.c b/byterun/interp.c
index 4c345d8ab..7316c0e22 100644
--- a/byterun/interp.c
+++ b/byterun/interp.c
@@ -791,16 +791,25 @@ value interprete(prog, prog_size)
accu = (value)((long) accu - (long) *sp++ + 1); Next;
Instruct(MULINT):
accu = Val_long(Long_val(accu) * Long_val(*sp++)); Next;
+
+#define Abs(x) (unsigned long)(x < 0 ? -x : x)
+
Instruct(DIVINT): {
- value div = *sp++;
- if (div == Val_long(0)) { Setup_for_c_call; raise_zero_divide(); }
- accu = Val_long(Long_val(accu) / Long_val(div));
+ long dividend = Long_val(accu);
+ long divisor = Long_val(*sp++);
+ if (divisor == 0) { Setup_for_c_call; raise_zero_divide(); }
+ accu = Abs(dividend) / Abs(divisor);
+ if ((dividend ^ divisor) < 0) accu = -accu;
+ accu = Val_long(accu);
Next;
}
Instruct(MODINT): {
- value div = *sp++;
- if (div == Val_long(0)) { Setup_for_c_call; raise_zero_divide(); }
- accu = Val_long(Long_val(accu) % Long_val(div));
+ long dividend = Long_val(accu);
+ long divisor = Long_val(*sp++);
+ if (divisor == 0) { Setup_for_c_call; raise_zero_divide(); }
+ accu = Abs(dividend) % Abs(divisor);
+ if (dividend < 0) accu = -accu;
+ accu = Val_long(accu);
Next;
}
Instruct(ANDINT):