I'd like to extend the FPSCR support functions in SH's libgcc.a to
include a way for applications to change the bits that GCC doesn't
care about (exception handling, denormals, etc).  I've come up with
this routine and (after much head-banging) managed to test it on real
hardware.  The idea is that GCC gets to manage the SZ and PR bits, and
the application is free to manage the remainder of the bits, without
the two interfering with each other.

I chose the single change_fpscr function (I'm not committed to that
name) as it allows you to set the multi-bit fields in a single call
(mask the whole field, set the new value), but a two-function
set/clear pair would work too.

At this point, I would like some feedback about the API and how to
cleanly (namespace-wise) add it to libgcc.a.

static int
get_fpscr()
{
  int ret;
  asm volatile ("sts fpscr,%0" : "=r" (ret));
  return ret;
}

static void
put_fpscr(int nv)
{
  asm volatile ("lds %0,fpscr" : : "r" (nv));
}

#define FR 0x00200000
#define SZ 0x00100000
#define PR 0x00080000
#define DN 0x00040000
#define RN 0x00000003
#define RN_N 0
#define RN_Z 1

extern int __fpscr_values[2];

void
change_fpscr(int off, int on)
{
  int b = get_fpscr();
  off = ~off;
  off |=   0x00180000;
  on  &= ~ 0x00180000;
  b &= off;
  b |= on;
  put_fpscr(b);
  __fpscr_values[0] &= off;
  __fpscr_values[0] |= on;
  __fpscr_values[1] &= off;
  __fpscr_values[1] |= on;
}

Reply via email to