08 October 2021, 17:47 | #1 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
SAS/C Fastcall-ABI (__regargs)
I'm looking for an exact specification of SAS/C's Fastcall ABI.
All I'm sure about is that the first two integer arguments are passed in d0, d1 while the first two pointers are passed in a0, a1. Function names following this ABI are preceded by an '@' instead of an '_'. Varargs functions will always pass all arguments on the stack, right? And the called function name is still _name. What about floating point arguments? Without an FPU are the first two float (single precision) arguments passed in d0,d1 (if not already occupied by integer arguments - who has priority)? And double is passed in the register pair d0/d1? Or do floating point arguments always use the stack? And with FPU? Does it use fp0 and fp1? Or also the stack? Anything else which I forgot? Passing structures? Any SAS/C expert here? |
08 October 2021, 18:13 | #2 |
Zone Friend
Join Date: May 2006
Location: France
Posts: 1,801
|
Hi PHX I was in contact with a SAS employee who know Steve Krueger, is it a question for him or someone else could answer here?
|
08 October 2021, 19:03 | #3 | |||
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
Quote:
Quote:
Quote:
The only exception are function calls to mathieeedoubXXXX, for which SAS/C seems to have extra support. Here doubles are passed correctly. (Though register allocation is broken, d1 is trashed and that is not taken care of. Had to learn this the hard way). I do not recall by heart, but it was likely fp0 and fp1 as first double arguments. I can probably provide an answer by tomorrow. Ditto, stack-based likely, but let me verify. |
|||
08 October 2021, 19:29 | #4 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
Quote:
Stack based, I recalled correctly. If you return a structure, SAS/C allocates the returned structure at a stack on the caller, and provides the address of the expected return structure as hidden argument on the stack, even for regargs. |
|
09 October 2021, 12:01 | #5 | |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
Thanks a lot! That's all I need to know!
Looks like vbcc's -fastcall option is already very compatible. So I only need some time to add all the Fastcall-ABI functions to vclib. Quote:
Certainly useful to keep in mind for the future. |
|
19 October 2021, 11:43 | #6 | |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
Quote:
This would lead to another question: Let's take the varargs function printf. It would only occur as _printf in clib, because of varargs. Does it mean this is the Standard-ABI printf-object, with references to more Standard-ABI functions? This would effectively make the linker pull in more Standard-ABI objects, which are suboptimal regarding the currently selected ABI. And, even worse, you may have Fastcall-ABI variants for the same functions in parallel (e.g. vfprintf or fputc), increasing the size of your executable. Or is there a second Standard-ABI printf in clib, which calls Fastcall-ABI functions (as long as they do not take varargs)? Then how does SAS/C differentiate between them? |
|
19 October 2021, 15:14 | #7 | |||
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
Quote:
Quote:
Quote:
This being said, I personally avoid printf() (it's rather fat anyhow). There is Printf() from dos, or go through RawDoFmt() to get the dirty work done. |
|||
19 October 2021, 18:40 | #8 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
So, apparently, the sc.lib was compiled with the option PARMS=BOTH, which creates for each module exactly the structure I described above for NewList: Two entry points per functions, one for regargs as @name, and one with stack-based arguments that takes the stack values, and puts them into the registers for the regargs function. The stack-based function is then of course _name.
To make this more precise: It's not that every function is compiled twice, but each function has two entry points, with the stack-based entry point loading the registers for the registerized entry point a couple of bits later. |
19 October 2021, 19:09 | #9 | |||
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
Quote:
Quote:
Quote:
So you may get a separate @vfprintf and _vfprintf, which is a quite complex routine. Assuming printf calls @vfprintf you will bloat your Standard-ABI program when calling vfprintf() from your own source, as the linker has to include both. Same problem for the other functions which vfprintf() calls. At least fputc(). Maybe also isdigit() and floating point arithmetics. EDIT: Just saw your new post. Still my questions/confusion remains. Last edited by phx; 19 October 2021 at 19:11. Reason: New post |
|||
20 October 2021, 19:41 | #10 | ||
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
Quote:
Quote:
The sc.lib will (likely) include both _vprintf and @vprintf, and the former contains just of a preample that picks arguments from the stack and runs into @vprintf. This does not extend the function by a lot (8 bytes or so). |
||
21 October 2021, 11:08 | #11 | |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
Quote:
I don't really like that, though. As far as I understand now, sc.lib is probably build with PARMS=both for all functions to keep them compatible with mixed ABIs. This puts Standard-ABI programs generally at a disadvantage, because of the preamble-overhead, which becomes bigger as more registers you pass. On the other hand you could argue that this overhead becomes insignificant when functions with many arguments are sufficiently complex. And internal sc.lib calls are using regargs anyway. Hmm... |
|
21 October 2021, 11:44 | #12 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,215
|
ISO C always allows the compiler to operate on an AS-IF basis, that is, if the observable behavior isn't any different, the compiler can do what it wants. In this case, it doesn't really make any difference, it just creates overhead by moving bytes around. Note that most sc.lib functions do not create this overhead as it requires more than two ints or more than two pointers to run into this issue.
Well, two arguments: First, the standard ABI is already not ideal as registerized calls are more efficient anyhow, so the standard ABI should be better deprecated. The other argument would be that you could always supply call-convention specific libraries (i.e. have a sc_rr.lib and a sc_std.lib) if that would be necessary, just that SAS/C did not follow this route. So it's not exactly a compiler choice, but a compiler-deployment choice. |
21 October 2021, 15:46 | #13 | |||
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
Quote:
Quote:
Quote:
|
|||
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
AROS ABI-v1 68k AMiGA Version | AMIGASYSTEM | News | 12 | 20 June 2019 01:29 |
Labykill (Fastcall BBS Game) | Darksun777 | request.Apps | 1 | 12 February 2018 11:20 |
SAS C 6.58 (again) | nyteshade | request.Other | 2 | 15 December 2016 17:18 |
[Found: Death Trap] Game with protagonist called Abi? | Justice | Looking for a game name ? | 2 | 08 February 2010 22:15 |
Sas C V 6.0 | Jherek Carnelia | request.Apps | 1 | 20 March 2007 10:13 |
|
|