SH-4 Mode Bits

The semantics of several instructions of the SH-4 are subject to the control of mode bits in the floating-point control register (FPSCR). These bits include FR, PR, and SZ. These bits dictate which floating-point register bank is currently active and the size of floating point register operands - 32 or 64 bits.

The SH-4 specification dictates specific rules about the state of these mode bits on entry to and exit from function calls. Inline assembly code, which modifies the values of these bits, must be careful to avoid the violation of these rules and should follow these rules as if they in fact were separate function calls.

Specifically, before control leaves the scope of an inline assembly sequence, the state of the mode bits must be returned to their value on entry to the scope. Failure to maintain consistency in these mode bits may result in undefined and unanticipated program failures.

The following code fragment illustrates how to change and restore the PR bit in the FPSCR control register.

// Compute x+y+z --> result
float add_trig(float x, float y, float z)
{
  float result;
  __asm("lds r4,    fpul  ;   load lw-part of x to fpul \n"
     "fsts   fpul,  fr5   ; copy lw-part of x to fr5 \n"
     "lds    r5,    fpul  ; load hi-part of x to fpul \n"
     "fsts   fpul,  fr4   ; copy hi-part of x to fr4 \n" 
     "lds    r6,    fpul  ; load lw-part of y to fpul \n"
     "fsts   fpul,  fr7   ; copy lw-part of y to fr7 \n"
     "lds    r7,    fpul  ; load hi-part of y to fpul \n"
     "fsts   fpul,  fr6   ; copy hi-part of y to fr6 \n"
     "mov.l  @(16,sp),r0  ; load lw-part of z to r0 \n"
     "lds    r0,    fpul  ; \n"
     "fsts   fpul,  fr9   ; copy lw-part of z to fr9 \n"
     "mov.l  @(20,sp),r0   ; load hi-part of z to r0 \n"
     "lds    r0,     fpul  ; \n"
     "fsts   fpul,   fr8   ; copy hi-part of z to fr8 \n"
     "mov    #8,     r0    ; prepare to mask the pr bit \n"
     "shll16 r0      ; \n"
     "sts    fpscr,  r1    ; \n"
     "xor    r0,     r1    ; toggle pr bit \n"
     "lds    r1,     fpscr ; turn-on pr bit \n"
     "fcnvds dr4,    fpul  ; convert x double to single precision\n"
     "fsts   fpul,   fr4   ; store float x in fr4\n"
     "fcnvds dr6,    fpul  ; convert y double to single precision\n"
     "fsts   fpul,   fr5   ; store float y in fr5\n"
     "fcnvds dr8,    fpul  ; convert z double to single precision\n"
     "fsts   fpul,   fr6   ; store float z in fr6\n"
     "xor    r0,     r1    ; toggle pr bit \n"
     "lds    r1,     fpscr ; turn-off pr bit\n" 
     "fadd   fr4,    fr5   ; compute x+y\n"
     "fadd   fr5,    fr6   ; compute x+y+z \n"
     "mov.l  @(24,sp), r0  ; load result address\n"
     "fmov.s fr6, @r0      ; store fr6 into result addr\n",
  x,   // promoted to double and passed in r4 and r5 
  y,   // promoted to double and passed in r6 and r7
  z,   // promoted to double and passed in @(16,sp) 
      // and @(20,sp)
  &result);  // pointer to result passed in @(24,sp) 
  return result;
}
void main()
{
  float  retval = add_trig(1.0f, 2.0f,3.0f);
  printf("%g\n", retval);
}

See Also

Elements of the SHx __asm Block | The __asm Keyword in SHx Inline Assembly | __asm Restrictions in SHx Inline Assembly | Constants in SHx Inline Assembly | Symbols and Labels in SHx Inline Assembly | SHx Inline Assembly Parameters | Branching in SHx Inline Assembly

 Last updated on Thursday, April 08, 2004

© 1992-2003 Microsoft Corporation. All rights reserved.