diff options
author | Xavier Leroy <xavier.leroy@inria.fr> | 1996-07-01 12:39:13 +0000 |
---|---|---|
committer | Xavier Leroy <xavier.leroy@inria.fr> | 1996-07-01 12:39:13 +0000 |
commit | 51a3a69a47e3714ae13a73758d8ff2cccb1d7df2 (patch) | |
tree | d75791702ea8f793259d26a9df22f504c0e4a021 | |
parent | e844057f4c00725fcd00f080b6e1008fe06491a4 (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.c | 21 |
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): |