[M3devel] div/mod helpers for pair of negative numbers?
Jay K
jay.krell at cornell.edu
Sat Jun 19 10:44:04 CEST 2010
Tony, I'm not going to change the release branch, but this is seemingly relevant to ARM on head:
if ((b == 'P' && a == 'P') || IS_WORD_TYPE(T)) {
EXPR_REF (-2) = m3_build2 (FLOOR_MOD_EXPR, t,
m3_cast (t, EXPR_REF (-2)),
m3_cast (t, EXPR_REF (-1)));
EXPR_POP ();
is better off as:
if ((b == a) || IS_WORD_TYPE(T)) {
EXPR_REF (-2) = m3_build2 (FLOOR_MOD_EXPR, t,
m3_cast (t, EXPR_REF (-2)),
m3_cast (t, EXPR_REF (-1)));
EXPR_POP ();
right?
That, consider..well..the historical modL function is close to that:
int64 __cdecl m3_modL
ANSI(( int64 b, int64 a))
KR((b, a) int64 b; int64 a;)
{
register int64 c;
if ((a == 0) && (b != 0)) { c = 0;
} else if (a> 0) { c = (b>= 0) ? a % b : b + 1 + (a-1) % (-b);
} else /* a < 0 */ { c = (b>= 0) ? b - 1 - (-1-a) % (b) : - ((-a) % (-b));
}
return c;
}
for a < 0 and b < 0, it returns - ((-a) % (-b));.
which isn't exactly a % b as far as I know.
But if you consider my rewritten mod64 function, which I believe I tested thoroughly:
int64
__stdcall
m3_mod64(int64 b, int64 a)
{
typedef int64 ST; /* signed type */
typedef uint64 UT; /* unsigned type */
int aneg = (a < 0);
int bneg = (b < 0);
if (aneg == bneg || a == 0 || b == 0)
return (a % b);
else
{
UT ua = (aneg ? M3_POS(UT, a) : (UT)a);
UT ub = (bneg ? M3_POS(UT, b) : (UT)b);
a = (ST)(ub - 1 - (ua + ub - 1) % ub);
return (bneg ? -a : a);
}
}
It seems 64bit floor mod doesn't work on ARM, so I'm putting back calling functions, sometimes -- only for 64bit mod on ARM.
div also if I found it is needed.
All other targets will keep using gcc's builtin support, whatever that is.
I guess I'll just have to go back and make sure there is test coverage here and compare release with head.
- Jay
More information about the M3devel
mailing list