<< Click to Display Table of Contents >> Inline Assembly Macros |
It is useful at times to gang together a set of inline assembly instructions into a macro - this technique can be particularly useful for making calls to inline assembly functions. Here is an example from NXP Set 4:
#define MC_RIPPLE_ELIM(u_ab, u_dc_bus, inv_mod_idx) \
#asm(ram p <- u_ab.) \
#asm(alu d = p; ram p <- inv_mod_idx.) \
#asm(call mc_ripple_elim, no_flush.) \
#asm(alu a = p; ram p <- u_dc_bus.) \
#asm(alu p = a; ram p -> u_ab.)
Under ANSI/ISO C rules, within a function-like macro the '#' token acts as a stringification operator - it must be followed by a parameter and it turns that parameter into a string constant. So the above is actually invalid C code from a C preprocessing perspective. To simplify things, when ETEC compiles code it passes the source through the C preprocessor in ETPUC mode, which allows the special keywords #asm and #endasm to pass without issue. Additionally, the ETEC compiler processes the #asm, #endasm and #asm() directives regardless of whether they are the first text on a source line or not. Thus, the macro above could also be written as:
#define MC_RIPPLE_ELIM(u_ab, u_dc_bus, inv_mod_idx) \
#asm \
ram p <- u_ab. \
alu d = p; ram p <- inv_mod_idx. \
call mc_ripple_elim, no_flush. \
alu a = p; ram p <- u_dc_bus. \
alu p = a; ram p -> u_ab. \
#endasm
Although not necessary, to write such macros in an ANSI/ISO compatible way, an extra level of mis-direction is required:
#define hash_asm #asm
#define hash_endasm #endasm
#define MC_RIPPLE_ELIM(u_ab, u_dc_bus, inv_mod_idx) \
hash_asm \
ram p <- u_ab. \
alu d = p; ram p <- inv_mod_idx. \
call mc_ripple_elim, no_flush. \
alu a = p; ram p <- u_dc_bus. \
alu p = a; ram p -> u_ab. \
hash_endasm