File ffcall/trampoline/PORTING from the latest check-in


The list of CPUs and platforms TRAMPOLINE has been ported to can be found
at the top of file trampoline.c.

To port TRAMPOLINE to a new platform, three issues may have to be resolved:
A. a new CPU - how to build the trampoline?
B. a new OS - how to make code in malloc'ed memory executable?
C. a new CPU or OS - how to flush the instruction cache?


A. a new CPU - how to build the trampoline?

   The trampoline is a short sequence of machine instructions which puts
   the constant <data> into <variable>, then jumps to <address>. The only
   registers that are allowed to be modified are call-used-registers. No
   stack manipulations are allowed since the trampoline has to pass its
   arguments along to the function at <address>.

   1. To find out which instructions are available for "move"/"store" and
      "jump", compile proto.c for your CPU:

          make -f Makefile.devel proto-${CPU}.s
      or
          gcc -O2 -fomit-frame-pointer -S proto.c -o proto-${CPU}.s

   2. Write down the instructions for the trampoline in a file tramp-${CPU}.s,
      using constants for <data>, <variable>, <address>. Assemble it:

          gcc -c tramp-${CPU}.s

      Verify that the jump actually goes to <address>. (Beware: Some CPUs have
      program-counter relative jumps.)

          gdb tramp-${CPU}.o
          disassemble tramp

   3. Take a hex dump of tramp-${CPU}.o

          hexdump -e '"%06.6_ax " 16/1 " %02X" "\n"' < tramp-${CPU}.o
      or
          od -tx1 -Ax < tramp-${CPU}.o
      or
          od -x +x < tramp-${CPU}.o

      Look out for the magic numbers you used for <data>, <variable> and
      <address>.

   4. Write the code which builds up a trampoline in memory, in trampoline.c.

   5. Try it:

          make
          make check1

   6. Write the is_tramp() macro and the tramp_xxx() accessor macros
      in trampoline.c.

   7. Try it:

          make
          make check


B. a new OS - how to make code in malloc'ed memory executable?

   `configure' will find out whether code stored in malloc'ed memory is
   executable, or whether virtual memory protections have to be set in order
   to allow this. (The test is pretty simple: it copies a small function
   to malloc'ed memory and tries to executed it. The test could also fail
   because the compiler produced non-position-independent code or because
   of alignment issues.)

   To set virtual memory protections on a page of memory, your system should
   provide the mprotect() and getpagesize() functions. If it does not, find
   a substitute.


C. a new CPU or OS - how to flush the instruction cache?

   CPUs which have separate data and instruction caches need to flush
   (part of) the instruction cache when alloc_trampoline() is called.
   (There may have been an old trampoline at the same location, and the
   instruction cache is not updated when the new trampoline is built.
   The effect can be that when the new trampoline is called, the old one
   will still be executed.)

   To flush the instruction cache, some CPUs have special instruction which
   can be put into gcc "asm" statements. On some CPUs these instructions are
   privileged, you therefore need to call some system or library function.
   On other CPUs, the only way to flush the instruction cache is to execute
   a long sequence of "nop" or "jump" instructions. This is hairy.


When you are done with porting to a new platform, or even if TRAMPOLINE
passes the "make check" out of the box without modifications, please report
your results to the author of TRAMPOLINE, for inclusion in the next release.