source: trunk/source/lisp-kernel/x86-constants64.h @ 15093

Last change on this file since 15093 was 15093, checked in by gb, 8 years ago

New Linux ARM binaries.

The image and FASL versions changed on the ARM, but (if I did it right)
not on other platforms.

(The image and FASL versions are now architecture-specific. This may
make it somewhat easier and less disruptive to change them, since the
motivation for such a change is often also architecture-specific.)
The FASL and current image version are defined (in the "TARGET" package)
in the architecture-specific *-arch.lisp files; the min, max, and current
image versions are defined in the *constants*.h file for the architecture.

Most of the changes are ARM-specific.

Each TCR now contains a 256-word table at byte offset 256. (We've
been using about 168 bytes in the TCR, so there are still 88 bytes/22
words left for expansion.) The table is initialized at TCR-creation
time to contain the absolute addresses of the subprims (there are
currently around 130 defined); we try otherwise not to reference
subprims by absolute address. Jumping to a subprim is:

(ldr pc (:@ rcontext (:$ offset-of-subprim-in-tcr-table)))

and calling one involves loading its address from that table into a
register and doing (blx reg). We canonically use LR as the register,
since it's going to be clobbered by the blx anyway and there doesn't
seem to be a performance hazard there. The old scheme (which involved
using BA and BLA pseudoinstructions to jump to/call a hidden jump table
at the end of the function) is no longer supported.

ARM Subprims no longer need to be aligned (on anything more than an
instruction boundary.) Some remnants of the consequences of an old
scheme (where subprims had to "fit" in small regions and sometimes
had to jump out of line if they would overflow that region's bounds)
still remain, but we can repair that (and it'll be a bit more straightforward
to add new ARM subprims.) We no longer care (much) about where subprims
are mapped in memory, and don't have to bias suprimitive addresses by
a platform-specific constant (and have to figure out whether or not we've
already done so) on (e.g.) Android.

Rather than setting the first element (fn.entrypoint) of a
newly-created function to the (absolute) address of a subprim that updates
that entrypoint on the first call, we use a little LAP function to correct
the address before the function can be called.

Non-function objects that can be stored in symbols' function cells
(the UNDEFINED-FUNCTION object, the things that encapsulate
special-operator names and global macro-functions) need to be
structured like FUNCTIONS: the need to have a word-aligned entrypoint
in element 0 that tracks the CODE-VECTOR object in element 1. We
don't want these things to be of type FUNCTION, but do want the GC to
adjust the entrypoint if the codevector moves. We've been essentially
out of GVECTOR subtags on 32-bit platforms, largely because of the
constraints that vector/array subtags must be greater than other
subtags and numeric types be less. The first constraint is probably
reasonable, but the second isn't: other typecodes (tag-list, etc) may
be less than the maximum numeric typecode, so tests like NUMBERP can't
reliably involve a simple comparison. (As long as a mask of all
numeric typecodes will fit in a machine word/FIXNUM, a simple LOGBITP
test can be used instead.) Removed all portable and ARM-specific code
that made assumptions about numeric typecode ordering, made a few more
gvector typecodes available, and used one of them to define a new
"pseudofunction" type. Made the GC update the entrypoints of
pseudofunctions and used them for the undefined-function object and
for the function cells of macros/special-operators.

Since we don't need the subprim jump table at the end of each function
anymore, we can more easily revive the idea of embedded pc-relative
constant data ("constant pools") and initialize FPRs from constant
data, avoiding most remaining traffic between FPRs and GPRs.

I've had a fairly-reproducible cache-coherency problem: on the first
GC in the cold load, the thread misbehaves mysteriously when it
resumes. The GC tries to synchronize the I and D caches on the entire
range of addresses that may contain newly-moved code-vectors. I'm not
at all sure why, but walking that range and flushing the cache for
each code-vector individually seems to avoid the problem (and may actually
be faster.)

Fix ticket:894

Fixed a few typos in error messages/comments/etc.

I -think- that the non-ARM-specific changes (how FASL/image versions are
defined) should bootstrap cleanly, but won't know for sure until this is
committed. (I imagine that the buildbot will complain if not.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/*
2   Copyright (C) 2005-2009 Clozure Associates
3   This file is part of Clozure CL. 
4
5   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with Clozure CL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with Clozure CL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   Clozure CL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16
17#include "x86-constants.h"
18
19#ifdef DARWIN
20#define REG_RAX 0
21#define REG_RBX 1
22#define REG_RCX 2
23#define REG_RDX 3
24#define REG_RDI 4
25#define REG_RSI 5
26#define REG_RBP 6
27#define REG_RSP 7
28#define REG_R8 8
29#define REG_R9 9
30#define REG_R10 10
31#define REG_R11 11
32#define REG_R12 12
33#define REG_R13 13
34#define REG_R14 14
35#define REG_R15 15
36#define REG_RIP 16
37#define REG_RFL 17
38#endif
39
40#ifdef FREEBSD
41#define REG_RDI 1
42#define REG_RSI 2
43#define REG_RDX 3
44#define REG_RCX 4
45#define REG_R8 5
46#define REG_R9 6
47#define REG_RAX 7
48#define REG_RBX 8
49#define REG_RBP 9
50#define REG_R10 10
51#define REG_R11 11
52#define REG_R12 12
53#define REG_R13 13
54#define REG_R14 14
55#define REG_R15 15
56#define REG_RIP 20
57#define REG_RFL 22
58#define REG_RSP 23
59#endif
60
61#ifdef WIN_64
62/* DWORD64 indices in &(CONTEXT->Rax) */
63#define REG_RAX     0
64#define REG_RCX     1
65#define REG_RDX     2
66#define REG_RBX     3
67#define REG_RSP     4
68#define REG_RBP     5
69#define REG_RSI     6
70#define REG_RDI     7
71#define REG_R8      8
72#define REG_R9      9
73#define REG_R10     10
74#define REG_R11     11
75#define REG_R12     12
76#define REG_R13     13
77#define REG_R14     14
78#define REG_R15     15
79#define REG_RIP     16
80#endif
81
82/* Define indices of the GPRs in the mcontext component of a ucontext */
83#define Itemp0      REG_RBX
84#define Iarg_y      REG_RDI
85#define Iarg_x      REG_R8
86#define Iarg_z      REG_RSI
87#define Isave3      REG_R11
88#define Isave2      REG_R12
89#define Isave1      REG_R14
90#define Isave0      REG_R15
91#define Itemp2        REG_R10
92#define Ifn         REG_R13
93#define Irbp        REG_RBP
94#define Iimm0       REG_RAX
95#define Iimm1       REG_RDX
96#define Iimm2       REG_RCX
97#define Itemp1      REG_R9
98#define Isp         REG_RSP
99#define Iip         REG_RIP
100#if defined(LINUX) || defined(WINDOWS)
101#define Iflags      REG_EFL
102#endif
103
104#if defined(SOLARIS) || defined(FREEBSD) || defined(DARWIN)
105#define Iflags      REG_RFL
106#endif
107
108
109#define Iallocptr Itemp0
110#define Ira0 Itemp2
111#define Inargs Iimm2
112#define Ixfn Itemp1
113#define Ifp Irbp
114
115
116#define nbits_in_word 64L
117#define log2_nbits_in_word 6L
118#define nbits_in_byte 8L
119#define ntagbits 4L
120#define nlisptagbits 3L
121#define nfixnumtagbits 2L
122#define num_subtag_bits 8L
123#define fixnumshift 3L
124#define fixnum_shift 3L
125#define fulltagmask 15L
126#define tagmask  7L
127#define fixnummask 3
128#define subtagmask ((1L<<num_subtag_bits)-1L)
129#define ncharcodebits 8L
130#define charcode_shift 8L
131#define node_size 8L
132#define node_shift 3L
133#define nargregs 3L
134
135#define tag_fixnum 0L
136#define tag_imm_0 1L            /* subtag_single_float ONLY */
137#define tag_imm_1 2L            /* subtag_character, internal markers */
138#define tag_list 3L             /* subtag_cons or NIL */
139#define tag_tra 4L              /* tagged return_address */
140#define tag_misc 5L             /* random uvector */
141#define tag_symbol 6L           /* non-null symbol */
142#define tag_function 7L /* function entry point */
143
144#define fulltag_even_fixnum 0L
145#define fulltag_imm_0 1L
146#define fulltag_imm_1 2L
147#define fulltag_cons 3L
148#define fulltag_tra_0 4L
149#define fulltag_nodeheader_0 5L
150#define fulltag_nodeheader_1 6L
151#define fulltag_immheader_0 7L
152#define fulltag_odd_fixnum 8L
153#define fulltag_immheader_1 9L
154#define fulltag_immheader_2 10L
155#define fulltag_nil 11L
156#define fulltag_tra_1 12L
157#define fulltag_misc 13L
158#define fulltag_symbol 14L
159#define fulltag_function 15L
160
161#define SUBTAG(tag,subtag) ((tag) | ((subtag) << ntagbits))
162#define subtag_arrayH SUBTAG(fulltag_nodeheader_0,10L)
163#define subtag_vectorH SUBTAG(fulltag_nodeheader_1,10L)
164#define subtag_simple_vector SUBTAG(fulltag_nodeheader_1,11L)
165#define min_vector_subtag subtag_vectorH       
166
167#define ivector_class_64_bit fulltag_immheader_2
168#define ivector_class_32_bit fulltag_immheader_1
169#define ivector_class_other_bit fulltag_immheader_0
170
171
172#define subtag_fixnum_vector SUBTAG(ivector_class_64_bit,12L)
173#define subtag_s64_vector SUBTAG(ivector_class_64_bit,13L)
174#define subtag_u64_vector SUBTAG(ivector_class_64_bit,14L)
175#define subtag_double_float_vector SUBTAG(ivector_class_64_bit,15L)
176
177#define subtag_simple_base_string SUBTAG(ivector_class_32_bit,12L)
178#define subtag_s32_vector SUBTAG(ivector_class_32_bit,13L)
179#define subtag_u32_vector SUBTAG(ivector_class_32_bit,14L)
180#define subtag_single_float_vector SUBTAG(ivector_class_32_bit,15L)
181
182#define subtag_s16_vector SUBTAG(ivector_class_other_bit,10L)
183#define subtag_u16_vector SUBTAG(ivector_class_other_bit,11L)
184#define subtag_s8_vector SUBTAG(ivector_class_other_bit,13L)
185#define subtag_u8_vector SUBTAG(ivector_class_other_bit,14L)
186#define subtag_bit_vector SUBTAG(ivector_class_other_bit,15L)
187/* min_8_bit_ivector_subtag is the old 8-bit simple_base_string */
188#define min_8_bit_ivector_subtag SUBTAG(ivector_class_other_bit,12L)
189
190/* There's some room for expansion in non-array ivector space. */
191#define subtag_macptr SUBTAG(ivector_class_64_bit,1)
192#define subtag_dead_macptr SUBTAG(ivector_class_64_bit,2)
193#define subtag_bignum SUBTAG(ivector_class_32_bit,0)
194#define subtag_double_float SUBTAG(ivector_class_32_bit,1)
195#define subtag_xcode_vector SUBTAG(ivector_class_32_bit,2)
196
197/* Note the difference between (e.g) fulltag_function - which
198   defines what the low 4 bytes of a function pointer look like -
199   and subtag_function - which describes what the subtag byte
200   in a function header looks like.  (Likewise for fulltag_symbol
201   and subtag_symbol)
202*/             
203
204#define subtag_symbol SUBTAG(fulltag_nodeheader_0,1)
205#define subtag_catch_frame SUBTAG(fulltag_nodeheader_0,2)
206#define subtag_hash_vector SUBTAG(fulltag_nodeheader_0,3)
207#define subtag_pool SUBTAG(fulltag_nodeheader_0,4)
208#define subtag_weak SUBTAG(fulltag_nodeheader_0,5)
209#define subtag_package SUBTAG(fulltag_nodeheader_0,6)
210#define subtag_slot_vector SUBTAG(fulltag_nodeheader_0,7)
211#define subtag_basic_stream SUBTAG(fulltag_nodeheader_0,8)
212#define subtag_function SUBTAG(fulltag_nodeheader_0,9)
213
214#define subtag_ratio SUBTAG(fulltag_nodeheader_1,1)
215#define subtag_complex SUBTAG(fulltag_nodeheader_1,2)
216#define subtag_struct SUBTAG(fulltag_nodeheader_1,3)
217#define subtag_istruct SUBTAG(fulltag_nodeheader_1,4)
218#define subtag_value_cell SUBTAG(fulltag_nodeheader_1,5)
219#define subtag_xfunction SUBTAG(fulltag_nodeheader_1,6)
220#define subtag_lock SUBTAG(fulltag_nodeheader_1,7)
221#define subtag_instance SUBTAG(fulltag_nodeheader_1,8)
222
223
224
225#define nil_value ((0x13000+fulltag_nil)+(LOWMEM_BIAS))
226#define t_value ((0x13020+fulltag_symbol)+(LOWMEM_BIAS))
227#define misc_bias fulltag_misc
228#define cons_bias fulltag_cons
229
230       
231#define misc_header_offset -fulltag_misc
232#define misc_subtag_offset misc_header_offset       /* low byte of header */
233#define misc_data_offset misc_header_offset+node_size   /* first word of data */
234#define misc_dfloat_offset misc_header_offset           /* double-floats are doubleword-aligned */
235
236#define subtag_single_float SUBTAG(fulltag_imm_0,0)
237#define subtag_character SUBTAG(fulltag_imm_1,0)
238
239#define subtag_unbound SUBTAG(fulltag_imm_1,1)
240#define unbound_marker subtag_unbound
241#define undefined unbound_marker
242#define unbound unbound_marker
243#define subtag_slot_unbound SUBTAG(fulltag_imm_1,2)
244#define slot_unbound_marker subtag_slot_unbound
245#define slot_unbound slot_unbound_marker
246#define subtag_illegal SUBTAG(fulltag_imm_1,3)
247#define illegal_marker subtag_illegal
248#define subtag_no_thread_local_binding SUBTAG(fulltag_imm_1,4)
249#define no_thread_local_binding_marker subtag_no_thread_local_binding
250#define subtag_reserved_frame  SUBTAG(fulltag_imm_1,5)
251#define reserved_frame_marker subtag_reserved_frame
252#define subtag_forward_marker SUBTAG(fulltag_imm_1,6)
253
254#define function_boundary_marker SUBTAG(fulltag_imm_1,15)       
255
256/*
257 * To determine the function associated with a tagged return
258 * address, we attempt to recognize an the instruction
259 * (lea (@ disp (% rip)) (% fn)) at the tra.
260 */
261#define RECOVER_FN_FROM_RIP_LENGTH 7 /* the instruction is 7 bytes long */
262#define RECOVER_FN_FROM_RIP_DISP_OFFSET 3 /* displacement word is 3 bytes in */
263#define RECOVER_FN_FROM_RIP_WORD0 0x8d4c /* 0x4c 0x8d, little-endian */
264#define RECOVER_FN_FROM_RIP_BYTE2 0x2d  /* third byte of opcode */
265
266
267/* The objects themselves look something like this: */
268
269
270typedef struct double_float {
271  LispObj header;
272  LispObj value;
273} double_float;
274
275
276
277typedef struct lisp_frame {
278  struct lisp_frame *backlink;
279  LispObj tra;
280  LispObj xtra;                 /* if tra is nvalretn */
281} lisp_frame;
282
283/* These are created on the lisp stack by the exception callback mechanism,
284   but nothing ever returns to them.  (At the very least, nothing -should-
285   try to return to them ...).
286*/
287typedef struct exception_callback_frame {
288  struct lisp_frame *backlink;
289  LispObj tra;                  /* ALWAYS 0 FOR AN XCF */
290  LispObj nominal_function;     /* the current function at the time of the exception */
291  LispObj relative_pc;          /* Boxed byte offset within actual function */
292  LispObj containing_uvector;   /* the uvector that contains the relative PC or NIL */
293  LispObj xp;                   /* exception context */
294  LispObj ra0;                  /* value of ra0 from context */
295  LispObj foreign_sp;           /* foreign sp at the time that exception occurred */
296  LispObj prev_xframe;          /* so %apply-in-frame can unwind it */
297  LispObj pc_low;               /* fixnum low half of absolute pc */
298  LispObj pc_high;              /* and the high half */
299} xcf;
300
301
302
303/*
304  The GC also needs to know what a catch_frame looks like.
305*/
306
307typedef struct catch_frame {
308  LispObj header;
309  LispObj catch_tag;
310  LispObj link;
311  LispObj mvflag;
312  LispObj csp;
313  LispObj db_link;
314  LispObj regs[4];
315  LispObj xframe;
316  LispObj tsp_segment;
317} catch_frame;
318
319#define catch_frame_element_count ((sizeof(catch_frame)/sizeof(LispObj))-1)
320#define catch_frame_header make_header(subtag_catch_frame,catch_frame_element_count)
321
322
323/*
324  All exception frames in a thread are linked together
325  */
326typedef struct xframe_list {
327  ExceptionInformation *curr;
328  struct xframe_list *prev;
329} xframe_list;
330
331#define fixnum_bitmask(n)  (1LL<<((n)+fixnumshift))
332
333
334#include "lisp-errors.h"
335
336
337
338#define TCR_BIAS (0x0)
339
340typedef struct tcr {
341  struct tcr* next;
342  struct tcr* prev;
343  struct {
344    u32_t tag;
345    float f;
346  } single_float_convert;
347  struct tcr* linear;
348  LispObj *save_fp;            /* RBP when in foreign code */
349  u32_t lisp_mxcsr;
350  u32_t foreign_mxcsr;
351  special_binding* db_link;     /* special binding chain head */
352  LispObj catch_top;            /* top catch frame */
353  LispObj* save_vsp;  /* VSP when in foreign code */
354  LispObj* save_tsp;  /* TSP when in foreign code */
355  LispObj* foreign_sp;
356  struct area* cs_area; /* cstack area pointer */
357  struct area* vs_area; /* vstack area pointer */
358  struct area* ts_area; /* tstack area pointer */
359  LispObj cs_limit;             /* stack overflow limit */
360  natural bytes_allocated;
361  natural log2_allocation_quantum;      /* for per-thread consing */
362  signed_natural interrupt_pending;     /* pending interrupt flag */
363  xframe_list* xframe; /* exception-frame linked list */
364  int* errno_loc;               /* per-thread (?) errno location */
365  LispObj ffi_exception;        /* fpscr bits from ff-call */
366  LispObj osid;                 /* OS thread id */
367  signed_natural valence;                       /* odd when in foreign code */
368  signed_natural foreign_exception_status;      /* non-zero -> call lisp_exit_hook */
369  void* native_thread_info;     /* platform-dependent */
370  void* native_thread_id;       /* mach_thread_t, pid_t, etc. */
371  char *last_allocptr;
372  char *save_allocptr;
373  char *save_allocbase;
374  void* reset_completion;
375  void* activate;
376  signed_natural suspend_count;
377  ExceptionInformation* suspend_context;
378  ExceptionInformation* pending_exception_context;
379  void* suspend;                /* suspension semaphore */
380  void* resume;                 /* resumption semaphore */
381  natural flags;
382  ExceptionInformation* gc_context;
383  void* termination_semaphore;
384  signed_natural unwinding;
385  natural tlb_limit;
386  LispObj* tlb_pointer;
387  natural shutdown_count;
388  LispObj* next_tsp;
389  void *safe_ref_address;
390  void *pending_io_info;
391  void *io_datum;
392} TCR;
393
394#define t_offset (t_value-nil_value)
395
396typedef struct {
397  natural Rip;
398  natural Cs;                   /* in low 16 bits */
399  natural Rflags;               /* in low 32 bits */
400  natural Rsp;
401  natural Ss;                   /* in low 16 bits*/
402} x64_iret_frame;
403
404/*
405  These were previously global variables.  There are lots of implicit
406  assumptions about the size of a heap segment, so they might as well
407  be constants.
408*/
409
410#define heap_segment_size 0x00020000L
411#define log2_heap_segment_size 17L
412
413#define ABI_VERSION_MIN 1037
414#define ABI_VERSION_CURRENT 1037
415#define ABI_VERSION_MAX 1037
Note: See TracBrowser for help on using the repository browser.