Fastcall16 + variable # of arguments = problem?

Discussion and support of the compiler from ImageCraft for the M8C.

Moderator: richard@imagecraft.com

Fastcall16 + variable # of arguments = problem?

Postby nan358 » Fri Mar 01, 2013 5:10 am

Hi,

While trying to find out exact implementation of fastcall16 calling convention, I found a case which yields a seemingly problematic assembly code generation.

Suppose I'm trying to write a printf function in assembly, MyPrintf1 and MyPrintf2. MyPrintf1 uses standard calling convention, and MyPrintf2 uses fastcall16 calling convention.

Here's a sample source code fastcall16.c which calls MyPrintf1 and MyPrintf2:
Code: Select all
int MyPrintf1(const char *szFormat, ...);

void test1_1(void)
{
   MyPrintf1("string");
}

void test1_2(void)
{
   MyPrintf1("%d", 12);
}


#pragma fastcall16 MyPrintf1
int MyPrintf2(const char *szFormat, ...);

void test2_1(void)
{
   MyPrintf2("string");
}

void test2_2(void)
{
   MyPrintf2("%d", 12);
}


The above code compiles like this (sorry a bit lengthy):
Code: Select all
                        .module fastcall16test.c
                        .area text(rom, con, rel)
 0000                   .dbfile ./fastcall16test.c
 0000                   .dbfile C:\Users\ADMINI~1\DOCUME~1\PSOCDE~1.3PR\FASTCA~1\FASTCA~1\fastcall16test.c
 0000                   .dbfunc e test1_1 _test1_1 fV
 0000           _test1_1::
 0000                   .dbline -1
 0000                   .dbline 5
 0000           ;
 0000           ; int MyPrintf1(const char *szFormat, ...);
 0000           ;
 0000           ; void test1_1(void)
 0000           ; {
 0000                   .dbline 6
 0000           ;       MyPrintf1("string");
 0000 5003              mov A,>L2               ; ***
 0002 08                push A                  ; *** MSB of 1st argument on stack
 0003 5003              mov A,<L2               ; ***
 0005 08                push A                  ; *** LSB of 1st argument on stack
 0006 7C0000            xcall _MyPrintf1        ; *** Call _MyPrintf1
 0009 38FE              add SP,-2               ; *** Restore stack pointer
 000B                   .dbline -2
 000B           L1:
 000B                   .dbline 0 ; func end
 000B 7F                ret
 000C                   .dbend
 000C                   .dbfunc e test1_2 _test1_2 fV
 000C           _test1_2::
 000C                   .dbline -1
 000C                   .dbline 10
 000C           ; }
 000C           ;
 000C           ; void test1_2(void)
 000C           ; {
 000C                   .dbline 11
 000C           ;       MyPrintf1("%d", 12);
 000C 5000              mov A,0                 ; ***
 000E 08                push A                  ; *** MSB of 2nd argument on stack
 000F 500C              mov A,12                ; ***
 0011 08                push A                  ; *** LSB of 2nd argument on stack
 0012 5000              mov A,>L4               ; ***
 0014 08                push A                  ; *** MSB of 1st argument on stack
 0015 5000              mov A,<L4               ; ***
 0017 08                push A                  ; *** LSB of 1st argument on stack
 0018 7C0000            xcall _MyPrintf1        ; *** Call _MyPrintf1
 001B 38FC              add SP,-4               ; *** Restore stack pointer
 001D                   .dbline -2
 001D           L3:
 001D                   .dbline 0 ; func end
 001D 7F                ret
 001E                   .dbend
 001E                   .dbfunc e test2_1 _test2_1 fV
 001E           _test2_1::
 001E                   .dbline -1
 001E                   .dbline 19
 001E           ; }
 001E           ;
 001E           ;
 001E           ; #pragma fastcall16 MyPrintf2
 001E           ; int MyPrintf2(const char *szFormat, ...);
 001E           ;
 001E           ; void test2_1(void)
 001E           ; {
 001E                   .dbline 20
 001E           ;       MyPrintf2("string");
 001E 10                push X
 001F 5003              mov A,>L2               ; ***
 0021 08                push A                  ; ***
 0022 5003              mov A,<L2               ; ***
 0024 5C                mov X,A                 ; *** LSB of 1st argument in register
 0025 18                pop A                   ; *** MSB of 1st argument in register
 0026 7C0000            xcall _MyPrintf2        ; *** Call _MyPrintf2
 0029 20                pop X
 002A                   .dbline -2
 002A           L5:
 002A                   .dbline 0 ; func end
 002A 7F                ret
 002B                   .dbend
 002B                   .dbfunc e test2_2 _test2_2 fV
 002B           _test2_2::
 002B                   .dbline -1
 002B                   .dbline 24
 002B           ; }
 002B           ;
 002B           ; void test2_2(void)
 002B           ; {
 002B                   .dbline 25
 002B           ;       MyPrintf2("%d", 12);
 002B 10                push X
 002C 5000              mov A,0                 ; ***
 002E 08                push A                  ; *** MSB of 2nd argument on stack
 002F 500C              mov A,12                ; ***
 0031 08                push A                  ; *** LSB of 2nd argument on stack
 0032 5000              mov A,>L4               ; ***
 0034 08                push A                  ; *** MSB of 1st argument on stack
 0035 5000              mov A,<L4               ; ***
 0037 08                push A                  ; *** LSB of 1st argument on stack
 0038 7C0000            xcall _MyPrintf2        ; *** Call _MyPrintf2
 003B 38FC              add SP,-4               ; *** Restore stack pointer
 003D 20                pop X
 003E                   .dbline -2
 003E           L6:
 003E                   .dbline 0 ; func end
 003E 7F                ret
 003F                   .dbend
                        .area lit(rom, con, rel, lit)
 0000           L4:
 0000 256400            .byte 37,'d,0
 0003           L2:
 0003 737472696E6700    .byte 's,'t,'r,'i,'n,'g,0


Assembly code generated for calling MyPrintf1 look quite straight-forward, but code for MyPrintf2 look odd.
When calling MyPrintf2 with 1 argument, the argument is passed in registers. However, when calling it with 2 arguments, they are passed on stack.
It doesn't seem possible to implement MyPrintf2 which can be called two way.

Compiler output message with verbose option is as follows, FYI:
Code: Select all
Compiling...
psocmakemake.exe fastcall16test -oproject.mk
creating project.mk
iccm8c.exe -g -e -c -v -Wf-Osize   -IC:/PROGRA~1/Cypress/PSOCDE~1/5.3/Common/CY110F~1/tools/include -I./lib -I./std -I. -IC:/PROGRA~1/Cypress/PSOCDE~1/5.3/Common/CY110F~1/tools/include/CY8C27~1   -o obj/fastcall16test.o ./fastcall16test.c
Copyright (C) 1994 - 2011 ImageCraft Creations Inc.
ImageCraft, 2625 Middlefield Rd #685, Palo Alto, CA 94306
info@imagecraft.com, phone (650) 493-9326 FAX (866) 889-4834
http://www.imagecraft.com
lcc source code (C) 1995, by David R. Hanson and AT&T. Reproduced by permission
Version 7.05.00.
C:\PROGRA~1\Cypress\PSOCDE~1\5.3\Common\CY110F~1\tools\icppw.exe -D_M8C -D__IMAGECRAFT__ -e -IC:/PROGRA~1/Cypress/PSOCDE~1/5.3/Common/CY110F~1/tools/include -I./lib -I./std -I. -IC:/PROGRA~1/Cypress/PSOCDE~1/5.3/Common/CY110F~1/tools/include/CY8C27~1 -IC:\PROGRA~1\Cypress\PSOCDE~1\5.3\Common\CY110F~1\include ./fastcall16test.c fastcall16test.i
C:\PROGRA~1\Cypress\PSOCDE~1\5.3\Common\CY110F~1\tools\iccomm8c.exe -g -e -Osize -l./fastcall16test.c fastcall16test.i fastcall16test.s
C:\PROGRA~1\Cypress\PSOCDE~1\5.3\Common\CY110F~1\tools\iasm8c.exe -o obj/fastcall16test.o fastcall16test.s
rm fastcall16test.s fastcall16test.i
fastcall16test.o - 0 error(s) 0 warning(s)  21:56:07


Regards,
Nobu
nan358
The Big Cheese
The Big Cheese
 
Posts: 728
Joined: Mon Jul 02, 2007 8:12 am

Return to “%s” ImageCraft ICCv7 for M8C Compiler

Who is online

Users browsing this forum: No registered users and 1 guest

cron