Fix: DIV and MOD on negative args
This commit is contained in:
parent
7f5abdd670
commit
109a357e95
|
@ -782,7 +782,13 @@ CodeOper(expr, true_label, false_label)
|
|||
Operands(expr);
|
||||
switch(tp->tp_fund) {
|
||||
case T_INTEGER:
|
||||
C_dvi(tp->tp_size);
|
||||
if ((int)(tp->tp_size) == word_size) {
|
||||
C_cal((int)(tp->tp_size) == (int)word_size
|
||||
? "dvi"
|
||||
: "dvil");
|
||||
}
|
||||
C_asp(2*tp->tp_size);
|
||||
C_lfr(tp->tp_size);
|
||||
break;
|
||||
case T_POINTER:
|
||||
case T_EQUAL:
|
||||
|
@ -798,7 +804,13 @@ CodeOper(expr, true_label, false_label)
|
|||
Operands(expr);
|
||||
switch(tp->tp_fund) {
|
||||
case T_INTEGER:
|
||||
C_rmi(tp->tp_size);
|
||||
if ((int)(tp->tp_size) == word_size) {
|
||||
C_cal((int)(tp->tp_size) == (int)word_size
|
||||
? "rmi"
|
||||
: "rmil");
|
||||
}
|
||||
C_asp(2*tp->tp_size);
|
||||
C_lfr(tp->tp_size);
|
||||
break;
|
||||
case T_POINTER:
|
||||
case T_EQUAL:
|
||||
|
|
|
@ -186,35 +186,28 @@ cstibin(expp)
|
|||
node_error(expp, "division by 0");
|
||||
return;
|
||||
}
|
||||
#if (-1)/2==0
|
||||
o1 /= o2;
|
||||
#else
|
||||
if (o1 == 0) break;
|
||||
if ((o1 < 0) != (o2 < 0)) {
|
||||
o1 = o1/o2 + 1;
|
||||
if (o1 < 0) o1 = -o1;
|
||||
else o2 = -o2;
|
||||
o1 = -((o1+o2-1)/o2);
|
||||
}
|
||||
else {
|
||||
o1 /= o2;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
if (o2 == 0) {
|
||||
node_error(expp, "modulo by 0");
|
||||
return;
|
||||
}
|
||||
#if (-1)/2==0
|
||||
o1 %= o2;
|
||||
#else
|
||||
if (o1 == 0) break;
|
||||
if ((o1 < 0) != (o2 < 0)) {
|
||||
o1 -= (o1 / o2 + 1) * o2;
|
||||
if (o1 < 0) o1 = -o1;
|
||||
else o2 = -o2;
|
||||
o1 = ((o1+o2-1)/o2) * o2 - o1;
|
||||
}
|
||||
else {
|
||||
o1 %= o2;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case '+':
|
||||
|
|
|
@ -19,6 +19,7 @@ ArraySort.mod
|
|||
catch.c
|
||||
Traps.mod
|
||||
XXTermcap.c
|
||||
dvi.c
|
||||
Arguments.c
|
||||
LtoUset.e
|
||||
StrAss.c
|
||||
|
|
68
lang/m2/libm2/dvi.c
Normal file
68
lang/m2/libm2/dvi.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
(c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
|
||||
/*
|
||||
Module: implementation of DIV and MOD
|
||||
Author: Ceriel J.H. Jacobs
|
||||
Version: $Header$
|
||||
Reason: We cannot use DVI and RMI, because DVI rounds towards 0
|
||||
and Modula-2 requires truncation
|
||||
*/
|
||||
|
||||
#include <em_abs.h>
|
||||
|
||||
int
|
||||
dvi(j,i)
|
||||
int j,i;
|
||||
{
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if ((i < 0) != (j < 0)) {
|
||||
if (i < 0) i = -i;
|
||||
else j = -j;
|
||||
return -((i+j-1)/j);
|
||||
}
|
||||
else return i/j;
|
||||
}
|
||||
|
||||
long
|
||||
dvil(j,i)
|
||||
long j,i;
|
||||
{
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if ((i < 0) != (j < 0)) {
|
||||
if (i < 0) i = -i;
|
||||
else j = -j;
|
||||
return -((i+j-1)/j);
|
||||
}
|
||||
else return i/j;
|
||||
}
|
||||
|
||||
int
|
||||
rmi(j,i)
|
||||
int j,i;
|
||||
{
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if (i == 0) return 0;
|
||||
if ((i < 0) != (j < 0)) {
|
||||
if (i < 0) i = -i;
|
||||
else j = -j;
|
||||
return j*((i+j-1)/j)-i;
|
||||
}
|
||||
else return i%j;
|
||||
}
|
||||
|
||||
long
|
||||
rmil(j,i)
|
||||
long j,i;
|
||||
{
|
||||
if (j == 0) TRP(EIDIVZ);
|
||||
if (i == 0) return 0L;
|
||||
if ((i < 0) != (j < 0)) {
|
||||
if (i < 0) i = -i;
|
||||
else j = -j;
|
||||
return j*((i+j-1)/j)-i;
|
||||
}
|
||||
else return i%j;
|
||||
}
|
Loading…
Reference in a new issue