3
$Id: i386.h,v 1.35 2002/02/03 03:38:55 cph Exp $
5
Copyright (c) 1992-2002 Massachusetts Institute of Technology
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25
* Compiled code interface macros.
27
* See cmpint.txt for a description of these fields.
29
* Specialized for the Intel 386 (and successors) architecture.
32
#ifndef SCM_CMPINTMD_H
33
#define SCM_CMPINTMD_H
37
/* Until cmpaux-i386.m4 is updated. */
38
#define CMPINT_USE_STRUCS
40
/* Hack for OS/2 calling-convention type: */
42
#if defined(__OS2__) && (defined(__IBMC__) || defined(__WATCOMC__))
43
# define ASM_ENTRY_POINT(name) (_System name)
45
# if defined(__WIN32__) && defined(__WATCOMC__)
46
# define ASM_ENTRY_POINT(name) (__cdecl name)
48
# define ASM_ENTRY_POINT(name) name
52
extern void EXFUN (ia32_cache_synchronize, (void));
53
extern int ia32_cpuid_needed;
55
#define IA32_CACHE_SYNCHRONIZE() \
57
if (ia32_cpuid_needed) \
58
ia32_cache_synchronize (); \
63
Problems with i386 ISA (instruction set architecture)
65
<1> Code space is separate from data space. The only way to obtain a
66
code space address is to do a CALL and use the return address on the
69
Problem: References to the constants vector in compiled code.
71
Fix: Just as on RISC machines. Use CALL when necessary, and cache the
72
result in the assembly language.
75
<2> Jumps are PC-relative. There are absolute jumps, assuming the PC
76
is in a data location, or with immediate destinations that include a
77
segment descriptor (16 bits). The short forms have a PC-relative
78
offset defined with respect to the immediately following instruction.
80
Problem: Closures and execute caches need their address in old space
81
in order to be relocated correctly.
85
For execute caches we can define a new linker field, called
86
load-relocation-address which on every GC/relocation stores the new
87
address and the old contents into global variables and stores the new
88
address in the field. Alternatively the difference between the new
89
address and the old contents can be stored into a single global
90
variable, and this can be used, together with the new address of each
91
cache, to find the old code.
93
For closures the code that reads the header (manifest closure) can
97
<3> The stack pointer register (ESP) cannot be used as the base in
98
(base + displacement) addressing mode.
100
Problem: Common operation in the compiler, which assumes direct access
103
Fix: Use base + indexed mode, which allows specification of ESP as
104
base and nullification of the index (by using ESP again).
105
This is one byte longer than otherwise, but...
114
ESP (4) Stack Pointer
115
EBP (5) Register Mask
116
ESI (6) Pointer to register block, etc.
119
The dynamic link and value "registers" are not processor registers.
120
Slots in the register array must be reserved for them.
122
The Free Pointer is EDI because EDI is the implicit base register for
123
the memory-to-memory move instructions, and the string store
124
instruction. Perhaps we can make use of it.
126
The pointer to register block is not held in EBP (the processor's
127
"frame" register is typically used) because its most common use, (EBP)
128
(address syllable for memory memtop) takes more bytes than (ESI).
130
Encodings and layout of various control features:
134
The processor will be in 32-bit address and operand mode.
135
Thus instructions use 32-bit operands, and displacements for
136
addressing modes and jump instructions are all 32-bits by default.
138
Offset Contents Encoding
141
- Execute cache entry encoding:
146
2 0x00 [TC_FIXNUM | arity]
155
entry 3 JMP opcode 0x39
159
Arity stays in place because the i386 is a little-endian architecture.
162
- Closure entry encoding:
164
entry 0 CALL opcode 0xE8
167
6 <next entry or variables>
170
- Trampoline encoding:
172
entry 0 MOV AL,code 0xB0, code-byte
173
2 CALL n(ESI) 0xFF 0x96 n-longword
174
8 <trampoline dependent storage>
177
- GC & interrupt check at procedure/continuation entry:
179
gc_lab -7 CALL n(ESI) 0xFF 0x56 n-byte
182
entry 0 CMP EDI,(ESI) 0x39 0x3e
183
2 JAE gc_lab 0x73 -11
187
- GC & interrupt check at closure entry:
189
gc_lab -11 ADD (ESP),&offset 0x83 0x04 0x24 offset-byte
190
-7 JMP n(ESI) 0xFF 0x66 n-byte
193
entry 0 ADD (ESP),&magic 0x81 0x04 0x24 magic-longword
194
7 CMP EDI,(ESI) 0x39 0x3e
195
9 JAE gc_lab 0x73 0xea (= -22)
198
The magic value depends on the closure because of canonicalization.
200
The ADD instruction at offset -11 is not present for the 0th closure
201
entry, since it is the canonical entry point. Its format depends on
202
the value of offset, since the sign-extending forms often suffice.
204
offset = entry_number * entry_size
205
magic = ([TC_COMPILED_ENTRY | 0] - (offset + length_of_CALL_instruction))
209
#define COMPILER_PROCESSOR_TYPE COMPILER_IA32_TYPE
211
/* The i387 coprocessor and i486 use 80-bit extended format internally. */
213
#define COMPILER_TEMP_SIZE 3
215
typedef unsigned short format_word;
217
/* i386 instructions can be aligned on any byte boundary. */
219
#define PC_ZERO_BITS 0
221
/* See the encodings above. */
223
#define ENTRY_PREFIX_LENGTH 3
225
# define COMPILED_CLOSURE_ENTRY_SIZE \
226
((2 * (sizeof (format_word))) + 6)
228
# define ADJUST_CLOSURE_AT_CALL(entry_point, location) \
230
long magic_constant; \
232
magic_constant = (* ((long *) (((char *) (entry_point)) + 3))); \
233
(location) = ((SCHEME_OBJECT) \
234
((((long) (OBJECT_ADDRESS (location))) + 5) + \
238
/* For the relocation of PC-relative JMP and CALL instructions.
239
This is used during GC/relocation, when the displacement
240
is incorrect, since it was computed with respect to the
241
location in old space.
244
extern long i386_pc_displacement_relocation;
246
#define EXTRACT_ADDRESS_FROM_DISPLACEMENT(var, instr_addr) do \
248
long displacement_address, new_displacement; \
250
displacement_address = (((long) (instr_addr)) + 1); \
251
new_displacement = ((* ((long *) displacement_address)) \
252
+ i386_pc_displacement_relocation); \
253
(* ((long *) displacement_address)) = new_displacement; \
254
(var) = ((SCHEME_OBJECT) \
255
((ADDR_TO_SCHEME_ADDR (displacement_address + 4)) \
256
+ new_displacement)); \
259
#define STORE_DISPLACEMENT_FROM_ADDRESS(target, instr_address) do \
261
long displacement_address = (((long) (instr_address)) + 1); \
262
(* ((long *) displacement_address)) = \
264
- (ADDR_TO_SCHEME_ADDR (displacement_address + 4))); \
267
#define BCH_EXTRACT_ADDRESS_FROM_DISPLACEMENT(var, v_addr, p_addr) do \
269
long displacement_address, new_displacement; \
271
displacement_address = (((long) (p_addr)) + 1); \
272
new_displacement = ((* ((long *) displacement_address)) \
273
+ i386_pc_displacement_relocation); \
274
(* ((long *) displacement_address)) = new_displacement; \
275
(var) = ((SCHEME_OBJECT) \
276
((ADDR_TO_SCHEME_ADDR (((long) (v_addr)) + 5)) \
277
+ new_displacement)); \
280
#define BCH_STORE_DISPLACEMENT_FROM_ADDRESS(target, v_addr, p_addr) do \
282
long displacement_address = (((long) (p_addr)) + 1); \
283
(* ((long *) displacement_address)) \
284
= (((long) (target)) \
285
- (ADDR_TO_SCHEME_ADDR (((long) (v_addr)) + 5))); \
288
#define START_CLOSURE_RELOCATION(scan) do \
290
SCHEME_OBJECT * _block, * _old; \
293
_block = ((SCHEME_OBJECT *) (scan)); \
294
_old = (OBJECT_ADDRESS (_block[(OBJECT_DATUM (*_block))])); \
295
_new = ((char *) (FIRST_MANIFEST_CLOSURE_ENTRY (_block + 1))); \
297
i386_pc_displacement_relocation = (((long) _old) - ((long) _new)); \
300
#define END_CLOSURE_RELOCATION(scan) i386_pc_displacement_relocation = 0
301
#define EXTRACT_CLOSURE_ENTRY_ADDRESS EXTRACT_ADDRESS_FROM_DISPLACEMENT
302
#define STORE_CLOSURE_ENTRY_ADDRESS STORE_DISPLACEMENT_FROM_ADDRESS
304
#define BCH_START_CLOSURE_RELOCATION(scan) do \
306
SCHEME_OBJECT * _scan, * _block, _old_obj, * _old; \
309
_scan = ((SCHEME_OBJECT *) (scan)); \
310
_block = ((SCHEME_OBJECT *) \
311
(SCAN_POINTER_TO_NEWSPACE_ADDRESS (_scan))); \
312
READ_NEWSPACE_ADDRESS (_old_obj, \
313
(_block + (OBJECT_DATUM (* _scan)))); \
314
_old = (OBJECT_ADDRESS (_old_obj)); \
315
_new = ((char *) (FIRST_MANIFEST_CLOSURE_ENTRY (_scan + 1))); \
317
i386_pc_displacement_relocation \
319
- ((long) (SCAN_POINTER_TO_NEWSPACE_ADDRESS (_new)))); \
322
#define BCH_END_CLOSURE_RELOCATION END_CLOSURE_RELOCATION
324
#define BCH_EXTRACT_CLOSURE_ENTRY_ADDRESS(var, p_addr) do \
326
SCHEME_OBJECT * _p_addr, * _v_addr; \
328
_p_addr = ((SCHEME_OBJECT *) (p_addr)); \
329
_v_addr = ((SCHEME_OBJECT *) \
330
(SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr))); \
332
BCH_EXTRACT_ADDRESS_FROM_DISPLACEMENT (var, _v_addr, _p_addr); \
335
#define BCH_STORE_CLOSURE_ENTRY_ADDRESS(target, p_addr) do \
337
SCHEME_OBJECT * _p_addr, * _v_addr; \
339
_p_addr = ((SCHEME_OBJECT *) (p_addr)); \
340
_v_addr = ((SCHEME_OBJECT *) \
341
(SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr))); \
343
BCH_STORE_DISPLACEMENT_FROM_ADDRESS (target, _v_addr, _p_addr); \
346
#define EXECUTE_CACHE_ENTRY_SIZE 2
348
#define FIRST_OPERATOR_LINKAGE_OFFSET 2
350
#define EXTRACT_EXECUTE_CACHE_ARITY(target, address) do \
352
(target) = ((long) (* ((unsigned short *) (address)))); \
355
#define EXTRACT_EXECUTE_CACHE_SYMBOL(target, address) do \
357
(target) = (* (((SCHEME_OBJECT *) (address)) + 1)); \
360
/* This is used during GC/relocation.
361
The displacement stored in the instruction refers to the old space
365
#define EXTRACT_OPERATOR_LINKAGE_ADDRESS(target, address) do \
367
EXTRACT_ADDRESS_FROM_DISPLACEMENT (target, \
368
(((long) (address)) + 3)); \
371
/* This is used when not relocating.
372
The displacement refers to the current location of the instruction.
375
#define EXTRACT_EXECUTE_CACHE_ADDRESS(loc, cache_addr) do \
377
long displacement_address, displacement; \
379
displacement_address = (((long) (cache_addr)) + 4); \
380
displacement = (* ((long *) displacement_address)); \
381
(loc) = ((SCHEME_OBJECT) \
382
((displacement_address + 4) + displacement)); \
385
#define STORE_EXECUTE_CACHE_ADDRESS(address, entry_address) do \
387
STORE_DISPLACEMENT_FROM_ADDRESS (entry_address, \
388
(((long) (address)) + 3)); \
391
#define STORE_EXECUTE_CACHE_CODE(address) do \
393
/* Store a <JMP rel32> opcode. */ \
394
(* (((unsigned char *) (address)) + 3)) = 0xe9; \
397
#define START_OPERATOR_RELOCATION(scan) do \
399
SCHEME_OBJECT * _scan, * _old, _loc; \
401
_scan = (((SCHEME_OBJECT *) (scan)) + 1); \
402
_old = ((SCHEME_OBJECT *) (* _scan)); \
403
_loc = (ADDR_TO_SCHEME_ADDR (_scan)); \
406
i386_pc_displacement_relocation = (((long) _old) - ((long) _loc)); \
409
#define END_OPERATOR_RELOCATION(scan) i386_pc_displacement_relocation = 0
411
#define BCH_START_OPERATOR_RELOCATION(scan) do \
413
SCHEME_OBJECT * _scan, * _old, _loc; \
415
_scan = (((SCHEME_OBJECT *) (scan)) + 1); \
416
_old = ((SCHEME_OBJECT *) (* _scan)); \
417
_loc = (ADDR_TO_SCHEME_ADDR \
418
(SCAN_POINTER_TO_NEWSPACE_ADDRESS (_scan))); \
421
i386_pc_displacement_relocation = (((long) _old) - ((long) _loc)); \
424
#define BCH_END_OPERATOR_RELOCATION END_OPERATOR_RELOCATION
426
#define BCH_EXTRACT_OPERATOR_LINKAGE_ADDRESS(var, p_addr) do \
428
SCHEME_OBJECT * _p_addr, * _v_addr; \
430
_p_addr = ((SCHEME_OBJECT *) (((long) (p_addr)) + 3)); \
431
_v_addr = ((SCHEME_OBJECT *) \
432
(SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr))); \
434
BCH_EXTRACT_ADDRESS_FROM_DISPLACEMENT (var, _v_addr, _p_addr); \
437
#define BCH_STORE_OPERATOR_LINKAGE_ADDRESS(e_addr, p_addr) do \
439
SCHEME_OBJECT * _p_addr, * _v_addr; \
441
_p_addr = ((SCHEME_OBJECT *) (((long) (p_addr)) + 3)); \
442
_v_addr = ((SCHEME_OBJECT *) \
443
(SCAN_POINTER_TO_NEWSPACE_ADDRESS (_p_addr))); \
445
BCH_STORE_DISPLACEMENT_FROM_ADDRESS (e_addr, _v_addr, _p_addr); \
448
#define TRAMPOLINE_ENTRY_SIZE 3
449
#define TRAMPOLINE_BLOCK_TO_ENTRY 3 /* MNV to MOV instr. */
451
#define STORE_TRAMPOLINE_ENTRY(entry_address, index) do \
453
unsigned char *PC = ((unsigned char *) (entry_address)); \
455
*PC++ = 0xb0; /* MOV AL,byte */ \
456
*PC++ = ((unsigned char) (index)); /* byte value */ \
457
*PC++ = 0xff; /* CALL */ \
458
*PC++ = 0x96; /* /2 disp32(ESI) */ \
459
(* ((unsigned long *) PC)) = ESI_TRAMPOLINE_TO_INTERFACE_OFFSET; \
460
IA32_CACHE_SYNCHRONIZE (); \
463
#define TRAMPOLINE_ENTRY_POINT(tramp_block) \
464
(((SCHEME_OBJECT *) (tramp_block)) + TRAMPOLINE_BLOCK_TO_ENTRY)
466
#define TRAMPOLINE_STORAGE(tramp_entry) \
467
((((SCHEME_OBJECT *) (tramp_entry)) - TRAMPOLINE_BLOCK_TO_ENTRY) + \
468
(2 + TRAMPOLINE_ENTRY_SIZE))
470
#define FLUSH_I_CACHE() do \
472
IA32_CACHE_SYNCHRONIZE (); \
475
#define FLUSH_I_CACHE_REGION(address, nwords) do \
477
IA32_CACHE_SYNCHRONIZE (); \
480
#define PUSH_D_CACHE_REGION(address, nwords) do \
482
IA32_CACHE_SYNCHRONIZE (); \
486
/* These must aggree with cmpaux-i386.m4!
487
The register block is actually allocated there.
490
#define COMPILER_REGBLOCK_N_FIXED 16
492
#define COMPILER_REGBLOCK_N_HOOKS 80
494
/* A hook is the address (offset) of an assembly-language routine. */
496
#define COMPILER_HOOK_SIZE 1
498
#define COMPILER_REGBLOCK_EXTRA_SIZE \
499
(COMPILER_REGBLOCK_N_HOOKS * COMPILER_HOOK_SIZE)
501
#define REGBLOCK_ALLOCATED_BY_INTERFACE
503
#define ESI_TRAMPOLINE_TO_INTERFACE_OFFSET \
504
((COMPILER_REGBLOCK_N_FIXED + (2 * COMPILER_HOOK_SIZE)) * \
505
(sizeof (SCHEME_OBJECT)))
511
# define VM_PROT_SCHEME (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
514
long i386_pc_displacement_relocation = 0;
516
#define ASM_RESET_HOOK i386_reset_hook
518
#ifndef HOOK_TO_SCHEME_OFFSET
519
# define HOOK_TO_SCHEME_OFFSET(hook) ((unsigned long) (hook))
523
# define STRINGIFY(x) #x
525
# define STRINGIFY(x) "x"
528
#define SETUP_REGISTER(hook) do \
530
extern void hook (); \
532
(* ((unsigned long *) (esi_value + offset))) = \
533
(HOOK_TO_SCHEME_OFFSET (hook)); \
534
offset += (COMPILER_HOOK_SIZE * (sizeof (SCHEME_OBJECT))); \
535
declare_builtin (((unsigned long) hook), (STRINGIFY (hook))); \
539
DEFUN_VOID (i386_reset_hook)
541
extern int EXFUN (ASM_ENTRY_POINT(i386_interface_initialize), (void));
542
extern void EXFUN (declare_builtin, (unsigned long, char *));
543
int offset = (COMPILER_REGBLOCK_N_FIXED * (sizeof (SCHEME_OBJECT)));
544
unsigned char * esi_value = ((unsigned char *) (&Registers[0]));
545
int fp_support_present = (i386_interface_initialize ());
547
/* These must match machines/i386/lapgen.scm */
549
SETUP_REGISTER (asm_scheme_to_interface); /* 0 */
550
SETUP_REGISTER (asm_scheme_to_interface_call); /* 1 */
552
if (offset != ESI_TRAMPOLINE_TO_INTERFACE_OFFSET)
554
outf_fatal ("\ni386_reset_hook: ESI_TRAMPOLINE_TO_INTERFACE_OFFSET\n");
555
Microcode_Termination (TERM_EXIT);
557
SETUP_REGISTER (asm_trampoline_to_interface); /* 2 */
559
SETUP_REGISTER (asm_interrupt_procedure); /* 3 */
560
SETUP_REGISTER (asm_interrupt_continuation); /* 4 */
561
SETUP_REGISTER (asm_interrupt_closure); /* 5 */
562
SETUP_REGISTER (asm_interrupt_dlink); /* 6 */
564
SETUP_REGISTER (asm_primitive_apply); /* 7 */
565
SETUP_REGISTER (asm_primitive_lexpr_apply); /* 8 */
566
SETUP_REGISTER (asm_assignment_trap); /* 9 */
567
SETUP_REGISTER (asm_reference_trap); /* 10 */
568
SETUP_REGISTER (asm_safe_reference_trap); /* 11 */
569
SETUP_REGISTER (asm_link); /* 12 */
570
SETUP_REGISTER (asm_error); /* 13 */
571
SETUP_REGISTER (asm_primitive_error); /* 14 */
572
SETUP_REGISTER (asm_short_primitive_apply); /* 15 */
574
/* No more room for positive offsets without going to 32-bit
578
/* This is a hack to make all the hooks be addressable
579
with byte offsets (instead of longword offsets).
580
The register block extends to negative offsets as well,
581
so all the following hooks are accessed with negative
582
offsets, and all fit in a byte.
587
if (fp_support_present != 0)
589
SETUP_REGISTER (asm_generic_add); /* -32 */
590
SETUP_REGISTER (asm_generic_subtract); /* -31 */
591
SETUP_REGISTER (asm_generic_multiply); /* -30 */
592
SETUP_REGISTER (asm_generic_divide); /* -29 */
593
SETUP_REGISTER (asm_generic_equal); /* -28 */
594
SETUP_REGISTER (asm_generic_less); /* -27 */
595
SETUP_REGISTER (asm_generic_greater); /* -26 */
596
SETUP_REGISTER (asm_generic_increment); /* -25 */
597
SETUP_REGISTER (asm_generic_decrement); /* -24 */
598
SETUP_REGISTER (asm_generic_zero); /* -23 */
599
SETUP_REGISTER (asm_generic_positive); /* -22 */
600
SETUP_REGISTER (asm_generic_negative); /* -21 */
601
SETUP_REGISTER (asm_generic_quotient); /* -20 */
602
SETUP_REGISTER (asm_generic_remainder); /* -19 */
603
SETUP_REGISTER (asm_generic_modulo); /* -18 */
607
SETUP_REGISTER (asm_nofp_add); /* -32 */
608
SETUP_REGISTER (asm_nofp_subtract); /* -31 */
609
SETUP_REGISTER (asm_nofp_multiply); /* -30 */
610
SETUP_REGISTER (asm_nofp_divide); /* -29 */
611
SETUP_REGISTER (asm_nofp_equal); /* -28 */
612
SETUP_REGISTER (asm_nofp_less); /* -27 */
613
SETUP_REGISTER (asm_nofp_greater); /* -26 */
614
SETUP_REGISTER (asm_nofp_increment); /* -25 */
615
SETUP_REGISTER (asm_nofp_decrement); /* -24 */
616
SETUP_REGISTER (asm_nofp_zero); /* -23 */
617
SETUP_REGISTER (asm_nofp_positive); /* -22 */
618
SETUP_REGISTER (asm_nofp_negative); /* -21 */
619
SETUP_REGISTER (asm_nofp_quotient); /* -20 */
620
SETUP_REGISTER (asm_nofp_remainder); /* -19 */
621
SETUP_REGISTER (asm_nofp_modulo); /* -18 */
624
SETUP_REGISTER (asm_sc_apply); /* -17 */
625
SETUP_REGISTER (asm_sc_apply_size_1); /* -16 */
626
SETUP_REGISTER (asm_sc_apply_size_2); /* -15 */
627
SETUP_REGISTER (asm_sc_apply_size_3); /* -14 */
628
SETUP_REGISTER (asm_sc_apply_size_4); /* -13 */
629
SETUP_REGISTER (asm_sc_apply_size_5); /* -12 */
630
SETUP_REGISTER (asm_sc_apply_size_6); /* -11 */
631
SETUP_REGISTER (asm_sc_apply_size_7); /* -10 */
632
SETUP_REGISTER (asm_sc_apply_size_8); /* -9 */
633
SETUP_REGISTER (asm_interrupt_continuation_2); /* -8 */
634
if (ia32_cpuid_needed)
636
SETUP_REGISTER (asm_serialize_cache); /* -7 */
640
SETUP_REGISTER (asm_dont_serialize_cache); /* -7 */
649
vm_inherit_t inheritance;
654
addr = ((vm_address_t) Heap);
655
if ((vm_region ((task_self ()), &addr, &size, &prot, &max_prot,
656
&inheritance, &shared, &object, &offset))
659
outf_fatal ( "compiler_reset: vm_region() failed.\n");
660
Microcode_Termination (TERM_EXIT);
663
if ((prot & VM_PROT_SCHEME) != VM_PROT_SCHEME)
665
if ((max_prot & VM_PROT_SCHEME) != VM_PROT_SCHEME)
668
"compiler_reset: inadequate protection for Heap.\n");
669
outf_fatal ( "maximum = 0x%lx; desired = 0x%lx\n",
670
((unsigned long) (max_prot & VM_PROT_SCHEME)),
671
((unsigned long) VM_PROT_SCHEME));
672
Microcode_Termination (TERM_EXIT);
675
if ((vm_protect ((task_self ()), ((vm_address_t) Heap),
676
(((char *) Constant_Top) - ((char *) Heap)),
681
"compiler_reset: unable to change protection for Heap.\n");
682
outf_fatal ( "actual = 0x%lx; desired = 0x%lx\n",
683
((unsigned long) (prot & VM_PROT_SCHEME)),
684
((unsigned long) VM_PROT_SCHEME));
685
Microcode_Termination (TERM_EXIT);
690
#endif /* _MACH_UNIX */
693
#endif /* IN_CMPINT_C */
695
/* Derived parameters and macros.
696
These macros expect the above definitions to be meaningful.
697
If they are not, the macros below may have to be changed as well.
700
#define COMPILED_ENTRY_OFFSET_WORD(entry) \
701
(((format_word *) (entry))[-1])
702
#define COMPILED_ENTRY_FORMAT_WORD(entry) \
703
(((format_word *) (entry))[-2])
705
/* The next one assumes 2's complement integers....*/
706
#define CLEAR_LOW_BIT(word) ((word) & ((unsigned long) -2))
707
#define OFFSET_WORD_CONTINUATION_P(word) (((word) & 1) != 0)
709
#if (PC_ZERO_BITS == 0)
710
/* Instructions aligned on byte boundaries */
711
#define BYTE_OFFSET_TO_OFFSET_WORD(offset) ((offset) << 1)
712
#define OFFSET_WORD_TO_BYTE_OFFSET(offset_word) \
713
((CLEAR_LOW_BIT(offset_word)) >> 1)
716
#if (PC_ZERO_BITS == 1)
717
/* Instructions aligned on word (16 bit) boundaries */
718
#define BYTE_OFFSET_TO_OFFSET_WORD(offset) (offset)
719
#define OFFSET_WORD_TO_BYTE_OFFSET(offset_word) \
720
(CLEAR_LOW_BIT(offset_word))
723
#if (PC_ZERO_BITS >= 2)
724
/* Should be OK for =2, but bets are off for >2 because of problems
727
#define SHIFT_AMOUNT (PC_ZERO_BITS - 1)
728
#define BYTE_OFFSET_TO_OFFSET_WORD(offset) ((offset) >> (SHIFT_AMOUNT))
729
#define OFFSET_WORD_TO_BYTE_OFFSET(offset_word) \
730
((CLEAR_LOW_BIT(offset_word)) << (SHIFT_AMOUNT))
733
#define MAKE_OFFSET_WORD(entry, block, continue) \
734
((BYTE_OFFSET_TO_OFFSET_WORD(((char *) (entry)) - \
735
((char *) (block)))) | \
736
((continue) ? 1 : 0))
738
#if (EXECUTE_CACHE_ENTRY_SIZE == 2)
739
#define EXECUTE_CACHE_COUNT_TO_ENTRIES(count) \
741
#define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries) \
745
#if (EXECUTE_CACHE_ENTRY_SIZE == 4)
746
#define EXECUTE_CACHE_COUNT_TO_ENTRIES(count) \
748
#define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries) \
752
#if (!defined(EXECUTE_CACHE_COUNT_TO_ENTRIES))
753
#define EXECUTE_CACHE_COUNT_TO_ENTRIES(count) \
754
((count) / EXECUTE_CACHE_ENTRY_SIZE)
755
#define EXECUTE_CACHE_ENTRIES_TO_COUNT(entries) \
756
((entries) * EXECUTE_CACHE_ENTRY_SIZE)
759
/* The first entry in a cc block is preceeded by 2 headers (block and nmv),
760
a format word and a gc offset word. See the early part of the
761
TRAMPOLINE picture, above.
764
#define CC_BLOCK_FIRST_ENTRY_OFFSET \
765
(2 * ((sizeof(SCHEME_OBJECT)) + (sizeof(format_word))))
769
#define FORMAT_BYTE_EXPR 0xFF
770
#define FORMAT_BYTE_COMPLR 0xFE
771
#define FORMAT_BYTE_CMPINT 0xFD
772
#define FORMAT_BYTE_DLINK 0xFC
773
#define FORMAT_BYTE_RETURN 0xFB
775
#define FORMAT_WORD_EXPR (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_EXPR))
776
#define FORMAT_WORD_CMPINT (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_CMPINT))
777
#define FORMAT_WORD_RETURN (MAKE_FORMAT_WORD(0xFF, FORMAT_BYTE_RETURN))
779
/* This assumes that a format word is at least 16 bits,
780
and the low order field is always 8 bits.
783
#define MAKE_FORMAT_WORD(field1, field2) \
784
(((field1) << 8) | ((field2) & 0xff))
786
#define SIGN_EXTEND_FIELD(field, size) \
787
(((field) & ((1 << (size)) - 1)) | \
788
((((field) & (1 << ((size) - 1))) == 0) ? 0 : \
791
#define FORMAT_WORD_LOW_BYTE(word) \
792
(SIGN_EXTEND_FIELD((((unsigned long) (word)) & 0xff), 8))
794
#define FORMAT_WORD_HIGH_BYTE(word) \
795
(SIGN_EXTEND_FIELD((((unsigned long) (word)) >> 8), \
796
(((sizeof (format_word)) * CHAR_BIT) - 8)))
798
#define COMPILED_ENTRY_FORMAT_HIGH(addr) \
799
(FORMAT_WORD_HIGH_BYTE(COMPILED_ENTRY_FORMAT_WORD(addr)))
801
#define COMPILED_ENTRY_FORMAT_LOW(addr) \
802
(FORMAT_WORD_LOW_BYTE(COMPILED_ENTRY_FORMAT_WORD(addr)))
804
#define FORMAT_BYTE_FRAMEMAX 0x7f
806
#define COMPILED_ENTRY_MAXIMUM_ARITY COMPILED_ENTRY_FORMAT_LOW
807
#define COMPILED_ENTRY_MINIMUM_ARITY COMPILED_ENTRY_FORMAT_HIGH
809
#endif /* not SCM_CMPINTMD_H */