This cc65 version has some extensions to the ISO C standard.
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 can
therefore be disabled with the
--standard
command line option.
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 ("txa"), \
asm ("ldx #$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 document for examples
on how to use this feature.
register
, and the size and compiler settings
do allow the compiler actually to 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.