/[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 - (show 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 /* x86-arch.c -*- Mode: C; comment-column: 40 -*-
2 *
3 * $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 *
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 #define __USE_GNU
16 #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 unsigned long fast_random_state = 1;
26
27 char *
28 arch_init(fpu_mode_t mode)
29 {
30 return "lisp.core";
31 }
32
33
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 void
43 arch_skip_instruction(os_context_t *context)
44 {
45 int vlen, code;
46
47 DPRINTF(0, (stderr, "[arch_skip_inst at %x>]\n", SC_PC(context)));
48
49 /* Get and skip the lisp error code. */
50 code = *(char *) SC_PC(context)++;
51 switch (code) {
52 case trap_Error:
53 case trap_Cerror:
54 /* Lisp error arg vector length */
55 vlen = *(char *) SC_PC(context)++;
56 /* Skip lisp error arg data bytes */
57 while (vlen-- > 0)
58 SC_PC(context)++;
59 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 }
74
75 DPRINTF(0, (stderr, "[arch_skip_inst resuming at %x>]\n", SC_PC(context)));
76 }
77
78 unsigned char *
79 arch_internal_error_arguments(os_context_t *context)
80 {
81 return (unsigned char *) (SC_PC(context) + 1);
82 }
83
84 boolean
85 arch_pseudo_atomic_atomic(os_context_t *context)
86 {
87 return SymbolValue(PSEUDO_ATOMIC_ATOMIC);
88 }
89
90 void
91 arch_set_pseudo_atomic_interrupted(os_context_t *context)
92 {
93 SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, make_fixnum(1));
94 }
95
96
97
98 unsigned long
99 arch_install_breakpoint(void *pc)
100 {
101 unsigned long result = *(unsigned long *) pc;
102
103 *(char *) pc = BREAKPOINT_INST; /* x86 INT3 */
104 *((char *) pc + 1) = trap_Breakpoint; /* Lisp trap code */
105
106 return result;
107 }
108
109 void
110 arch_remove_breakpoint(void *pc, unsigned long orig_inst)
111 {
112 *((char *) pc) = orig_inst & 0xff;
113 *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;
114 }
115
116
117
118 /*
119 * When single stepping single_stepping holds the original instruction
120 * pc location.
121 */
122
123 unsigned int *single_stepping = NULL;
124
125 #ifndef __linux__
126 unsigned int single_step_save1;
127 unsigned int single_step_save2;
128 unsigned int single_step_save3;
129 #endif
130
131 void
132 arch_do_displaced_inst(os_context_t *context, unsigned long orig_inst)
133 {
134 unsigned int *pc = (unsigned int *) SC_PC(context);
135
136 /*
137 * Put the original instruction back.
138 */
139
140 *((char *) pc) = orig_inst & 0xff;
141 *((char *) pc + 1) = (orig_inst & 0xff00) >> 8;
142
143 #ifdef SC_EFLAGS
144 SC_EFLAGS(context) |= 0x100;
145 #else
146
147 /*
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 #endif
159
160 single_stepping = (unsigned int *) pc;
161
162 #ifndef __linux__
163 (unsigned int *) SC_PC(context) = (char *) pc - 9;
164 #endif
165 }
166
167
168 void
169 sigtrap_handler(HANDLER_ARGS)
170 {
171 unsigned int trap;
172
173 #if 0
174 fprintf(stderr, "x86sigtrap: %8x %x\n",
175 SC_PC(context), *(unsigned char *) (SC_PC(context) - 1));
176 fprintf(stderr, "sigtrap(%d %d %x)\n", signal, code, context);
177 #endif
178
179 if (single_stepping && (signal == SIGTRAP)) {
180 #if 0
181 fprintf(stderr, "* Single step trap %x\n", single_stepping);
182 #endif
183
184 #ifdef SC_EFLAGS
185 /* Disable single-stepping */
186 SC_EFLAGS(context) ^= 0x100;
187 #else
188 /* 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 if ((int) SC_PC(context) == (int) single_stepping + 1)
199 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 }
206
207 single_stepping = NULL;
208 return;
209 }
210
211 /* This is just for info in case monitor wants to print an approx */
212 current_control_stack_pointer = (unsigned long *) SC_SP(context);
213
214 RESTORE_FPU(context);
215 /*
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 trap = *(unsigned char *) (SC_PC(context));
223
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 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
234 int fpu_state[27];
235
236 fpu_save(fpu_state);
237 #endif
238 fake_foreign_function_call(context);
239 lose("%%primitive halt called; the party is over.\n");
240 undo_fake_foreign_function_call(context);
241 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
242 fpu_restore(fpu_state);
243 #endif
244 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 interrupt_internal_error(signal, code, context, CODE(code) == trap_Cerror);
252 break;
253
254 case trap_Breakpoint:
255 #if 0
256 fprintf(stderr, "*C break\n");
257 #endif
258 SC_PC(context) -= 1;
259 handle_breakpoint(signal, CODE(code), context);
260 #if 0
261 fprintf(stderr, "*C break return\n");
262 #endif
263 break;
264
265 case trap_FunctionEndBreakpoint:
266 SC_PC(context) -= 1;
267 SC_PC(context) =
268 (int) handle_function_end_breakpoint(signal, code, context);
269 break;
270
271 #ifdef DYNAMIC_SPACE_OVERFLOW_WARNING_HIT
272 case trap_DynamicSpaceOverflowWarning:
273 interrupt_handle_space_overflow(SymbolFunction
274 (DYNAMIC_SPACE_OVERFLOW_WARNING_HIT),
275 context);
276 break;
277 #endif
278 #ifdef DYNAMIC_SPACE_OVERFLOW_ERROR_HIT
279 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 }
292 }
293
294 void
295 arch_install_interrupt_handlers(void)
296 {
297 interrupt_install_low_level_handler(SIGILL, sigtrap_handler);
298 interrupt_install_low_level_handler(SIGTRAP, sigtrap_handler);
299 }
300
301
302 extern lispobj call_into_lisp(lispobj fun, lispobj * args, int nargs);
303
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 lispobj
317 funcall0(lispobj function)
318 {
319 lispobj *args = NULL;
320
321 return call_into_lisp(function, args, 0);
322 }
323
324 lispobj
325 funcall1(lispobj function, lispobj arg0)
326 {
327 lispobj args[1];
328
329 args[0] = arg0;
330 return call_into_lisp(function, args, 1);
331 }
332
333 lispobj
334 funcall2(lispobj function, lispobj arg0, lispobj arg1)
335 {
336 lispobj args[2];
337
338 args[0] = arg0;
339 args[1] = arg1;
340 return call_into_lisp(function, args, 2);
341 }
342
343 lispobj
344 funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
345 {
346 lispobj args[3];
347
348 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 void
361 arch_make_linkage_entry(long linkage_entry, void *target_addr, long type)
362 {
363 char *reloc_addr = (char *) (FOREIGN_LINKAGE_SPACE_START
364
365 + linkage_entry * LinkageEntrySize);
366
367 if (type == 1) { /* code reference */
368 /* Make JMP to function entry. */
369 long offset = (char *) target_addr;
370 int i;
371
372 /* %r11 is a temp register */
373 *reloc_addr++ = 0x49; /* opcode for MOV */
374 *reloc_addr++ = 0xbb; /* %r11 */
375 for (i = 0; i < 8; i++) {
376 *reloc_addr++ = offset & 0xff;
377 offset >>= 8;
378 }
379 *reloc_addr++ = 0x41; /* jmpq */
380 *reloc_addr++ = 0xff;
381 *reloc_addr++ = 0xe3; /* %r11 */
382 /* write a nop for good measure. */
383 *reloc_addr = 0x90;
384 } else if (type == 2) {
385 *(unsigned long *) reloc_addr = (unsigned long) target_addr;
386 }
387 }
388
389 /* Make a call to the first function in the linkage table, which is
390 resolve_linkage_tramp. */
391 void
392 arch_make_lazy_linkage(long linkage_entry)
393 {
394 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 int i;
399
400 *reloc_addr++ = 0xe8; /* opcode for CALL rel32 */
401 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 long
414 arch_linkage_entry(unsigned long retaddr)
415 {
416 return ((retaddr - 5) - FOREIGN_LINKAGE_SPACE_START) / LinkageEntrySize;
417 }
418 #endif /* LINKAGE_TABLE */

  ViewVC Help
Powered by ViewVC 1.1.5