ccg
's behaviourSeveral aspects of the runtime assembler and preprocessor can be customised for a particular client program. This is occasionally useful and not difficult for assembler ``wizards'' to do, but it does require a certain familiarity with the preprocessor and runtime assemblers. If in doubt, seek professional help.
The runtime assemblers share a common framework in which several actions can be changed from their defaults by the client program. The customisable operations are:
#[
'', ``#{
'',
``]#
'' and ``}#
''.
.org
'' pseudo-op.
name:
''.
Customisation is achieved by defining one or more macros before
using the #cpu
directive. The macros concerned, and their
default definitions, are as follows:
#[
''#define _ASM_APP_1 { asm_pass= 0; {
]#
''#define _ASM_NOAPP_1 } asm_hwm= asm_pc; }
#{
''#define _ASM_APP_2 { for (asm_pass= 1; asm_pass < 3; ++asm_pass) {
}#
''#define _ASM_NOAPP_2 if (asm_pass==1) asm_hwm= asm_pc; \ else if (asm_hwm!=asm_pc) ASMFAIL("phase error"); } }
.org O
''#define _ASM_ORG(O) (asm_pc= (O))
.label N
''#define _ASM_LBL(N) static insn *N= 0
N:
''#define _ASM_DEF(N) (N= (((asm_pass==2)&&(asm_pc!=(N))) \ ? (insn *)ASMFAIL("phase error") : asm_pc))
Several preprocessor characteristics can be altered by changing
definitions near the beginning of the source file ccg.c
and then
recompiling. The customisable definitions and their default values
are as follows:
#include
directive corresponding to the #cpu
declaration#define HEADER_PREFIX "ccg/asm-"
$
') to this list)#define LABEL_CHARS "_A-Za-z0-9"
#define ASM_1_OPEN "#[" #define ASM_1_CLOSE "]#" #define ASM_2_OPEN "#{" #define ASM_2_CLOSE "}#"
One simple but useful customisation is to implement automatic synchronisation of the instruction and data caches at the end of each dynamic assembler section. One way to achieve this is as follows:
... header files or other preambulae ... /*** customised runtime assembler actions: add automatic iflush(lwm,pc) ***/ #define _ASM_NOAPP_1 } iflush(asm_lwm, asm_pc); asm_lwm= asm_pc; } #define _ASM_NOAPP_2 if (asm_pass==1) asm_hwm= asm_pc; \ else if (asm_hwm!=asm_pc) ASMFAIL("phase error"); \ else { iflush(asm_lwm, asm_pc); asm_lwm= asm_pc; } } } #define _ASM_ORG(ADDR) if (asm_lwm != 0) iflush(asm_lwm, asm_pc); \ (asm_lwm= asm_pc= (ADDR)) #cpu nameOfTargetCPU /* the following variable must be _defined_ in only ONE program file */ extern insn *asm_lwm; /* "low water mark" for cache flush */ /*** end of customised runtime assembler actions ***/ ... program ...