[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