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

  ViewVC Help
Powered by ViewVC 1.1.5