SH-4 Inline Assembly Parameters (Windows CE 5.0)
The syntax of the __asm intrinsic call is:
__asm(string[,expression...]);
You can pass parameters to a __asm intrinsic call using the list of expressions. The compiler processes the list of expression values in exactly the same way a function call with variable arguments. The compiler treats the first expression in the list as the first argument.
Integer and Non-scalar Parameters
In most circumstances, the first four 32-bit words of integer or non-scalar arguments are passed in registers R4-R7. The remaining words are placed on the stack frame, starting at a displacement of 16 bytes from the stack pointer.
The following code example shows how to access parameters from registers and local argument stack space according to the calling standards.
__asm(
"add R4,R5 ; add first two numbers\n"
"add R5,R6 ; add third number\n"
"add R6,R7 ; add fourth number\n"
"mov.l @(16,SP), R0 ; retrieve fifth number\n"
"add R0,R7 ; add fifth number\n"
"mov.l @(20,SP), R0 ; get address of result\n"
"mov.l R7,@R0 ; save results"
,num1 // passed in R4
,num2 // passed in R5
,num3 // passed in R6
,1000 // passed in R7
,0xFFFF // passed in stack at a displacement of 16 bytes from SP
,&result // passed in stack at a displacement of 20 bytes from SP
);
Floating-point and Double Parameters
To pass a floating-point argument into a __asm block, pass the address of the argument, and then load the argument to a register within the __asm block.
Because the __asm prototype specifies a variable argument list, passing parameters of type floating-point and double is governed by the SH-4 calling standard for variable argument list.
If a function is declared to use variable argument lists, floating-point registers are unused and floating-point arguments are passed using only the integer argument registers and the stack.
In addition, the C and C++ ANSI standards require that float arguments in a variable argument list be promoted to type double. Consequently, floating point arguments are promoted to type double, and passed as word pairs in the integer registers and or on the stack.
The following code example shows how to first pass the address of float arguments to __asm call and then load the argument to a register within the __asm statement.
//
// Compute x+y+z --> result
//
float add_trig(float x, float y, float z)
{
float result;
void * temp_stk_space = _alloca(8); // Reserve temp space in stack
__asm(
"mov.l @(20,sp), r0 ; get pointer to temp stack space \n"
"mov.l r6, @r0 ; save pointer to z on stack \n"
"mov.l r7, @(4,r0) ; save pointer to result on stack \n"
"mov.l @r4, r4 ; get x \n"
"mov.l @(16, sp),r0 ; get address of add routine \n"
"jsr @r0 ; compute x+y \n"
"mov.l @r5, r5 ; get y \n"
"mov r0, r4 ; get x + y \n"
"mov.l @(20,sp), r1 ;\n"
"mov.l @(16, sp),r0 ; get address of add routine \n"
"mov.l @r1, r5 ; get pointer to z \n"
"jsr @r0 ; compute x+y+z \n"
"mov.l @r5, r5 ; get z \n"
"mov.l @(20,sp), r1 ; get pointer to temp stack space \n"
"mov.l @(4,r1), r1 ; get pointer to result \n"
"mov.l r0, @r1 ; store r0 into result addr \n",
&x, // pointer to x passed in r4
&y, // pointer to y passed in r5
&z, // pointer to z passed in r6
&result, // pointer to result passed in r7
_adds, // pointer to _adds routine passed in @(16,sp)
temp_stk_space); // pointer to temp stack space passed in // @(20,sp)
return result;
}
void main()
{
float retval = add_trig(1.0f, 2.0f,3.0f);
printf("%f\n", retval);
}
See Also
Elements of the SH-4 __asm Block
Send Feedback on this topic to the authors