Initial revision
authorGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Fri, 15 Feb 1991 00:47:19 +0000 (00:47 +0000)
committerGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Fri, 15 Feb 1991 00:47:19 +0000 (00:47 +0000)
v7/src/microcode/cmpauxmd/vax.m4 [new file with mode: 0644]
v7/src/microcode/cmpintmd/vax.h [new file with mode: 0644]

diff --git a/v7/src/microcode/cmpauxmd/vax.m4 b/v7/src/microcode/cmpauxmd/vax.m4
new file mode 100644 (file)
index 0000000..fe47933
--- /dev/null
@@ -0,0 +1,280 @@
+### -*-Midas-*-
+###
+###    $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/cmpauxmd/vax.m4,v 1.1 1991/02/15 00:46:58 jinx Exp $
+###
+###    Copyright (c) 1991 Massachusetts Institute of Technology
+###
+###    This material was developed by the Scheme project at the
+###    Massachusetts Institute of Technology, Department of
+###    Electrical Engineering and Computer Science.  Permission to
+###    copy this software, to redistribute it, and to use it for any
+###    purpose is granted, subject to the following restrictions and
+###    understandings.
+###
+###    1. Any copy made of this software must include this copyright
+###    notice in full.
+###
+###    2. Users of this software agree to make their best efforts (a)
+###    to return to the MIT Scheme project any improvements or
+###    extensions that they make, so that these may be included in
+###    future releases; and (b) to inform MIT of noteworthy uses of
+###    this software.
+###
+###    3. All materials developed as a consequence of the use of this
+###    software shall duly acknowledge such use, in accordance with
+###    the usual standards of acknowledging credit in academic
+###    research.
+###
+###    4. MIT has made no warrantee or representation that the
+###    operation of this software will be error-free, and MIT is
+###    under no obligation to provide any services, by way of
+###    maintenance, update, or otherwise.
+###
+###    5. In conjunction with products arising from the use of this
+###    material, there shall be no use of the name of the
+###    Massachusetts Institute of Technology nor of any adaptation
+###    thereof in any advertising, promotional, or sales literature
+###    without prior written consent from MIT in each case.
+###
+\f
+#### Vax assembly language (BSD as Syntax) part of the compiled code
+#### interface.  See cmpint.txt, cmpaux.txt, cmpint.c, cmpint-vax.h,
+#### and cmpgc.h for more documentation.
+####
+#### NOTE:
+####   Assumptions:
+####
+####   1) C uses CALLS and RET for linkage.
+####
+####   2) The C compiler divides registers into three groups:
+####   - Linkage registers, used for procedure calls and global
+####   references.  On Vax: ap, fp, sp, pc.
+####   - Super temporaries, not preserved accross procedure calls and
+####   always usable.  On the Vax this depends on the compiler:
+####   GCC and BSD PCC use r0-r5 as super temporaries.
+####   The (VMS) Vax C compiler uses r0-r1 as super temporaries.
+####   - Preserved registers saved by the callee if they are written.
+####   On the Vax: all others.
+####
+####   3) C procedures return long values in r0.
+####   Two word structures are returned in different ways:
+####   o GCC returns them in r0/r1.  Define flag GCC.
+####   o PCC returns the address of the structure (in static storage)
+####   in r0.  This is the default.
+####   o (VMS) Vax C passes the address of the destination structure
+####   as the first argument.  The other arguments are shifted right.
+####
+#### Compiled Scheme code uses the following register convention:
+####   - sp (r14) contains the Scheme stack pointer, not the C stack
+####   pointer.
+####   - fp (r13) contains the dynamic link when needed.
+####   - ap (r12) contains the Scheme free pointer.
+####   - r11 contains the Scheme datum mask.
+####   - r10 contains a pointer to the Scheme interpreter's
+####   "register" block.  This block contains the compiler's copy of
+####   MemTop, the interpreter's registers (val, env, exp, etc),
+####   temporary locations for compiled code, and the mechanism used
+####   to invoke the hooks in this file.
+####   - r9 is where Scheme compiled code returns values.
+####
+####   All other registers are available to the compiler.  A
+####   caller-saves convention is used, so the registers need not be
+####   preserved by subprocedures.
+####
+#### MAJOR NOTE: $ signifies immediate values to AS on the Vax.
+#### However, M4 also uses $ to signify macro constants,
+#### thus we use @ here to signify immediate values and a sed script
+#### is run on the output of M4 to change them to $.
+\f
+####   Utility macros and definitions
+
+ifdef(`VMS', `', `ifdef(`GCC',`',`define(PCC,1)')')
+
+ifdef(`VMS',
+      `define(HEX,`^X$1')',
+      `define(HEX,`0x$1')')
+
+
+ifdef(`VMS',
+      `define(ASMSET,
+             `
+       $1=$2')',
+
+      `define(ASMSET,
+             `
+       .set $1,$2')')
+
+
+ifdef(`VMS',
+      `define(extern_c_variable,
+             `$1')',
+      `define(extern_c_variable,
+             `_$1')')
+
+define(extern_c_label,
+       `extern_c_variable($1)')
+
+
+ifdef(`VMS',
+      `define(reference_c_variable,
+             `
+       .save_psect
+       .psect $1,pic,usr,ovr,rel,gbl,shr,noexe,rd,wrt,novec
+$1:
+       .restore_psect')',
+
+      `define(reference_c_variable,
+             `')')
+
+
+ifdef(`VMS',
+      `define(define_c_label,
+             `
+$1::')',
+
+      `define(define_c_label,
+             `
+       .globl  extern_c_label($1)
+extern_c_label($1):')')
+
+
+ifdef(`VMS',
+      `define(define_c_procedure,
+             `
+       .align  word
+define_c_label($1)
+       .word   ^M<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>')', # save r2-r11
+
+      `define(define_c_procedure,
+             `
+       .align  1
+define_c_label($1)
+       .word   0x0fc0')')              # save r6-r11
+\f
+# This must match the compiler (machines/vax/machin.scm)
+
+define(TC_LENGTH, ifdef(`TYPE_CODE_LENGTH', TYPE_CODE_LENGTH, 8))
+define(ADDRESS_MASK, eval((0 - (2 ** (32 - TC_LENGTH))), 10))
+
+define(rval,r9)
+define(regs,r10)
+define(rmask,r11)
+define(rfree,ap)
+define(dlink,fp)
+
+ASMSET(regblock_val,8)
+ASMSET(address_mask,ADDRESS_MASK)
+
+reference_c_variable(Ext_Stack_Pointer)
+reference_c_variable(Free)
+reference_c_variable(Registers)
+reference_c_variable(utility_table)
+
+###
+### Global data
+###
+
+ifdef(`VMS',
+      `
+       .psect  code,nowrt,exe,long
+       .psect  data,wrt,noexe,quad
+
+       .psect  data
+       .align  long
+c_save_stack:
+       .long   0
+
+       .psect  code',
+      `
+       .data
+       .align  2
+       .comm   c_save_stack,4
+
+       .text')
+
+### Callable by C conventions.  Swaps to Scheme register set and jumps
+### to the entry point specified by its only argument.
+
+define_c_procedure(C_to_interface)
+       movl    4(ap),r1                # Argument: entry point
+       subl2   @8,sp                   # Allocate space for return struct.
+       pushl   ap                      # Save while in Scheme
+       pushl   fp
+       movl    @address_mask,rmask
+       moval   extern_c_variable(Registers),regs
+
+### The data in r1 is the address of an entry point to invoke.
+
+define_c_label(interface_to_scheme)
+                                       # Swap to C registers
+       movl    sp,c_save_stack
+       movl    extern_c_variable(Ext_Stack_Pointer),sp
+       movl    extern_c_variable(Free),rfree
+                                       # Scheme return value
+       movl    regblock_val(regs),rval
+       bicl3   rmask,rval,dlink
+       jmp     (r1)                    # invoke entry point
+
+### The data in r1 is a return code to the interpreter
+
+define_c_label(interface_to_C)
+       movl    r1,r0                   # C return location
+       ret
+\f
+### Called by Scheme through a jump instruction in the register block.
+### It expects an index in r0, a return address on the stack, and 3
+### longword arguments in r2-r4.
+### The return address needs to be bumped over the format longword.
+
+define_c_label(asm_scheme_to_interface_jsb)
+       addl3   @4,(sp)+,r1
+#      brb     asm_scheme_to_interface
+
+### Transfer procedure from Scheme to C.
+### Called by Scheme through a jump instruction in the register block.
+### It expects an index in r0, and 4 longword arguments in r1-r4
+
+define_c_label(asm_scheme_to_interface)
+                                       # Swap to C registers
+       movl    rval,regblock_val(regs)
+       movl    rfree,extern_c_variable(Free)
+       movl    sp,extern_c_variable(Ext_Stack_Pointer)
+       movl    c_save_stack,sp
+       movl    (sp),fp
+       movl    4(sp),ap
+                                       # extract the C utility
+       moval   extern_c_variable(utility_table),r6
+       movl    (r6)[r0],r6
+                                       # push arguments to utility
+       pushl   r4
+       pushl   r3
+       pushl   r2
+       pushl   r1
+                                       # call C procedure
+       ifdef(`VMS',
+             `pushab   24(sp)
+              calls    @5,(r6)',
+             `calls    @4,(r6)')
+                                       # return struct -> r0/r1
+       ifdef(`VMS',
+             `movl     28(sp),r1
+              movl     24(sp),r0')
+       ifdef(`PCC',
+             `movl     4(r0),r1
+              movl     (r0),r0')
+
+       jmp     (r0)                    # invoke return handler
+
+### Called by Scheme trampolines through a jump instruction in the
+### register block.
+### It expects an index in r0, and a return address on the stack.
+### The return address needs to be bumped over the padding in the
+### trampoline.
+
+define_c_label(asm_trampoline_to_interface)
+       addl3   @2,(sp)+,r1
+       brb     extern_c_label(asm_scheme_to_interface)
+
+ifdef(`VMS',
+      `.end',
+      `')
diff --git a/v7/src/microcode/cmpintmd/vax.h b/v7/src/microcode/cmpintmd/vax.h
new file mode 100644 (file)
index 0000000..6155a9b
--- /dev/null
@@ -0,0 +1,492 @@
+/* -*-C-*-
+
+$Header: /scheme/users/jinx/microcode/RCS/cmpint-hppa.h,v 1.24 1991/08/13 18:23:23 jinx Exp j@
+Copyright (c) 1991 Massachusetts Institute of Technology
+
+This material was developed by the Scheme project at the Massachusetts
+Institute of Technology, Department of Electrical Engineering and
+Computer Science.  Permission to copy this software, to redistribute
+it, and to use it for any purpose is granted, subject to the following
+restrictions and understandings.
+
+1. Any copy made of this software must include this copyright notice
+in full.
+
+2. Users of this software agree to make their best efforts (a) to
+return to the MIT Scheme project any improvements or extensions that
+they make, so that these may be included in future releases; and (b)
+to inform MIT of noteworthy uses of this software.
+
+3. All materials developed as a consequence of the use of this
+software shall duly acknowledge such use, in accordance with the usual
+standards of acknowledging credit in academic research.
+
+4. MIT has made no warrantee or representation that the operation of
+this software will be error-free, and MIT is under no obligation to
+provide any services, by way of maintenance, update, or otherwise.
+
+5. In conjunction with products arising from the use of this material,
+there shall be no use of the name of the Massachusetts Institute of
+Technology nor of any adaptation thereof in any advertising,
+promotional, or sales literature without prior written consent from
+MIT in each case. */
+
+/*
+ *
+ * Compiled code interface macros.
+ *
+ * See cmpint.txt for a description of these fields.
+ *
+ * Specialized for the Vax architecture.
+ */
+
+#ifndef CMPINT2_H_INCLUDED
+#define CMPINT2_H_INCLUDED
+
+#define COMPILER_NONE_TYPE                     0
+#define COMPILER_MC68020_TYPE                  1
+#define COMPILER_VAX_TYPE                      2
+#define COMPILER_SPECTRUM_TYPE                 3
+#define COMPILER_MIPS_TYPE                     4
+\f
+/* Machine parameters to be set by the user. */
+
+/* Processor type.  Choose a number from the above list, or allocate your own. */
+
+#define COMPILER_PROCESSOR_TYPE                        COMPILER_VAX_TYPE
+
+/* Size (in long words) of the contents of a floating point register if
+   different from a double.
+
+#define COMPILER_TEMP_SIZE                     2
+
+*/
+
+/* Descriptor size.
+   This is the size of the offset field, and of the format field.
+   This definition probably does not need to be changed.
+ */
+
+typedef unsigned short format_word;
+
+/* PC alignment constraint.
+   Change PC_ZERO_BITS to be how many low order bits of the pc are
+   guaranteed to be 0 always because of PC alignment constraints.
+*/
+
+#define PC_ZERO_BITS                    0
+\f
+/* Skip over this many BYTES to bypass the GC check code (ordinary
+procedures and continuations differ from closures) */
+
+#define ENTRY_SKIPPED_CHECK_OFFSET     5
+#define CLOSURE_SKIPPED_CHECK_OFFSET   12
+
+/* The length of the GC recovery code that precedes an entry.
+   On the Vax a "movl s^code,r0; jsb b^n(r10)" sequence.
+ */
+
+#define ENTRY_PREFIX_LENGTH            6
+
+/* Multi-closure magic
+   On the Vax, when closures are invoked, the closure corresponding
+   to the first entry point is what's needed on the top of the stack.
+   Note that it is needed for environment only, not for code.
+   The closure code does an
+   ADDL2       &magic-constant,(SP)
+   on entry, to bump the current entry point (after the JSB instruction)
+   to the correct place.
+   This code emulates that operation by extracting the magic constant
+   from the closure code, and adjusting the address by 6 as if the
+   JSB instruction had just been executed.
+   It is used when interrupts are disabled, in order not to get into a loop.
+   Note that if closure entry points were always longword-aligned, there
+   would be no need for this nonsense.
+ */
+
+#define ADJUST_CLOSURE_AT_CALL(entry_point, location)                  \
+do {                                                                   \
+  long magic_constant;                                                 \
+                                                                       \
+  magic_constant = (* ((long *) (((char *) (entry_point)) + 2)));      \
+  (location) = ((SCHEME_OBJECT)                                                \
+               ((((long) (OBJECT_ADDRESS (location))) + 6) +           \
+                magic_constant));                                      \
+} while (0)
+
+/* Manifest closure entry block size. 
+   Size in bytes of a compiled closure's header excluding the
+   TC_MANIFEST_CLOSURE header.
+
+   On the Vax, this is the format word and gc offset word and 6 bytes
+   more for the jsb instruction.  
+*/
+
+#define COMPILED_CLOSURE_ENTRY_SIZE                                    \
+((2 * (sizeof (format_word))) + 6)
+
+/* Manifest closure entry destructuring.
+
+   Given the entry point of a closure, extract the `real entry point'
+   (the address of the real code of the procedure, ie. one indirection)
+   from the closure.
+   Note that on some machines this address may be "smeared out" over
+   multiple instructions.
+*/
+
+#define EXTRACT_CLOSURE_ENTRY_ADDRESS(real_entry_point, entry_point)   \
+{                                                                      \
+  (real_entry_point) =                                                 \
+    (* ((SCHEME_OBJECT *) (((char *) (entry_point)) + 2)));            \
+}
+
+/* This is the inverse of EXTRACT_CLOSURE_ENTRY_ADDRESS.
+   Given a closure's entry point and a code entry point, store the
+   code entry point in the closure.
+ */
+
+#define STORE_CLOSURE_ENTRY_ADDRESS(real_entry_point, entry_point)     \
+{                                                                      \
+  (* ((SCHEME_OBJECT *) (((char *) (entry_point)) + 2))) =             \
+    ((SCHEME_OBJECT) (real_entry_point));                              \
+}
+\f
+/* Execute cache entry size size in longwords.  The cache itself
+   contains both the number of arguments provided by the caller and
+   code to jump to the destination address.  Before linkage, the cache
+   contains the callee's name instead of the jump code.
+ */
+
+#define EXECUTE_CACHE_ENTRY_SIZE        2
+
+/* Execute cache destructuring. */
+
+/* Given a target location and the address of the first word of an
+   execute cache entry, extract from the cache cell the number of
+   arguments supplied by the caller and store it in target. */
+
+/* For the Vax, addresses in bytes from start of cache:
+   Before linking
+     +0: TC_FIXNUM || arity
+     +4: TC_SYMBOL || symbol address
+   After linking
+     +0: arity
+     +2: jmp @&
+     +4: xxx
+   Note that arity stays in the same place since Vaxen are little-endian.
+*/
+
+#define EXTRACT_EXECUTE_CACHE_ARITY(target, address)                   \
+{                                                                      \
+  (target) = ((long) (* ((unsigned short *) (address))));              \
+}
+
+#define EXTRACT_EXECUTE_CACHE_SYMBOL(target, address)                  \
+{                                                                      \
+  (target) = (* (((SCHEME_OBJECT *) (address)) + 1));                  \
+}
+
+/* Extract the target address (not the code to get there) from an
+   execute cache cell.
+ */
+
+#define EXTRACT_EXECUTE_CACHE_ADDRESS(target, address)                 \
+{                                                                      \
+  (target) = (* (((SCHEME_OBJECT *) (address)) + 1));                  \
+}
+
+/* This is the inverse of EXTRACT_EXECUTE_CACHE_ADDRESS. */
+
+#define STORE_EXECUTE_CACHE_ADDRESS(address, entry_address)            \
+{                                                                      \
+  (* (((SCHEME_OBJECT *) (address)) + 1)) =                            \
+    ((SCHEME_OBJECT) (entry_address));                                 \
+}
+
+/* This stores the fixed part of the instructions leaving the
+   destination address and the number of arguments intact.  These are
+   split apart so the GC can call EXTRACT/STORE...ADDRESS but it does
+   NOT need to store the instructions back.  On some architectures the
+   instructions may change due to GC and then STORE_EXECUTE_CACHE_CODE
+   should become a no-op and all of the work is done by
+   STORE_EXECUTE_CACHE_ADDRESS instead.
+ */
+
+#define STORE_EXECUTE_CACHE_CODE(address)                              \
+{                                                                      \
+  (* (((unsigned short *) (address)) + 1)) =                           \
+    ((unsigned short) 0x9f17);                                         \
+}
+\f
+/* This overrides the definition in cmpint.c because the code below
+   depends on knowing it, and is inserted before the definition in
+   cmpint.c
+ */
+
+#define COMPILER_REGBLOCK_N_FIXED      16
+
+#define COMPILER_REGBLOCK_N_HOOKS      40
+#define COMPILER_HOOK_SIZE             2       /* jsb @& + pad */
+
+#define COMPILER_REGBLOCK_EXTRA_SIZE                                   \
+(COMPILER_REGBLOCK_N_HOOKS * COMPILER_HOOK_SIZE)
+
+#define R10_TRAMPOLINE_TO_INTERFACE_OFFSET                             \
+((COMPILER_REGBLOCK_N_FIXED + (2 * COMPILER_HOOK_SIZE)) *              \
+ (sizeof (SCHEME_OBJECT)))
+
+#ifdef IN_CMPINT_C
+
+#define ASM_RESET_HOOK vax_reset_hook
+
+#ifdef CAST_FUNCTION_TO_INT_BUG
+
+#define SETUP_REGISTER(hook)                                           \
+{                                                                      \
+  extern unsigned long hook;                                           \
+  (* ((unsigned short *) (r10_value + offset))) =                      \
+    ((unsigned short) 0x9f17);                                         \
+  (* ((unsigned long *)                                                        \
+      (((unsigned short *) (r10_value + offset)) + 1))) =              \
+    ((unsigned long) (&hook));                                         \
+  offset += (COMPILER_HOOK_SIZE * (sizeof (SCHEME_OBJECT)));           \
+}
+
+#else /* not CAST_FUNCTION_TO_INT_BUG */
+
+#define SETUP_REGISTER(hook)                                           \
+{                                                                      \
+  extern void EXFUN (hook, (void));                                    \
+  (* ((unsigned short *) (r10_value + offset))) =                      \
+    ((unsigned short) 0x9f17);                                         \
+  (* ((unsigned long *)                                                        \
+      (((unsigned short *) (r10_value + offset)) + 1))) =              \
+       ((unsigned long) hook);                                         \
+  offset += (COMPILER_HOOK_SIZE * (sizeof (SCHEME_OBJECT)));           \
+}
+
+#endif
+
+void
+DEFUN_VOID (vax_reset_hook)
+{
+  unsigned char * r10_value = ((unsigned char *) (&Registers[0]));
+  int offset = (COMPILER_REGBLOCK_N_FIXED * (sizeof (SCHEME_OBJECT)));
+
+  /* These must match machines/vax/lapgen.scm */
+  SETUP_REGISTER (asm_scheme_to_interface);            /* 0 */
+  SETUP_REGISTER (asm_scheme_to_interface_jsb);                /* 1 */
+  SETUP_REGISTER (asm_trampoline_to_interface);                /* 2 */
+#if 0
+  /* Not yet written for the Vax */
+  SETUP_REGISTER (asm_shortcircuit_apply);             /* 3 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_1);      /* 4 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_2);      /* 5 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_3);      /* 6 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_4);      /* 7 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_5);      /* 8 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_6);      /* 9 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_7);      /* 10 */
+  SETUP_REGISTER (asm_shortcircuit_apply_size_8);      /* 11 */
+  SETUP_REGISTER (asm_primitive_apply);                        /* 12 */
+  SETUP_REGISTER (asm_primitive_lexpr_apply);          /* 13 */
+  SETUP_REGISTER (asm_error);                          /* 14 */
+  SETUP_REGISTER (asm_link);                           /* 15 */
+  SETUP_REGISTER (asm_interrupt_closure);              /* 16 */
+  SETUP_REGISTER (asm_interrupt_dlink);                        /* 17 */
+  SETUP_REGISTER (asm_interrupt_procedure);            /* 18 */
+  SETUP_REGISTER (asm_interrupt_continuation);         /* 19 */
+  SETUP_REGISTER (asm_assignment_trap);                        /* 20 */
+  SETUP_REGISTER (asm_reference_trap);                 /* 21 */
+  SETUP_REGISTER (asm_safe_reference_trap);            /* 22 */
+  SETUP_REGISTER (asm_generic_add);                    /* 23 */
+  SETUP_REGISTER (asm_generic_subtract);               /* 24 */
+  SETUP_REGISTER (asm_generic_multiply);               /* 25 */
+  SETUP_REGISTER (asm_generic_divide);                 /* 26 */
+  SETUP_REGISTER (asm_generic_equal);                  /* 27 */
+  SETUP_REGISTER (asm_generic_less);                   /* 28 */
+  SETUP_REGISTER (asm_generic_greater);                        /* 29 */
+  SETUP_REGISTER (asm_generic_increment);              /* 30 */
+  SETUP_REGISTER (asm_generic_decrement);              /* 31 */
+  SETUP_REGISTER (asm_generic_zero);                   /* 32 */
+  SETUP_REGISTER (asm_generic_positive);               /* 33 */
+  SETUP_REGISTER (asm_generic_negative);               /* 34 */
+  SETUP_REGISTER (asm_primitive_error);                        /* 35 */
+#endif /* 0 */
+  return;
+}
+
+#endif /* IN_CMPINT_C */
+\f
+/* On the Vax, here's a  picture of a trampoline (offset in bytes from
+   entry point)
+     -12: MANIFEST vector header
+     - 8: NON_MARKED header
+     - 4: Format word
+     - 2: 0x12 (GC Offset to start of block from .+2)
+       0: movl S^code,r0
+       3: jsb  B^R10_TRAMPOLINE_TO_INTERFACE_OFFSET(r10)
+       6: 0
+       8: trampoline dependent storage (0 - 3 longwords)
+
+   TRAMPOLINE_ENTRY_SIZE is the size in longwords of the machine
+   dependent portion of a trampoline, including the GC and format
+   headers.  The code in the trampoline must store an index (used to
+   determine which C SCHEME_UTILITY procedure to invoke) in a
+   register, jump to "scheme_to_interface" and leave the address of
+   the storage following the code in a standard location.
+
+   TRAMPOLINE_BLOCK_TO_ENTRY is the number of longwords from the start
+   of a trampoline to the first instruction.  Note that this aligns
+   the first instruction to a longword boundary.
+
+   WARNING: make_trampoline in cmpint.c will need to be changed if
+   machine instructions must be aligned more strictly than just on
+   longword boundaries (e.g. quad word alignment for instructions).
+
+   TRAMPOLINE_STORAGE takes the address of the first instruction in a
+   trampoline (not the start of the trampoline block) and returns the
+   address of the first storage word in the trampoline.
+
+   STORE_TRAMPOLINE_ENTRY gets the address of the first instruction in
+   the trampoline and stores the instructions.  It also receives the
+   index of the C SCHEME_UTILITY to be invoked.
+*/
+
+#define TRAMPOLINE_ENTRY_SIZE          3
+#define TRAMPOLINE_BLOCK_TO_ENTRY      3
+#define TRAMPOLINE_STORAGE(tramp)                                      \
+((((SCHEME_OBJECT *) tramp) - TRAMPOLINE_BLOCK_TO_ENTRY) +             \
+ (2 + TRAMPOLINE_ENTRY_SIZE)) 
+
+#define STORE_TRAMPOLINE_ENTRY(entry_address, code)                    \
+{                                                                      \
+  unsigned long *PC;                                                   \
+  /* r0 will get the code.  JSB will be used to call the assembly      \
+     language to C SCHEME_UTILITY handler:                             \
+        movl   S^code,r0                                               \
+       jsb     B^R10_TRAMPOLINE_TO_INTERFACE_OFFSET(R10)               \
+  */                                                                   \
+  PC = ((unsigned long *) entry_address);                              \
+  *PC++ = (((unsigned long) 0x165000d0) +                              \
+          (((unsigned long) (code)) << 8));                            \
+  *PC++ = (((unsigned long) 0x000000aa) +                              \
+          (((unsigned long) R10_TRAMPOLINE_TO_INTERFACE_OFFSET)        \
+           << 8));                                                     \
+}
+\f
+/* Derived parameters and macros.
+   These macros expect the above definitions to be meaningful.
+   If they are not, the macros below may have to be changed as well.
+ */
+
+#define COMPILED_ENTRY_OFFSET_WORD(entry)                               \
+  (((format_word *) (entry))[-1])
+#define COMPILED_ENTRY_FORMAT_WORD(entry)                               \
+  (((format_word *) (entry))[-2])
+
+/* The next one assumes 2's complement integers....*/
+#define CLEAR_LOW_BIT(word)                     ((word) & ((unsigned long) -2))
+#define OFFSET_WORD_CONTINUATION_P(word)        (((word) & 1) != 0)
+
+#if (PC_ZERO_BITS == 0)
+/* Instructions aligned on byte boundaries */
+#define BYTE_OFFSET_TO_OFFSET_WORD(offset)      ((offset) << 1)
+#define OFFSET_WORD_TO_BYTE_OFFSET(offset_word)                         \
+  ((CLEAR_LOW_BIT(offset_word)) >> 1)
+#endif
+
+#if (PC_ZERO_BITS == 1)
+/* Instructions aligned on word (16 bit) boundaries */
+#define BYTE_OFFSET_TO_OFFSET_WORD(offset)      (offset)
+#define OFFSET_WORD_TO_BYTE_OFFSET(offset_word)                         \
+  (CLEAR_LOW_BIT(offset_word))
+#endif
+
+#if (PC_ZERO_BITS >= 2)
+/* Should be OK for =2, but bets are off for >2 because of problems
+   mentioned earlier!
+*/
+#define SHIFT_AMOUNT                            (PC_ZERO_BITS - 1)
+#define BYTE_OFFSET_TO_OFFSET_WORD(offset)      ((offset) >> (SHIFT_AMOUNT))
+#define OFFSET_WORD_TO_BYTE_OFFSET(offset_word)                         \
+  ((CLEAR_LOW_BIT(offset_word)) << (SHIFT_AMOUNT))
+#endif
+
+#define MAKE_OFFSET_WORD(entry, block, continue)                        \
+  ((BYTE_OFFSET_TO_OFFSET_WORD(((char *) (entry)) -                     \
+                               ((char *) (block)))) |                   \
+   ((continue) ? 1 : 0))
+
+#if (EXECUTE_CACHE_ENTRY_SIZE == 2)
+#define EXECUTE_CACHE_COUNT_TO_ENTRIES(count)                           \
+  ((count) >> 1)
+#define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries)                                \
+  ((entries) << 1)
+#endif
+
+#if (EXECUTE_CACHE_ENTRY_SIZE == 4)
+#define EXECUTE_CACHE_COUNT_TO_ENTRIES(count)                           \
+  ((count) >> 2)
+#define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries)                                \
+  ((entries) << 2)
+#endif
+
+#if (!defined(EXECUTE_CACHE_COUNT_TO_ENTRIES))
+#define EXECUTE_CACHE_COUNT_TO_ENTRIES(count)                           \
+  ((count) / EXECUTE_CACHE_ENTRY_SIZE)
+#define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries)                                \
+  ((entries) * EXECUTE_CACHE_ENTRY_SIZE)
+#endif
+\f
+/* The first entry in a cc block is preceeded by 2 headers (block and nmv),
+   a format word and a gc offset word.   See the early part of the
+   TRAMPOLINE picture, above.
+ */
+
+#define CC_BLOCK_FIRST_ENTRY_OFFSET                                     \
+  (2 * ((sizeof(SCHEME_OBJECT)) + (sizeof(format_word))))
+
+/* Format words */
+
+#define FORMAT_BYTE_EXPR                0xFF
+#define FORMAT_BYTE_COMPLR              0xFE
+#define FORMAT_BYTE_CMPINT              0xFD
+#define FORMAT_BYTE_DLINK               0xFC
+#define FORMAT_BYTE_RETURN              0xFB
+
+#define FORMAT_WORD_EXPR        (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_EXPR))
+#define FORMAT_WORD_CMPINT      (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_CMPINT))
+#define FORMAT_WORD_RETURN      (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_RETURN))
+
+/* This assumes that a format word is at least 16 bits,
+   and the low order field is always 8 bits.
+ */
+
+#define MAKE_FORMAT_WORD(field1, field2)                                \
+  (((field1) << 8) | ((field2) & 0xff))
+
+#define SIGN_EXTEND_FIELD(field, size)                                  \
+  (((field) & ((1 << (size)) - 1)) |                                    \
+   ((((field) & (1 << ((size) - 1))) == 0) ? 0 :                        \
+    ((-1) << (size))))
+
+#define FORMAT_WORD_LOW_BYTE(word)                                      \
+  (SIGN_EXTEND_FIELD((((unsigned long) (word)) & 0xff), 8))
+
+#define FORMAT_WORD_HIGH_BYTE(word)                                    \
+  (SIGN_EXTEND_FIELD((((unsigned long) (word)) >> 8),                  \
+                    (((sizeof (format_word)) * CHAR_BIT) - 8)))
+
+#define COMPILED_ENTRY_FORMAT_HIGH(addr)                                \
+  (FORMAT_WORD_HIGH_BYTE(COMPILED_ENTRY_FORMAT_WORD(addr)))
+
+#define COMPILED_ENTRY_FORMAT_LOW(addr)                                 \
+  (FORMAT_WORD_LOW_BYTE(COMPILED_ENTRY_FORMAT_WORD(addr)))
+
+#define FORMAT_BYTE_FRAMEMAX            0x7f
+
+#define COMPILED_ENTRY_MAXIMUM_ARITY    COMPILED_ENTRY_FORMAT_LOW
+#define COMPILED_ENTRY_MINIMUM_ARITY    COMPILED_ENTRY_FORMAT_HIGH
+
+#endif /* CMPINT2_H_INCLUDED */