Next: Floating-point macros, Previous: Standard macros, Up: Porting GNU lightning
There is actually a single function that you must define
in the funcs-suffix.h file, that is, jit_flush_code.
As explained in Generating code at run-time, its purpose is to flush part of the processor's
instruction cache (usually the part of memory that contains the
generated code), avoiding the processor executing bogus data
that it happens to find in the cache. The jit_flush_code
function takes the first and the last address to flush.
On many processors (for example, the x86 and the all the processors in the 68k family up to the 68030), it is not even necessary to flush the cache. In this case, the contents of the file will simply be
#ifndef __lightning_funcs_h
#define __lightning_funcs_h
#define jit_flush_code(dest, end)
#endif /* __lightning_core_h */
On other processors, flushing the cache is necessary for proper behavior of the program; in this case, the file will contain a proper definition of the function. However, we must make yet another distinction.
On some processors, flushing the cache is obtained through a call
to the operating system or to the C run-time library. In this case,
the definition of jit_flush_code will be very simple: two
examples are the Alpha and the 68040. For the Alpha the code will
be:
#define jit_flush_code(dest, end) \
__asm__ __volatile__("call_pal 0x86");
and, for the Motorola
#define jit_flush_code(start, end) \
__clear_cache((start), (end))
As you can see, the Alpha does not even need to pass the start and
end address to the function. It is good practice to protect usage of
the GNU CC-specific __asm__ directive by relying
on the preprocessor. For example:
#if !defined(__GNUC__) && !defined(__GNUG__)
#error Go get GNU C, I do not know how to flush the cache
#error with this compiler.
#else
#define jit_flush_code(dest, end) \
__asm__ __volatile__("call_pal 0x86");
#endif
gnu lightning's configuration process tries to compile a dummy file that
includes lightning.h, and gives a warning if there are problem
with the compiler that is installed on the system.
In more complex cases, you'll need to write a full-fledged function.
Don't forget to make it static, otherwise you'll have problems
linking programs that include lightning.h multiple times. An
example, taken from the funcs-ppc.h file, is:
#ifndef __lightning_funcs_h
#define __lightning_funcs_h
#if !defined(__GNUC__) && !defined(__GNUG__)
#error Go get GNU C, I do not know how to flush the cache
#error with this compiler.
#else
static void
jit_flush_code(start, end)
void *start;
void *end;
{
register char *dest = start;
for (; dest <= end; dest += SIZEOF_CHAR_P)
__asm__ __volatile__
("dcbst 0,%0; sync; icbi 0,%0; isync"::"r"(dest));
}
#endif
#endif /* __lightning_funcs_h */
The funcs-suffix.h file is also the right place to put
helper functions that do complex tasks for the
core-suffix.h file. For example, the PowerPC assembler
defines jit_prolog as a function and puts it in that file (for more
information, see Implementing the ABI). Take special care when
defining such a function, as explained in Reentrant usage of gnu lightning.