home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / cmpintmd / i386.h < prev    next >
C/C++ Source or Header  |  2000-12-05  |  26KB  |  775 lines

  1. /* -*-C-*-
  2.  
  3. $Id: i386.h,v 1.32 2000/12/05 21:23:50 cph Exp $
  4.  
  5. Copyright (c) 1992-2000 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. /*
  23.  *
  24.  * Compiled code interface macros.
  25.  *
  26.  * See cmpint.txt for a description of these fields.
  27.  *
  28.  * Specialized for the Intel 386 (and successors) architecture.
  29.  */
  30.  
  31. #ifndef SCM_CMPINTMD_H
  32. #define SCM_CMPINTMD_H
  33.  
  34. #include "cmptype.h"
  35.  
  36. /* Until cmpaux-i386.m4 is updated. */
  37. #define CMPINT_USE_STRUCS
  38.  
  39. /* Hack for OS/2 calling-convention type: */
  40.  
  41. #if defined(__OS2__) && (defined(__IBMC__) || defined(__WATCOMC__))
  42. #  define ASM_ENTRY_POINT(name) (_System name)
  43. #else
  44. #  if defined(__WIN32__) && defined(__WATCOMC__)
  45. #    define ASM_ENTRY_POINT(name) (__cdecl name)
  46. #  else
  47. #    define ASM_ENTRY_POINT(name) name
  48. #  endif
  49. #endif
  50.  
  51. /*
  52.  
  53.     Problems with i386 ISA (instruction set architecture)
  54.  
  55. <1> Code space is separate from data space.  The only way to obtain a
  56. code space address is to do a CALL and use the return address on the
  57. stack.
  58.  
  59. Problem: References to the constants vector in compiled code.
  60.  
  61. Fix: Just as on RISC machines.  Use CALL when necessary, and cache the
  62. result in the assembly language.
  63.  
  64.  
  65. <2> Jumps are PC-relative.  There are absolute jumps, assuming the PC
  66. is in a data location, or with immediate destinations that include a
  67. segment descriptor (16 bits).  The short forms have a PC-relative
  68. offset defined with respect to the immediately following instruction.
  69.  
  70. Problem: Closures and execute caches need their address in old space
  71. in order to be relocated correctly.
  72.  
  73. Fix: 
  74.  
  75.   For execute caches we can define a new linker field, called
  76. load-relocation-address which on every GC/relocation stores the new
  77. address and the old contents into global variables and stores the new
  78. address in the field.  Alternatively the difference between the new
  79. address and the old contents can be stored into a single global
  80. variable, and this can be used, together with the new address of each
  81. cache, to find the old code.
  82.  
  83.   For closures the code that reads the header (manifest closure) can
  84. do the same.
  85.  
  86.  
  87. <3> The stack pointer register (ESP) cannot be used as the base in
  88. (base + displacement) addressing mode.
  89.  
  90. Problem: Common operation in the compiler, which assumes direct access
  91. to the stack.
  92.  
  93. Fix: Use base + indexed mode, which allows specification of ESP as
  94. base and nullification of the index (by using ESP again).
  95. This is one byte longer than otherwise, but...
  96.  
  97.     Register assignments
  98.  
  99. EAX (0)        Unassigned
  100. ECX (1)        Unassigned
  101. EDX (2)        Unassigned
  102. EBX (3)        Unassigned
  103.  
  104. ESP (4)        Stack Pointer
  105. EBP (5)        Register Mask
  106. ESI (6)        Pointer to register block, etc.
  107. EDI (7)        Free Pointer
  108.  
  109. The dynamic link and value "registers" are not processor registers.
  110. Slots in the register array must be reserved for them.
  111.  
  112. The Free Pointer is EDI because EDI is the implicit base register for
  113. the memory-to-memory move instructions, and the string store
  114. instruction.  Perhaps we can make use of it.
  115.  
  116. The pointer to register block is not held in EBP (the processor's
  117. "frame" register is typically used) because its most common use, (EBP)
  118. (address syllable for memory memtop) takes more bytes than (ESI).
  119.  
  120.     Encodings and layout of various control features:
  121.  
  122. Assumptions:
  123.  
  124.   The processor will be in 32-bit address and operand mode.
  125. Thus instructions use 32-bit operands, and displacements for
  126. addressing modes and jump instructions are all 32-bits by default.
  127.  
  128.     Offset        Contents        Encoding
  129.  
  130.  
  131. - Execute cache entry encoding:
  132.  
  133.         Before linking
  134.  
  135.     0        16-bit arity    \
  136.     2        0x00          [TC_FIXNUM | arity]
  137. entry    3        0x1A        /
  138.     4        Symbol
  139.     8        <next cache>
  140.  
  141.         After linking
  142.  
  143.     0        16-bit arity
  144.     2        0x00
  145. entry    3        JMP opcode        0x39
  146.     4        32-bit offset
  147.     8        <next cache>
  148.  
  149. Arity stays in place because the i386 is a little-endian architecture.
  150.  
  151.  
  152. - Closure entry encoding:
  153.  
  154. entry    0        CALL opcode        0xE8
  155.     1        32-bit offset
  156.     5        <padding>        0x00
  157.     6        <next entry or variables>
  158.  
  159.  
  160. - Trampoline encoding:
  161.  
  162. entry    0        MOV    AL,code        0xB0, code-byte
  163.     2        CALL    n(ESI)        0xFF 0x96 n-longword
  164.     8        <trampoline dependent storage>
  165.  
  166.  
  167. - GC & interrupt check at procedure/continuation entry:
  168.  
  169. gc_lab    -7        CALL    n(ESI)        0xFF 0x56 n-byte
  170.     -4        <type/arity info>
  171.     -2        <gc offset>
  172. entry    0        CMP    EDI,(ESI)    0x39 0x3e
  173.     2        JAE    gc_lab        0x73 -11
  174.     4        <real code>
  175.  
  176.  
  177. - GC & interrupt check at closure entry:
  178.  
  179. gc_lab    -11        ADD    (ESP),&offset    0x83 0x04 0x24 offset-byte
  180.       -7        JMP    n(ESI)        0xFF 0x66 n-byte
  181.     -4        <type/arity info>
  182.     -2        <gc offset>
  183. entry    0        ADD    (ESP),&magic    0x81 0x04 0x24 magic-longword
  184.     7        CMP    EDI,(ESI)    0x39 0x3e
  185.     9        JAE    gc_lab        0x73 0xea (= -22)
  186.     11        <real code>
  187.  
  188. The magic value depends on the closure because of canonicalization.
  189.  
  190. The ADD instruction at offset -11 is not present for the 0th closure
  191. entry, since it is the canonical entry point.  Its format depends on
  192. the value of offset, since the sign-extending forms often suffice.
  193.  
  194. offset = entry_number * entry_size
  195. magic = ([TC_COMPILED_ENTRY | 0] - (offset + length_of_CALL_instruction))
  196.  
  197. */
  198.  
  199. #define COMPILER_PROCESSOR_TYPE            COMPILER_IA32_TYPE
  200.  
  201. /* The i387 coprocessor and i486 use 80-bit extended format internally. */
  202.  
  203. #define COMPILER_TEMP_SIZE            3
  204.  
  205. typedef unsigned short format_word;
  206.  
  207. /* i386 instructions can be aligned on any byte boundary. */
  208.  
  209. #define PC_ZERO_BITS                        0
  210.  
  211. /* See the encodings above. */
  212.  
  213. #define ENTRY_PREFIX_LENGTH            3
  214.  
  215. #  define COMPILED_CLOSURE_ENTRY_SIZE                    \
  216.   ((2 * (sizeof (format_word))) + 6)
  217.  
  218. #  define ADJUST_CLOSURE_AT_CALL(entry_point, location)            \
  219. do {                                    \
  220.   long magic_constant;                            \
  221.                                     \
  222.   magic_constant = (* ((long *) (((char *) (entry_point)) + 3)));    \
  223.   (location) = ((SCHEME_OBJECT)                        \
  224.         ((((long) (OBJECT_ADDRESS (location))) + 5) +        \
  225.          magic_constant));                    \
  226. } while (0)
  227.  
  228. /* For the relocation of PC-relative JMP and CALL instructions.
  229.    This is used during GC/relocation, when the displacement
  230.    is incorrect, since it was computed with respect to the
  231.    location in old space.
  232.  */
  233.  
  234. extern long i386_pc_displacement_relocation;
  235.  
  236. #define EXTRACT_ADDRESS_FROM_DISPLACEMENT(var, instr_addr) do        \
  237. {                                    \
  238.   long displacement_address, new_displacement;                \
  239.                                     \
  240.   displacement_address = (((long) (instr_addr)) + 1);            \
  241.   new_displacement = ((* ((long *) displacement_address))        \
  242.               + i386_pc_displacement_relocation);        \
  243.   (* ((long *) displacement_address)) = new_displacement;        \
  244.   (var) = ((SCHEME_OBJECT)                        \
  245.        ((ADDR_TO_SCHEME_ADDR (displacement_address + 4))        \
  246.         + new_displacement));                    \
  247. } while (0)
  248.  
  249. #define STORE_DISPLACEMENT_FROM_ADDRESS(target, instr_address) do    \
  250. {                                    \
  251.   long displacement_address = (((long) (instr_address)) + 1);        \
  252.   (* ((long *) displacement_address)) =                    \
  253.     (((long) (target))                            \
  254.      - (ADDR_TO_SCHEME_ADDR (displacement_address + 4)));        \
  255. } while (0)
  256.  
  257. #define BCH_EXTRACT_ADDRESS_FROM_DISPLACEMENT(var, v_addr, p_addr) do    \
  258. {                                    \
  259.   long displacement_address, new_displacement;                \
  260.                                     \
  261.   displacement_address = (((long) (p_addr)) + 1);            \
  262.   new_displacement = ((* ((long *) displacement_address))        \
  263.               + i386_pc_displacement_relocation);        \
  264.   (* ((long *) displacement_address)) = new_displacement;        \
  265.   (var) = ((SCHEME_OBJECT)                        \
  266.        ((ADDR_TO_SCHEME_ADDR (((long) (v_addr)) + 5))        \
  267.         + new_displacement));                    \
  268. } while (0)
  269.  
  270. #define BCH_STORE_DISPLACEMENT_FROM_ADDRESS(target, v_addr, p_addr) do    \
  271. {                                    \
  272.   long displacement_address = (((long) (p_addr)) + 1);            \
  273.   (* ((long *) displacement_address))                    \
  274.     = (((long) (target))                        \
  275.        - (ADDR_TO_SCHEME_ADDR (((long) (v_addr)) + 5)));        \
  276. } while (0)
  277.  
  278. #define START_CLOSURE_RELOCATION(scan) do                \
  279. {                                    \
  280.   SCHEME_OBJECT * _block, * _old;                    \
  281.   char * _new;                                \
  282.                                     \
  283.   _block = ((SCHEME_OBJECT *) (scan));                    \
  284.   _old = (OBJECT_ADDRESS (_block[(OBJECT_DATUM (*_block))]));        \
  285.   _new = ((char *) (FIRST_MANIFEST_CLOSURE_ENTRY (_block + 1)));    \
  286.                                     \
  287.   i386_pc_displacement_relocation = (((long) _old) - ((long) _new));    \
  288. } while (0)
  289.  
  290. #define END_CLOSURE_RELOCATION(scan)    i386_pc_displacement_relocation = 0
  291. #define EXTRACT_CLOSURE_ENTRY_ADDRESS    EXTRACT_ADDRESS_FROM_DISPLACEMENT
  292. #define STORE_CLOSURE_ENTRY_ADDRESS    STORE_DISPLACEMENT_FROM_ADDRESS
  293.  
  294. #define BCH_START_CLOSURE_RELOCATION(scan) do                \
  295. {                                    \
  296.   SCHEME_OBJECT * _scan, * _block, _old_obj, * _old;            \
  297.   char * _new;                                \
  298.                                     \
  299.   _scan = ((SCHEME_OBJECT *) (scan));                    \
  300.   _block = ((SCHEME_OBJECT *)                        \
  301.         (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_scan)));        \
  302.   READ_NEWSPACE_ADDRESS (_old_obj,                    \
  303.              (_block + (OBJECT_DATUM (* _scan))));        \
  304.   _old = (OBJECT_ADDRESS (_old_obj));                    \
  305.   _new = ((char *) (FIRST_MANIFEST_CLOSURE_ENTRY (_scan + 1)));        \
  306.                                     \
  307.   i386_pc_displacement_relocation                    \
  308.     = (((long) _old)                            \
  309.        - ((long) (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_new))));        \
  310. } while (0)
  311.  
  312. #define BCH_END_CLOSURE_RELOCATION    END_CLOSURE_RELOCATION
  313.  
  314. #define BCH_EXTRACT_CLOSURE_ENTRY_ADDRESS(var, p_addr) do        \
  315. {                                    \
  316.   SCHEME_OBJECT * _p_addr, * _v_addr;                    \
  317.                                     \
  318.   _p_addr = ((SCHEME_OBJECT *) (p_addr));                \
  319.   _v_addr = ((SCHEME_OBJECT *)                        \
  320.          (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr)));        \
  321.                                     \
  322.   BCH_EXTRACT_ADDRESS_FROM_DISPLACEMENT (var, _v_addr, _p_addr);    \
  323. } while (0)
  324.  
  325. #define BCH_STORE_CLOSURE_ENTRY_ADDRESS(target, p_addr) do        \
  326. {                                    \
  327.   SCHEME_OBJECT * _p_addr, * _v_addr;                    \
  328.                                     \
  329.   _p_addr = ((SCHEME_OBJECT *) (p_addr));                \
  330.   _v_addr = ((SCHEME_OBJECT *)                        \
  331.          (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr)));        \
  332.                                     \
  333.   BCH_STORE_DISPLACEMENT_FROM_ADDRESS (target, _v_addr, _p_addr);    \
  334. } while (0)
  335.  
  336. #define EXECUTE_CACHE_ENTRY_SIZE        2
  337.  
  338. #define FIRST_OPERATOR_LINKAGE_OFFSET        2
  339.  
  340. #define EXTRACT_EXECUTE_CACHE_ARITY(target, address) do            \
  341. {                                    \
  342.   (target) = ((long) (* ((unsigned short *) (address))));        \
  343. } while (0)
  344.  
  345. #define EXTRACT_EXECUTE_CACHE_SYMBOL(target, address) do        \
  346. {                                    \
  347.   (target) = (* (((SCHEME_OBJECT *) (address)) + 1));            \
  348. } while (0)
  349.  
  350. /* This is used during GC/relocation.
  351.    The displacement stored in the instruction refers to the old space
  352.    location.
  353.  */   
  354.  
  355. #define EXTRACT_OPERATOR_LINKAGE_ADDRESS(target, address) do        \
  356. {                                    \
  357.   EXTRACT_ADDRESS_FROM_DISPLACEMENT (target,                \
  358.                      (((long) (address)) + 3));        \
  359. } while (0)
  360.  
  361. /* This is used when not relocating.
  362.    The displacement refers to the current location of the instruction.
  363.  */
  364.  
  365. #define EXTRACT_EXECUTE_CACHE_ADDRESS(loc, cache_addr) do        \
  366. {                                    \
  367.   long displacement_address, displacement;                \
  368.                                     \
  369.   displacement_address = (((long) (cache_addr)) + 4);            \
  370.   displacement = (* ((long *) displacement_address));            \
  371.   (loc) = ((SCHEME_OBJECT)                        \
  372.        ((displacement_address + 4) + displacement));        \
  373. } while (0)
  374.  
  375. #define STORE_EXECUTE_CACHE_ADDRESS(address, entry_address) do        \
  376. {                                    \
  377.   STORE_DISPLACEMENT_FROM_ADDRESS (entry_address,            \
  378.                    (((long) (address)) + 3));        \
  379. } while (0)
  380.  
  381. #define STORE_EXECUTE_CACHE_CODE(address) do                \
  382. {                                    \
  383.   /* Store a <JMP rel32> opcode. */                    \
  384.   (* (((unsigned char *) (address)) + 3)) = 0xe9;            \
  385. } while (0)
  386.  
  387. #define START_OPERATOR_RELOCATION(scan)    do                \
  388. {                                    \
  389.   SCHEME_OBJECT * _scan, * _old, _loc;                    \
  390.                                     \
  391.   _scan = (((SCHEME_OBJECT *) (scan)) + 1);                \
  392.   _old = ((SCHEME_OBJECT *) (* _scan));                    \
  393.   _loc = (ADDR_TO_SCHEME_ADDR (_scan));                    \
  394.                                     \
  395.   (* _scan) = _loc;                            \
  396.   i386_pc_displacement_relocation = (((long) _old) - ((long) _loc));    \
  397. } while (0)
  398.  
  399. #define END_OPERATOR_RELOCATION(scan)    i386_pc_displacement_relocation = 0
  400.  
  401. #define BCH_START_OPERATOR_RELOCATION(scan) do                \
  402. {                                    \
  403.   SCHEME_OBJECT * _scan, * _old, _loc;                    \
  404.                                     \
  405.   _scan = (((SCHEME_OBJECT *) (scan)) + 1);                \
  406.   _old = ((SCHEME_OBJECT *) (* _scan));                    \
  407.   _loc = (ADDR_TO_SCHEME_ADDR                        \
  408.       (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_scan)));            \
  409.                                     \
  410.   * _scan = _loc;                            \
  411.   i386_pc_displacement_relocation = (((long) _old) - ((long) _loc));    \
  412. } while (0)
  413.  
  414. #define BCH_END_OPERATOR_RELOCATION        END_OPERATOR_RELOCATION
  415.  
  416. #define BCH_EXTRACT_OPERATOR_LINKAGE_ADDRESS(var, p_addr) do        \
  417. {                                    \
  418.   SCHEME_OBJECT * _p_addr, * _v_addr;                    \
  419.                                     \
  420.   _p_addr = ((SCHEME_OBJECT *) (((long) (p_addr)) + 3));        \
  421.   _v_addr = ((SCHEME_OBJECT *)                        \
  422.          (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr)));        \
  423.                                     \
  424.   BCH_EXTRACT_ADDRESS_FROM_DISPLACEMENT (var, _v_addr, _p_addr);    \
  425. } while (0)
  426.  
  427. #define BCH_STORE_OPERATOR_LINKAGE_ADDRESS(e_addr, p_addr) do        \
  428. {                                    \
  429.   SCHEME_OBJECT * _p_addr, * _v_addr;                    \
  430.                                     \
  431.   _p_addr = ((SCHEME_OBJECT *) (((long) (p_addr)) + 3));        \
  432.   _v_addr = ((SCHEME_OBJECT *)                        \
  433.          (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr)));        \
  434.                                     \
  435.   BCH_STORE_DISPLACEMENT_FROM_ADDRESS (e_addr, _v_addr, _p_addr);    \
  436. } while (0)
  437.  
  438. #define TRAMPOLINE_ENTRY_SIZE            3
  439. #define TRAMPOLINE_BLOCK_TO_ENTRY        3 /* MNV to MOV instr. */
  440.  
  441. #define STORE_TRAMPOLINE_ENTRY(entry_address, index) do            \
  442. {                                    \
  443.   unsigned char *PC = ((unsigned char *) (entry_address));        \
  444.                                     \
  445.   *PC++ = 0xb0;                /* MOV    AL,byte */        \
  446.   *PC++ = ((unsigned char) (index));    /* byte value */        \
  447.   *PC++ = 0xff;                /* CALL */            \
  448.   *PC++ = 0x96;                /* /2 disp32(ESI) */        \
  449.   (* ((unsigned long *) PC)) = ESI_TRAMPOLINE_TO_INTERFACE_OFFSET;    \
  450. } while (0)
  451.  
  452. #define TRAMPOLINE_ENTRY_POINT(tramp_block)                \
  453.   (((SCHEME_OBJECT *) (tramp_block)) + TRAMPOLINE_BLOCK_TO_ENTRY)
  454.  
  455. #define TRAMPOLINE_STORAGE(tramp_entry)                    \
  456.   ((((SCHEME_OBJECT *) (tramp_entry)) - TRAMPOLINE_BLOCK_TO_ENTRY) +    \
  457.    (2 + TRAMPOLINE_ENTRY_SIZE)) 
  458.  
  459. /* These must aggree with cmpaux-i386.m4!
  460.    The register block is actually allocated there.
  461.  */
  462.  
  463. #define COMPILER_REGBLOCK_N_FIXED        16
  464.  
  465. #define COMPILER_REGBLOCK_N_HOOKS        80
  466.  
  467.     /* A hook is the address (offset) of an assembly-language routine. */
  468.  
  469. #define COMPILER_HOOK_SIZE            1
  470.  
  471. #define COMPILER_REGBLOCK_EXTRA_SIZE                    \
  472.   (COMPILER_REGBLOCK_N_HOOKS * COMPILER_HOOK_SIZE)
  473.  
  474. #define REGBLOCK_ALLOCATED_BY_INTERFACE
  475.  
  476. #define ESI_TRAMPOLINE_TO_INTERFACE_OFFSET                \
  477.   ((COMPILER_REGBLOCK_N_FIXED + (2 * COMPILER_HOOK_SIZE)) *        \
  478.    (sizeof (SCHEME_OBJECT)))
  479.  
  480. #ifdef IN_CMPINT_C
  481.  
  482. #ifdef _MACH_UNIX
  483. #  include <mach.h>
  484. #  define VM_PROT_SCHEME (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
  485. #endif
  486.  
  487. long i386_pc_displacement_relocation = 0;
  488.  
  489. #define ASM_RESET_HOOK i386_reset_hook
  490.  
  491. #ifndef HOOK_TO_SCHEME_OFFSET
  492. #  define HOOK_TO_SCHEME_OFFSET(hook) ((unsigned long) (hook))
  493. #endif
  494.  
  495. #ifdef HAVE_STDC
  496. #  define STRINGIFY(x) #x
  497. #else
  498. #  define STRINGIFY(x) "x"
  499. #endif
  500.  
  501. #define SETUP_REGISTER(hook) do                        \
  502. {                                    \
  503.   extern void hook ();                            \
  504.                                     \
  505.   (* ((unsigned long *) (esi_value + offset))) =            \
  506.     (HOOK_TO_SCHEME_OFFSET (hook));                    \
  507.   offset += (COMPILER_HOOK_SIZE * (sizeof (SCHEME_OBJECT)));        \
  508.   declare_builtin (((unsigned long) hook), (STRINGIFY (hook)));        \
  509. } while (0)
  510.  
  511. void
  512. DEFUN_VOID (i386_reset_hook)
  513. {
  514.   extern int EXFUN (ASM_ENTRY_POINT(i386_interface_initialize), (void));
  515.   extern void EXFUN (declare_builtin, (unsigned long, char *));
  516.   int offset = (COMPILER_REGBLOCK_N_FIXED * (sizeof (SCHEME_OBJECT)));
  517.   unsigned char * esi_value = ((unsigned char *) (&Registers[0]));
  518.   int fp_support_present = (i386_interface_initialize ());
  519.  
  520.   /* These must match machines/i386/lapgen.scm */
  521.  
  522.   SETUP_REGISTER (asm_scheme_to_interface);         /* 0 */
  523.   SETUP_REGISTER (asm_scheme_to_interface_call);    /* 1 */
  524.  
  525.   if (offset != ESI_TRAMPOLINE_TO_INTERFACE_OFFSET)
  526.   {
  527.     outf_fatal ("\ni386_reset_hook: ESI_TRAMPOLINE_TO_INTERFACE_OFFSET\n");
  528.     Microcode_Termination (TERM_EXIT);
  529.   }
  530.   SETUP_REGISTER (asm_trampoline_to_interface);        /* 2 */
  531.  
  532.   SETUP_REGISTER (asm_interrupt_procedure);        /* 3 */
  533.   SETUP_REGISTER (asm_interrupt_continuation);        /* 4 */
  534.   SETUP_REGISTER (asm_interrupt_closure);        /* 5 */
  535.   SETUP_REGISTER (asm_interrupt_dlink);            /* 6 */
  536.  
  537.   SETUP_REGISTER (asm_primitive_apply);            /* 7 */
  538.   SETUP_REGISTER (asm_primitive_lexpr_apply);        /* 8 */
  539.   SETUP_REGISTER (asm_assignment_trap);            /* 9 */
  540.   SETUP_REGISTER (asm_reference_trap);            /* 10 */
  541.   SETUP_REGISTER (asm_safe_reference_trap);        /* 11 */
  542.   SETUP_REGISTER (asm_link);                /* 12 */
  543.   SETUP_REGISTER (asm_error);                /* 13 */
  544.   SETUP_REGISTER (asm_primitive_error);            /* 14 */
  545.   SETUP_REGISTER (asm_short_primitive_apply);        /* 15 */
  546.  
  547.   /* No more room for positive offsets without going to 32-bit
  548.      offsets!
  549.    */
  550.  
  551.   /* This is a hack to make all the hooks be addressable
  552.      with byte offsets (instead of longword offsets).
  553.      The register block extends to negative offsets as well,
  554.      so all the following hooks are accessed with negative
  555.      offsets, and all fit in a byte.
  556.    */
  557.  
  558.   offset    = -128;
  559.  
  560.   if (fp_support_present != 0)
  561.   {
  562.     SETUP_REGISTER (asm_generic_add);            /* -32 */
  563.     SETUP_REGISTER (asm_generic_subtract);        /* -31 */
  564.     SETUP_REGISTER (asm_generic_multiply);        /* -30 */
  565.     SETUP_REGISTER (asm_generic_divide);        /* -29 */
  566.     SETUP_REGISTER (asm_generic_equal);            /* -28 */
  567.     SETUP_REGISTER (asm_generic_less);            /* -27 */
  568.     SETUP_REGISTER (asm_generic_greater);        /* -26 */
  569.     SETUP_REGISTER (asm_generic_increment);        /* -25 */
  570.     SETUP_REGISTER (asm_generic_decrement);        /* -24 */
  571.     SETUP_REGISTER (asm_generic_zero);            /* -23 */
  572.     SETUP_REGISTER (asm_generic_positive);        /* -22 */
  573.     SETUP_REGISTER (asm_generic_negative);        /* -21 */
  574.     SETUP_REGISTER (asm_generic_quotient);        /* -20 */
  575.     SETUP_REGISTER (asm_generic_remainder);        /* -19 */
  576.     SETUP_REGISTER (asm_generic_modulo);        /* -18 */
  577.   }
  578.   else
  579.   {
  580.     SETUP_REGISTER (asm_nofp_add);            /* -32 */
  581.     SETUP_REGISTER (asm_nofp_subtract);            /* -31 */
  582.     SETUP_REGISTER (asm_nofp_multiply);            /* -30 */
  583.     SETUP_REGISTER (asm_nofp_divide);            /* -29 */
  584.     SETUP_REGISTER (asm_nofp_equal);            /* -28 */
  585.     SETUP_REGISTER (asm_nofp_less);            /* -27 */
  586.     SETUP_REGISTER (asm_nofp_greater);            /* -26 */
  587.     SETUP_REGISTER (asm_nofp_increment);        /* -25 */
  588.     SETUP_REGISTER (asm_nofp_decrement);        /* -24 */
  589.     SETUP_REGISTER (asm_nofp_zero);            /* -23 */
  590.     SETUP_REGISTER (asm_nofp_positive);            /* -22 */
  591.     SETUP_REGISTER (asm_nofp_negative);            /* -21 */
  592.     SETUP_REGISTER (asm_nofp_quotient);            /* -20 */
  593.     SETUP_REGISTER (asm_nofp_remainder);        /* -19 */
  594.     SETUP_REGISTER (asm_nofp_modulo);            /* -18 */
  595.   }
  596.  
  597.   SETUP_REGISTER (asm_sc_apply);            /* -17 */
  598.   SETUP_REGISTER (asm_sc_apply_size_1);            /* -16 */
  599.   SETUP_REGISTER (asm_sc_apply_size_2);            /* -15 */
  600.   SETUP_REGISTER (asm_sc_apply_size_3);            /* -14 */
  601.   SETUP_REGISTER (asm_sc_apply_size_4);            /* -13 */
  602.   SETUP_REGISTER (asm_sc_apply_size_5);            /* -12 */
  603.   SETUP_REGISTER (asm_sc_apply_size_6);            /* -11 */
  604.   SETUP_REGISTER (asm_sc_apply_size_7);            /* -10 */
  605.   SETUP_REGISTER (asm_sc_apply_size_8);            /* -9 */
  606.   SETUP_REGISTER (asm_interrupt_continuation_2);    /* -8 */
  607.  
  608. #ifdef _MACH_UNIX
  609.   {
  610.     vm_address_t addr;
  611.     vm_size_t size;
  612.     vm_prot_t prot;
  613.     vm_prot_t max_prot;
  614.     vm_inherit_t inheritance;
  615.     boolean_t shared;
  616.     port_t object;
  617.     vm_offset_t offset;
  618.  
  619.     addr = ((vm_address_t) Heap);
  620.     if ((vm_region ((task_self ()), &addr, &size, &prot, &max_prot,
  621.             &inheritance, &shared, &object, &offset))
  622.     != KERN_SUCCESS)
  623.     {
  624.       outf_fatal ( "compiler_reset: vm_region() failed.\n");
  625.       Microcode_Termination (TERM_EXIT);
  626.       /*NOTREACHED*/
  627.     }
  628.     if ((prot & VM_PROT_SCHEME) != VM_PROT_SCHEME)
  629.     {
  630.       if ((max_prot & VM_PROT_SCHEME) != VM_PROT_SCHEME)
  631.       {
  632.     outf_fatal (
  633.          "compiler_reset: inadequate protection for Heap.\n");
  634.     outf_fatal ( "maximum = 0x%lx; desired = 0x%lx\n",
  635.          ((unsigned long) (max_prot & VM_PROT_SCHEME)),
  636.          ((unsigned long) VM_PROT_SCHEME));
  637.     Microcode_Termination (TERM_EXIT);
  638.     /*NOTREACHED*/
  639.       }
  640.       if ((vm_protect ((task_self ()), ((vm_address_t) Heap),
  641.                (((char *) Constant_Top) - ((char *) Heap)),
  642.                0, VM_PROT_SCHEME))
  643.       != KERN_SUCCESS)
  644.       {
  645.     outf_fatal (
  646.          "compiler_reset: unable to change protection for Heap.\n");
  647.     outf_fatal ( "actual = 0x%lx; desired = 0x%lx\n",
  648.          ((unsigned long) (prot & VM_PROT_SCHEME)),
  649.          ((unsigned long) VM_PROT_SCHEME));
  650.     Microcode_Termination (TERM_EXIT);
  651.     /*NOTREACHED*/
  652.       }
  653.     }
  654.   }
  655. #endif /* _MACH_UNIX */
  656. }
  657.  
  658. #endif /* IN_CMPINT_C */
  659.  
  660. /* Derived parameters and macros.
  661.    These macros expect the above definitions to be meaningful.
  662.    If they are not, the macros below may have to be changed as well.
  663.  */
  664.  
  665. #define COMPILED_ENTRY_OFFSET_WORD(entry)                               \
  666.   (((format_word *) (entry))[-1])
  667. #define COMPILED_ENTRY_FORMAT_WORD(entry)                               \
  668.   (((format_word *) (entry))[-2])
  669.  
  670. /* The next one assumes 2's complement integers....*/
  671. #define CLEAR_LOW_BIT(word)                     ((word) & ((unsigned long) -2))
  672. #define OFFSET_WORD_CONTINUATION_P(word)        (((word) & 1) != 0)
  673.  
  674. #if (PC_ZERO_BITS == 0)
  675. /* Instructions aligned on byte boundaries */
  676. #define BYTE_OFFSET_TO_OFFSET_WORD(offset)      ((offset) << 1)
  677. #define OFFSET_WORD_TO_BYTE_OFFSET(offset_word)                         \
  678.   ((CLEAR_LOW_BIT(offset_word)) >> 1)
  679. #endif
  680.  
  681. #if (PC_ZERO_BITS == 1)
  682. /* Instructions aligned on word (16 bit) boundaries */
  683. #define BYTE_OFFSET_TO_OFFSET_WORD(offset)      (offset)
  684. #define OFFSET_WORD_TO_BYTE_OFFSET(offset_word)                         \
  685.   (CLEAR_LOW_BIT(offset_word))
  686. #endif
  687.  
  688. #if (PC_ZERO_BITS >= 2)
  689. /* Should be OK for =2, but bets are off for >2 because of problems
  690.    mentioned earlier!
  691. */
  692. #define SHIFT_AMOUNT                            (PC_ZERO_BITS - 1)
  693. #define BYTE_OFFSET_TO_OFFSET_WORD(offset)      ((offset) >> (SHIFT_AMOUNT))
  694. #define OFFSET_WORD_TO_BYTE_OFFSET(offset_word)                         \
  695.   ((CLEAR_LOW_BIT(offset_word)) << (SHIFT_AMOUNT))
  696. #endif
  697.  
  698. #define MAKE_OFFSET_WORD(entry, block, continue)                        \
  699.   ((BYTE_OFFSET_TO_OFFSET_WORD(((char *) (entry)) -                     \
  700.                                ((char *) (block)))) |                   \
  701.    ((continue) ? 1 : 0))
  702.  
  703. #if (EXECUTE_CACHE_ENTRY_SIZE == 2)
  704. #define EXECUTE_CACHE_COUNT_TO_ENTRIES(count)                           \
  705.   ((count) >> 1)
  706. #define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries)                \
  707.   ((entries) << 1)
  708. #endif
  709.  
  710. #if (EXECUTE_CACHE_ENTRY_SIZE == 4)
  711. #define EXECUTE_CACHE_COUNT_TO_ENTRIES(count)                           \
  712.   ((count) >> 2)
  713. #define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries)                \
  714.   ((entries) << 2)
  715. #endif
  716.  
  717. #if (!defined(EXECUTE_CACHE_COUNT_TO_ENTRIES))
  718. #define EXECUTE_CACHE_COUNT_TO_ENTRIES(count)                           \
  719.   ((count) / EXECUTE_CACHE_ENTRY_SIZE)
  720. #define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries)                \
  721.   ((entries) * EXECUTE_CACHE_ENTRY_SIZE)
  722. #endif
  723.  
  724. /* The first entry in a cc block is preceeded by 2 headers (block and nmv),
  725.    a format word and a gc offset word.   See the early part of the
  726.    TRAMPOLINE picture, above.
  727.  */
  728.  
  729. #define CC_BLOCK_FIRST_ENTRY_OFFSET                                     \
  730.   (2 * ((sizeof(SCHEME_OBJECT)) + (sizeof(format_word))))
  731.  
  732. /* Format words */
  733.  
  734. #define FORMAT_BYTE_EXPR                0xFF
  735. #define FORMAT_BYTE_COMPLR              0xFE
  736. #define FORMAT_BYTE_CMPINT              0xFD
  737. #define FORMAT_BYTE_DLINK               0xFC
  738. #define FORMAT_BYTE_RETURN              0xFB
  739.  
  740. #define FORMAT_WORD_EXPR        (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_EXPR))
  741. #define FORMAT_WORD_CMPINT      (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_CMPINT))
  742. #define FORMAT_WORD_RETURN      (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_RETURN))
  743.  
  744. /* This assumes that a format word is at least 16 bits,
  745.    and the low order field is always 8 bits.
  746.  */
  747.  
  748. #define MAKE_FORMAT_WORD(field1, field2)                                \
  749.   (((field1) << 8) | ((field2) & 0xff))
  750.  
  751. #define SIGN_EXTEND_FIELD(field, size)                                  \
  752.   (((field) & ((1 << (size)) - 1)) |                                    \
  753.    ((((field) & (1 << ((size) - 1))) == 0) ? 0 :                        \
  754.     ((-1) << (size))))
  755.  
  756. #define FORMAT_WORD_LOW_BYTE(word)                                      \
  757.   (SIGN_EXTEND_FIELD((((unsigned long) (word)) & 0xff), 8))
  758.  
  759. #define FORMAT_WORD_HIGH_BYTE(word)                    \
  760.   (SIGN_EXTEND_FIELD((((unsigned long) (word)) >> 8),            \
  761.              (((sizeof (format_word)) * CHAR_BIT) - 8)))
  762.  
  763. #define COMPILED_ENTRY_FORMAT_HIGH(addr)                                \
  764.   (FORMAT_WORD_HIGH_BYTE(COMPILED_ENTRY_FORMAT_WORD(addr)))
  765.  
  766. #define COMPILED_ENTRY_FORMAT_LOW(addr)                                 \
  767.   (FORMAT_WORD_LOW_BYTE(COMPILED_ENTRY_FORMAT_WORD(addr)))
  768.  
  769. #define FORMAT_BYTE_FRAMEMAX            0x7f
  770.  
  771. #define COMPILED_ENTRY_MAXIMUM_ARITY    COMPILED_ENTRY_FORMAT_LOW
  772. #define COMPILED_ENTRY_MINIMUM_ARITY    COMPILED_ENTRY_FORMAT_HIGH
  773.  
  774. #endif /* not SCM_CMPINTMD_H */
  775.