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.