[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5 More complex tasks in the platform-independent layer

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 section 3.4.5 Implementing the ABI). Take special care when defining such a function, as explained in Reentrant usage of GNU lightning.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

This document was generated by Alistair Turnbull on April, 12 2005 using texi2html