This cc65 version has some extensions to the ISO C standard.
-A.
asm (<string literal>[, optional parameters]) ;
or
__asm__ (<string literal>[, optional parameters]) ;
The first form is in the user namespace and is disabled if the -A
switch is given.
There is a whole section covering inline assembler statements,
see there.
<return type> fastcall <function name> (<parameter list>)
or
<return type> __fastcall__ <function name> (<parameter list>)
An example would be
void __fastcall__ f (unsigned char c)
The first form of the fastcall keyword is in the user namespace and is
therefore disabled in strict ANSI mode.
For functions declared as fastcall, the rightmost parameter is not
pushed on the stack but left in the primary register when the function
is called. This will reduce the cost when calling assembler functions
significantly, especially when the function itself is rather small.
__AX__ and __EAX__.
Both refer to the primary register that is used by the compiler to
evaluate expressions or return function results. __AX__ is of
type unsigned int and __EAX__ of type long unsigned int
respectively. The pseudo variables may be used as lvalue and rvalue as
every other variable. They are most useful together with short
sequences of assembler code. For example, the macro
#define hi(x) (__AX__=(x),asm("\ttxa\n\tldx\t#$00",__AX__)
will give the high byte of any unsigned value.
__func__ gives the name of the
current function as a string. Outside of functions, __func__ is
undefined.
Example:
#define PRINT_DEBUG(s) printf ("%s: %s\n", __func__, s);
The macro will print the name of the current function plus a given
string.
void variables. This may be
used to create variable structures that are more compatible with
interfaces written for assembler languages. Here is an example:
void GCmd = { (char)3, (unsigned)0x2000, (unsigned)0x3000 };
This will be translated as follows:
_GCmd:
.byte 3
.word $2000
.word $3000
Since the variable is of type void you may not use it as is.
However, taking the address of the variable results in a void*
which may be passed to any function expecting a pointer.
See the
GEOS library for examples on
how to use this feature.
register and the size and compiler settings
do allow the compiler to actually place the struct into the
register bank in the zero page.sizeof
operator returns the struct size with the flexible array member having
size zero, even if it is initialized.