diff options
-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): |