/[cmucl]/src/lisp/amd64-arch.c
ViewVC logotype

Contents of /src/lisp/amd64-arch.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.9.12.1 - (hide annotations)
Mon Nov 2 14:29:46 2009 UTC (4 years, 5 months ago) by rtoy
Branch: amd64-dd-branch
Changes since 1.9: +31 -52 lines
File MIME type: text/plain
(Oops.  Previous checkin went to wrong branch.  Here is the commit
log, again.)

This large checkin brings the amd64 port up-to-date with the current
sources.  No real attempt has been made to make it work, but the
cross-compile does create a kernel.core, and the C code compiles (on
openSuSE 10.3).  The resulting kernel.core does not yet work.

Use cross-x86-amd64.lisp as the cross-compile script.  This is
intended to be cross-compiled using the 20a release for Linux, and
only supports x87.  The sse2 support has not be ported yet.

tools/cross-scripts/cross-x86-amd64.lisp:
o Update cross-compile with some missing constants, and frob new
  symbols.

tools/clean-target.sh:
o Remove amd64f files too.

code/pred.lisp:
o Define predicates for double-doubles for bootstrapping to work
  around recursive known function problems with these predicates.

code/sap.lisp:
o Define int-sap with (unsigned-byte 64) type declaration.  (May not
  be needed?)

code/unix-glibc2.lisp:
o Build fails defining map_failed to (int-sap -1).  Just hard-wire to
  0 for now so we can build.

compiler/float-tran.lisp:
o Add missing conditional for %complex-double-double-float.

compiler/amd64/float.lisp:
o Merge double-double support for amd64.  Not really tested yet.

compiler/amd64/parms.lisp:
o Update to match x86 build.  In particular, get the space address
  correct and update the static symbols.

compiler/amd64/type-vops.lisp:
o DYLAN-FUNCTION-HEADER-TYPE no longer exists.

compiler/amd64/vm.lisp:
o Add double-double storage classes and register definitions.

lisp/Config.amd64:
o Bring in line with Config.x86 and friends.

lisp/Linux-os.c:
o Bring amd64 code up-to-date with x86/linux code.

lisp/Linux-os.h
o Need to include sys/ucontext.h to get ucontext defined.  (Why?)
o Also define __USE_GNU so we get the register offsets in the ucontext
  defined.  (Why?)

lisp/amd64-arch.c:
o Change struct sigcontext to os_context_t.
o Use SC_PC instead of context->sc_pc.
o Merge some changes in from x86 version, like SC_EFLAGS.  May need
  more work.

lisp/amd64-assem.s:
o Use rbx instead of ebx for jmp.

lisp/amd64-lispregs.h:
o Define SC_REG, SC_PC, SC_SP using the new x86 style.

lisp/backtrace.c:
o Remove inline assembly for now until I figure out what the amd64
  version should be.

lisp/gencgc.c:
o Conditionalize out weak hash table support for now.

lisp/gencgc.h:
o Set PAGE_SIZE for amd64.  (Is 4096 right?)

lisp/globals.h:
o Export current_dynamic_space_free_pointer and
  current_auto_gc_trigger like for x86.
1 cwang 1.1 /* x86-arch.c -*- Mode: C; comment-column: 40 -*-
2     *
3 rtoy 1.9.12.1 * $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/amd64-arch.c,v 1.9.12.1 2009/11/02 14:29:46 rtoy Exp $
4 cwang 1.1 *
5     */
6    
7     #include <stdio.h>
8    
9     #include "lisp.h"
10     #include "globals.h"
11     #include "validate.h"
12     #include "os.h"
13     #include "internals.h"
14     #include "arch.h"
15 rtoy 1.9.12.1 #define __USE_GNU
16 cwang 1.1 #include "lispregs.h"
17     #include "signal.h"
18     #include "alloc.h"
19     #include "interrupt.h"
20     #include "interr.h"
21     #include "breakpoint.h"
22    
23     #define BREAKPOINT_INST 0xcc /* INT3 */
24    
25 rtoy 1.4 unsigned long fast_random_state = 1;
26 cwang 1.1
27 rtoy 1.4 char *
28 rtoy 1.8 arch_init(fpu_mode_t mode)
29 cwang 1.1 {
30 rtoy 1.4 return "lisp.core";
31 cwang 1.1 }
32 rtoy 1.4
33 cwang 1.1
34    
35     /*
36     * Assuming we get here via an INT3 xxx instruction, the PC now
37     * points to the interrupt code (lisp value) so we just move past
38     * it. Skip the code, then if the code is an error-trap or
39     * Cerror-trap then skip the data bytes that follow.
40     */
41    
42 rtoy 1.4 void
43 rtoy 1.9.12.1 arch_skip_instruction(os_context_t *context)
44 cwang 1.1 {
45 rtoy 1.4 int vlen, code;
46 cwang 1.1
47 rtoy 1.9.12.1 DPRINTF(0, (stderr, "[arch_skip_inst at %x>]\n", SC_PC(context)));
48 cwang 1.1
49 rtoy 1.4 /* Get and skip the lisp error code. */
50 rtoy 1.9.12.1 code = *(char *) SC_PC(context)++;
51 rtoy 1.4 switch (code) {
52     case trap_Error:
53     case trap_Cerror:
54     /* Lisp error arg vector length */
55 rtoy 1.9.12.1 vlen = *(char *) SC_PC(context)++;
56 rtoy 1.4 /* Skip lisp error arg data bytes */
57     while (vlen-- > 0)
58 rtoy 1.9.12.1 SC_PC(context)++;
59 rtoy 1.4 break;
60    
61     case trap_Breakpoint:
62     case trap_FunctionEndBreakpoint:
63     break;
64    
65     case trap_PendingInterrupt:
66     case trap_Halt:
67     /* Only needed to skip the Code. */
68     break;
69    
70     default:
71     fprintf(stderr, "[arch_skip_inst invalid code %d\n]\n", code);
72     break;
73 cwang 1.1 }
74    
75 rtoy 1.9.12.1 DPRINTF(0, (stderr, "[arch_skip_inst resuming at %x>]\n", SC_PC(context)));
76 cwang 1.1 }
77    
78 rtoy 1.4 unsigned char *
79 rtoy 1.9.12.1 arch_internal_error_arguments(os_context_t *context)
80 cwang 1.1 {
81 rtoy 1.9.12.1 return (unsigned char *) (SC_PC(context) + 1);
82 cwang 1.1 }
83    
84 rtoy 1.4 boolean
85 rtoy 1.9.12.1 arch_pseudo_atomic_atomic(os_context_t *context)
86 cwang 1.1 {
87 rtoy 1.4 return SymbolValue(PSEUDO_ATOMIC_ATOMIC);
88 cwang 1.1 }
89    
90 rtoy 1.4 void
91 rtoy 1.9.12.1 arch_set_pseudo_atomic_interrupted(os_context_t *context)
92 cwang 1.1 {
93 rtoy 1.4 SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1));
94 cwang 1.1 }
95 rtoy 1.4
96 cwang 1.1
97    
98 rtoy 1.4 unsigned long
99     arch_install_breakpoint(void *pc)
100 cwang 1.1 {
101 rtoy 1.4 unsigned long result = *(unsigned long *) pc;
102 cwang 1.1
103 rtoy 1.4 *(char *) pc = BREAKPOINT_INST; /* x86 INT3 */
104     *((char *) pc + 1) = trap_Breakpoint; /* Lisp trap code */
105    
106     return result;
107 cwang 1.1 }
108    
109 rtoy 1.4 void
110     arch_remove_breakpoint(void *pc, unsigned long orig_inst)
111 cwang 1.1 {
112 rtoy 1.4 *((char *) pc) = orig_inst & 0xff;
113     *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;
114 cwang 1.1 }
115 rtoy 1.4
116 cwang 1.1
117    
118     /*
119     * When single stepping single_stepping holds the original instruction
120     * pc location.
121     */
122    
123     unsigned int *single_stepping = NULL;
124 rtoy 1.4
125 cwang 1.1 #ifndef __linux__
126 rtoy 1.4 unsigned int single_step_save1;
127     unsigned int single_step_save2;
128     unsigned int single_step_save3;
129 cwang 1.1 #endif
130    
131 rtoy 1.4 void
132 rtoy 1.9.12.1 arch_do_displaced_inst(os_context_t *context, unsigned long orig_inst)
133 cwang 1.1 {
134 rtoy 1.9.12.1 unsigned int *pc = (unsigned int *) SC_PC(context);
135 cwang 1.1
136 rtoy 1.4 /*
137     * Put the original instruction back.
138     */
139 cwang 1.1
140 rtoy 1.4 *((char *) pc) = orig_inst & 0xff;
141     *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;
142 cwang 1.1
143 rtoy 1.9.12.1 #ifdef SC_EFLAGS
144     SC_EFLAGS(context) |= 0x100;
145 cwang 1.1 #else
146    
147 rtoy 1.4 /*
148     * Install helper instructions for the single step:
149     * pushf; or [esp],0x100; popf.
150     */
151    
152     single_step_save1 = *(pc - 3);
153     single_step_save2 = *(pc - 2);
154     single_step_save3 = *(pc - 1);
155     *(pc - 3) = 0x9c909090;
156     *(pc - 2) = 0x00240c81;
157     *(pc - 1) = 0x9d000001;
158 cwang 1.1 #endif
159    
160 rtoy 1.4 single_stepping = (unsigned int *) pc;
161 cwang 1.1
162     #ifndef __linux__
163 rtoy 1.9.12.1 (unsigned int *) SC_PC(context) = (char *) pc - 9;
164 cwang 1.1 #endif
165     }
166    
167    
168 rtoy 1.4 void
169     sigtrap_handler(HANDLER_ARGS)
170 cwang 1.1 {
171 rtoy 1.4 unsigned int trap;
172    
173 cwang 1.1 #if 0
174 rtoy 1.4 fprintf(stderr, "x86sigtrap: %8x %x\n",
175 rtoy 1.9.12.1 SC_PC(context), *(unsigned char *) (SC_PC(context) - 1));
176 rtoy 1.4 fprintf(stderr, "sigtrap(%d %d %x)\n", signal, code, context);
177 cwang 1.1 #endif
178    
179 rtoy 1.4 if (single_stepping && (signal == SIGTRAP)) {
180 cwang 1.1 #if 0
181 rtoy 1.4 fprintf(stderr, "* Single step trap %x\n", single_stepping);
182 cwang 1.1 #endif
183    
184 rtoy 1.9.12.1 #ifdef SC_EFLAGS
185     /* Disable single-stepping */
186     SC_EFLAGS(context) ^= 0x100;
187     #else
188 rtoy 1.4 /* Un-install single step helper instructions. */
189     *(single_stepping - 3) = single_step_save1;
190     *(single_stepping - 2) = single_step_save2;
191     *(single_stepping - 1) = single_step_save3;
192     #endif
193    
194     /*
195     * Re-install the breakpoint if possible.
196     */
197    
198 rtoy 1.9.12.1 if ((int) SC_PC(context) == (int) single_stepping + 1)
199 rtoy 1.4 fprintf(stderr, "* Breakpoint not re-install\n");
200     else {
201     char *ptr = (char *) single_stepping;
202    
203     ptr[0] = BREAKPOINT_INST; /* x86 INT3 */
204     ptr[1] = trap_Breakpoint;
205 cwang 1.1 }
206    
207 rtoy 1.4 single_stepping = NULL;
208     return;
209 cwang 1.1 }
210    
211 rtoy 1.4 /* This is just for info in case monitor wants to print an approx */
212 rtoy 1.9.12.1 current_control_stack_pointer = (unsigned long *) SC_SP(context);
213 cwang 1.1
214 rtoy 1.9.12.1 RESTORE_FPU(context);
215 rtoy 1.4 /*
216     * On entry %eip points just after the INT3 byte and aims at the
217     * 'kind' value (eg trap_Cerror). For error-trap and Cerror-trap a
218     * number of bytes will follow, the first is the length of the byte
219     * arguments to follow.
220     */
221    
222 rtoy 1.9.12.1 trap = *(unsigned char *) (SC_PC(context));
223 rtoy 1.4
224     switch (trap) {
225     case trap_PendingInterrupt:
226     DPRINTF(0, (stderr, "<trap Pending Interrupt.>\n"));
227     arch_skip_instruction(context);
228     interrupt_handle_pending(context);
229     break;
230    
231     case trap_Halt:
232     {
233 cwang 1.1 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
234 rtoy 1.4 int fpu_state[27];
235    
236     fpu_save(fpu_state);
237 cwang 1.1 #endif
238 rtoy 1.4 fake_foreign_function_call(context);
239     lose("%%primitive halt called; the party is over.\n");
240     undo_fake_foreign_function_call(context);
241 cwang 1.1 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
242 rtoy 1.4 fpu_restore(fpu_state);
243 cwang 1.1 #endif
244 rtoy 1.4 arch_skip_instruction(context);
245     break;
246     }
247    
248     case trap_Error:
249     case trap_Cerror:
250     DPRINTF(0, (stderr, "<trap Error %d>\n", code));
251 rtoy 1.9.12.1 interrupt_internal_error(signal, code, context, CODE(code) == trap_Cerror);
252 rtoy 1.4 break;
253 cwang 1.1
254 rtoy 1.4 case trap_Breakpoint:
255 cwang 1.1 #if 0
256 rtoy 1.4 fprintf(stderr, "*C break\n");
257 cwang 1.1 #endif
258 rtoy 1.9.12.1 SC_PC(context) -= 1;
259     handle_breakpoint(signal, CODE(code), context);
260 cwang 1.1 #if 0
261 rtoy 1.4 fprintf(stderr, "*C break return\n");
262 cwang 1.1 #endif
263 rtoy 1.4 break;
264    
265     case trap_FunctionEndBreakpoint:
266 rtoy 1.9.12.1 SC_PC(context) -= 1;
267     SC_PC(context) =
268 rtoy 1.4 (int) handle_function_end_breakpoint(signal, code, context);
269     break;
270    
271 cwang 1.2 #ifdef DYNAMIC_SPACE_OVERFLOW_WARNING_HIT
272 rtoy 1.4 case trap_DynamicSpaceOverflowWarning:
273     interrupt_handle_space_overflow(SymbolFunction
274     (DYNAMIC_SPACE_OVERFLOW_WARNING_HIT),
275     context);
276     break;
277 cwang 1.1 #endif
278 cwang 1.2 #ifdef DYNAMIC_SPACE_OVERFLOW_ERROR_HIT
279 rtoy 1.4 case trap_DynamicSpaceOverflowError:
280     interrupt_handle_space_overflow(SymbolFunction
281     (DYNAMIC_SPACE_OVERFLOW_ERROR_HIT),
282     context);
283     break;
284     #endif
285     default:
286     DPRINTF(0,
287     (stderr, "[C--trap default %d %d %x]\n", signal, code,
288     context));
289     interrupt_handle_now(signal, code, context);
290     break;
291 cwang 1.1 }
292     }
293    
294 rtoy 1.4 void
295 cshapiro 1.7 arch_install_interrupt_handlers(void)
296 cwang 1.1 {
297     interrupt_install_low_level_handler(SIGILL, sigtrap_handler);
298     interrupt_install_low_level_handler(SIGTRAP, sigtrap_handler);
299     }
300    
301    
302 rtoy 1.4 extern lispobj call_into_lisp(lispobj fun, lispobj * args, int nargs);
303 cwang 1.1
304     /* These next four functions are an interface to the
305     * Lisp call-in facility. Since this is C we can know
306     * nothing about the calling environment. The control
307     * stack might be the C stack if called from the monitor
308     * or the Lisp stack if called as a result of an interrupt
309     * or maybe even a separate stack. The args are most likely
310     * on that stack but could be in registers depending on
311     * what the compiler likes. So I try to package up the
312     * args into a portable vector and let the assembly language
313     * call-in function figure it out.
314     */
315    
316 rtoy 1.4 lispobj
317     funcall0(lispobj function)
318 cwang 1.1 {
319     lispobj *args = NULL;
320    
321     return call_into_lisp(function, args, 0);
322     }
323    
324 rtoy 1.4 lispobj
325     funcall1(lispobj function, lispobj arg0)
326 cwang 1.1 {
327     lispobj args[1];
328 rtoy 1.4
329 cwang 1.1 args[0] = arg0;
330     return call_into_lisp(function, args, 1);
331     }
332    
333 rtoy 1.4 lispobj
334     funcall2(lispobj function, lispobj arg0, lispobj arg1)
335 cwang 1.1 {
336     lispobj args[2];
337 rtoy 1.4
338 cwang 1.1 args[0] = arg0;
339     args[1] = arg1;
340     return call_into_lisp(function, args, 2);
341     }
342    
343 rtoy 1.4 lispobj
344     funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
345 cwang 1.1 {
346     lispobj args[3];
347 rtoy 1.4
348 cwang 1.1 args[0] = arg0;
349     args[1] = arg1;
350     args[2] = arg2;
351     return call_into_lisp(function, args, 3);
352     }
353    
354     #ifdef LINKAGE_TABLE
355    
356     #ifndef LinkageEntrySize
357     #define LinkageEntrySize 16
358     #endif
359    
360 rtoy 1.4 void
361     arch_make_linkage_entry(long linkage_entry, void *target_addr, long type)
362 cwang 1.1 {
363 rtoy 1.4 char *reloc_addr = (char *) (FOREIGN_LINKAGE_SPACE_START
364 cwang 1.1
365 rtoy 1.4 + linkage_entry * LinkageEntrySize);
366    
367     if (type == 1) { /* code reference */
368     /* Make JMP to function entry. */
369     long offset = (char *) target_addr;
370 cwang 1.1 int i;
371 rtoy 1.4
372 cwang 1.3 /* %r11 is a temp register */
373 rtoy 1.4 *reloc_addr++ = 0x49; /* opcode for MOV */
374     *reloc_addr++ = 0xbb; /* %r11 */
375 cwang 1.1 for (i = 0; i < 8; i++) {
376     *reloc_addr++ = offset & 0xff;
377     offset >>= 8;
378     }
379 rtoy 1.4 *reloc_addr++ = 0x41; /* jmpq */
380 cwang 1.1 *reloc_addr++ = 0xff;
381 rtoy 1.4 *reloc_addr++ = 0xe3; /* %r11 */
382 cwang 1.1 /* write a nop for good measure. */
383     *reloc_addr = 0x90;
384     } else if (type == 2) {
385 rtoy 1.4 *(unsigned long *) reloc_addr = (unsigned long) target_addr;
386 cwang 1.1 }
387     }
388    
389     /* Make a call to the first function in the linkage table, which is
390     resolve_linkage_tramp. */
391 rtoy 1.4 void
392     arch_make_lazy_linkage(long linkage_entry)
393 cwang 1.1 {
394 rtoy 1.4 char *reloc_addr = (char *) (FOREIGN_LINKAGE_SPACE_START
395    
396     + linkage_entry * LinkageEntrySize);
397     long offset = (char *) (FOREIGN_LINKAGE_SPACE_START) - (reloc_addr + 5);
398 cwang 1.1 int i;
399    
400 rtoy 1.4 *reloc_addr++ = 0xe8; /* opcode for CALL rel32 */
401 cwang 1.1 for (i = 0; i < 4; i++) {
402     *reloc_addr++ = offset & 0xff;
403     offset >>= 8;
404     }
405     /* write a nop for good measure. */
406     *reloc_addr = 0x90;
407     }
408    
409     /* Get linkage entry. The initial instruction in the linkage
410     entry is a CALL; the return address we're passed points to the next
411     instruction. */
412    
413 rtoy 1.4 long
414     arch_linkage_entry(unsigned long retaddr)
415 cwang 1.1 {
416     return ((retaddr - 5) - FOREIGN_LINKAGE_SPACE_START) / LinkageEntrySize;
417     }
418     #endif /* LINKAGE_TABLE */

  ViewVC Help
Powered by ViewVC 1.1.5