SH-3 Examples

Provides examples of how to write prolog code of an SH-3 microprocessor.

  • Specify a naked function

    The compiler does not generate any prolog or epilog code for naked functions. If you need to work with a function such as this, specify the prolog and epilog code within __asm statements.

    For each such inline prolog, use the .prolog directive to mark the end of the prolog code. In this way, you can support stack trace-back walks through a routine during debugging and exception processing.

    The following example shows how to use the inline assembly language to specify code for a naked function.

    #include <stdio.h>
    
    void __asm(const char *, ...);
    _muls();
    _adds();
    
    // Compute (a * (X * X)) + (b * X) + c in single precision
    // floating point and return the result
    __declspec(naked) float quadratic(float X, float a, float b, float c) {
    
    __asm(
      "sts.l  PR,@-SP    ; save return address on stack\n"
      "mov.l  R4,@(4,SP)  ; save X on stack\n"
      "mov.l  R5,@(8,SP)  ; save a on stack\n"
      "mov.l  R6,@(12,SP)  ; save b on stack\n"
      "mov.l  R7,@(16,SP)  ; save c on stack\n"
      "add  #-12,SP    ; allocate local stack frame\n"
      ".prolog       ; add a prolog marker\n"
      );
    __asm(
      "mov.l  R4,@(4,SP)  ; save address of multiply routine\n"
      "mov.l  R5,@(8,SP)  ; save address of add routine\n"
      "mov  R4,R5      ; set up call to multiply routine\n"
      "mov.l  @(16,SP),R4  ; get X\n"
      "jsr    @R5      ; compute a * X\n"
      "mov.l  @(20,SP),R5  ; delay slot - get a\n"
      "mov  R0,R4      ; get a * X\n"
      "mov.l  @(8,SP),R0   ; get address of add routine\n"
      "jsr  @R0        ; compute a * X + b\n"
      "mov.l  @(24,SP),R5  ; delay slot - get b\n"
      "mov  R0,R4      ; get a * X + b\n"
      "mov.l  @(4,SP),R0   ; get address of mult routine\n"
      "jsr  @R0        ; compute (a * X + b) * X\n"
      "mov.l  @(16,SP),R5  ; delay slot - get X\n"
      "mov  R0,R4      ; get (a * X + b) * X\n"
      "mov.l  @(8,SP),R0   ; get address of add routine\n"
      "jsr  @R0        ; compute ((a * X + b) * X) + c\n"
      "mov.l  @(28,SP),R5  ; delay slot - get c\n"
      "mov.l  R0,@(0,SP)   ; save result on stack\n"
      ,_muls
      ,_adds
      );
    
    __asm(
      "mov.l  @(0,SP),R0   ; recover result\n"
      "mov  SP,  R2      ; save SP\n"
      "add  #12,  R2      ; R2 points to RSA base\n"
      "lds.l  @R2+,PR     ; pop return address from stack\n"
      "rts          ; return\n"
      "mov  R2,  SP      ; delay slot - restore stack pointer"
      );
    }
    
    void main ()
    {
      float f, x, a, b, c;
      x = 1.0f;
      a = 2.0f;
      b = 3.0f;
      c = 4.0f;
      f = quadratic(x, a, b, c);
    
      printf ("f = %f\n", f);
    }
    
  • Access double parameters from integer registers

    The following example shows how to access double parameters from integer registers and local argument stack space using inline assembly.

    #include <stdio.h>
    #include <malloc.h>
    void __asm(const char *, ...);
    _addd ();
    // Compute x+y+z --> result
    double add_trig(double x, double y, double z)
    {
      double result;
      void * temp_stk_space = _alloca(32)  ; // Reserve temp space in stack
      __asm("mov.l    @(32,sp), r0  ; get pointer to temp stack space \n"
        "mov.l  r4,  @(16,r0)  ; save lw-part of x on stack \n"
        "mov.l  r5,  @(20,r0)  ; save hi-part of x on stack \n"
        "mov.l  r6,  @(24,r0)  ; save lw-part of y on stack \n"
        "mov.l  r7,  @(28,r0)  ; save hi-part of y on stack \n"
        "mov.l  @(32,sp), r5  ; get pointer to temp stack space \n"
        "mov    r5,  r6    ; get pointer to temp stack space in r6 \n"
        "add    #24,  r6    ; pass pointer to y in r6 \n"
        "mov    r5,  r4    ; get pointer to temp stack space in r4 \n"
        "add    #8,  r4    ; pass pointer to temp stack space for a+b               ; \n" 
        "mov.l  @(28, sp),r0  ; get address of add routine\n"
        "jsr    @r0      ; compute x+y\n"
        "add    #16, r5    ; pass pointer to x in r5 \n" 
        "mov.l  @(32,sp), r5  ; get pointer to temp stack space \n"
        "mov    #16, r6    ; load offset of z on stack \n"
        "add    sp, r6    ; pass pointer to z in r6 \n"
        "mov    r5, r4    ; pass pointer to tmp stack space for                 ; a+b+z\n"
        "mov.l  @(28, sp),r0  ; get address of add routine \n"
        "jsr    @r0      ; compute x+y+z \n"
        "add    #8,  r5    ; pass pointer to a+b in r5 \n"
        "mov.l  @(32,sp), r5  ; get pointer to a+b+z \n"
        "mov.l  @r5+,r1    ; get hi-part of result \n"
        "mov.l  @r5,  r2    ; get lw-part of result \n"
        "mov.l  @(24,sp), r0  ; load result address \n"
        "add    #4, r0    ; increment result addr by 4 \n"
        "mov.l  r2, @r0    ; store hi-part into result addr\n"
        "mov.l  r1, @-r0    ; store lw-part into result addr\n",
        x,          // passed in r4 and r5 
        y,          // passed in r6 and r7
        z,          // passed in @(16,sp) and @(20,sp)
        &result,        // passed in @(24,sp) 
        _addd,        // passed in @(28,sp)
        temp_stk_space);    // passed in @(32,sp)
      return result;
    }
    
    void main()
    {
      double  retval = add_trig(1.0, 2.0,3.0);
      printf("%g\n", retval);
    }
    
  • Access floating-point parameters from integer registers

    The following example shows how to access float parameters from integer registers and local argument stack space using inline assembly:

    #include <stdio.h>
    #include <malloc.h>
    
    void __asm(const char *, ...);
    
    _adds ();
    _dtos ();
    
    //
    // Compute x+y+z --> result
    //
    double add_trig(float x, float y, float z)
    {
      float result;
    
      void * temp_stk_space = _alloca(20); // Reserve temp space in stack
    
      __asm("mov.l    @(36,sp), r0 ; get pointer to temp stack space \n"
        "mov.l  r12,   @r0   ; save permanent register r12 on stack \n" 
        "mov.l  r4,  @(4,r0)    ; save lw-part of x on stack \n" 
        "mov.l  r5,  @(8,r0)    ; save hi-part of x on stack \n"
        "mov.l  r6,  @(12,r0)    ;save lw-part of y on stack \n"
        "mov.l  r7,  @(16,r0)    ;save hi-part of y on stack \n"
        "mov.l  @(36, sp), r4  ; get pointer to temp stack space \n"
        "mov.l  @(32, sp), r0  ; get address of dtos routine \n"
        "jsr    @r0      ; convert x double to single precision \n"
        "add    #4,  r4      ; pass pointer to x in r4 \n"
        "mov    r0,  r12      ; save single precision x in r12 \n"
        "mov.l  @(36,sp), r4  ; get pointer to temp stack space \n"
        "mov.l  @(32, sp), r0  ; get address of dtos routine \n"
        "jsr    @r0      ; convert y double to single precision \n"
        "add    #12,  r4      ; pass pointer to y in r4 \n"
        "mov    r0,  r4      ; get single precision y \n"
        "mov.l  @(28, sp), r0  ; get address of add routine \n"
        "jsr    @r0        ; compute x + y \n"
        "mov    r12,  r5      ; get single precision x \n"
        "mov    r0,  r12      ; save x+y in r12 \n"
        "mov    #16,  r4      ; load offset of z on stack \n"
        "mov.l  @(32, sp), r0  ; get address of dtos routine \n"     
        "jsr    @r0      ; convert z double to single precision \n"
        "add    sp,  r4      ; pass pointer to z in r4 \n"
        "mov    r0,  r4      ; get single precision z \n"
        "mov.l  @(28, sp), r0  ; get address of add routine \n"
        "jsr    @r0        ; compute x + y + z \n"
        "mov    r12,  r5      ; get x+y \n"
        "mov.l  @(24,sp), r1   ; load result address \n"
        "mov.l  r0,  @r1      ; store r0 into result addr \n" 
        "mov.l  @(36,sp), r0   ; get pointer to temp stack space\n"
        "mov.l  @r0, r12; restore permanent register r12 from stack \n",
        x,            // passed in r4 and r5 
        y,            // passed in r6 and r7
        z,            // passed in @(16,sp) and @(20,sp)
        &result,          // passed in @(24,sp) 
        _adds,          // passed in @(28,sp)
        _dtos,          // passed in @(32,sp)
        temp_stk_space);      // passed in @(36,sp)
    
      return result;
    }
    
    void main()
    {
      float  retval = add_trig(1.0f, 2.0f,3.0f);
      printf("%f\n", retval);
    }
    

See Also

SHx Inline Assembly Samples | SH-4 Examples

 Last updated on Thursday, April 08, 2004

© 1992-2003 Microsoft Corporation. All rights reserved.