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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.11 - (show annotations)
Wed Mar 19 09:17:10 2008 UTC (6 years ago) by cshapiro
Branch: MAIN
CVS Tags: sparc-tramp-assem-base, post-merge-intl-branch, merged-unicode-utf16-extfmt-2009-06-11, unicode-utf16-extfmt-2009-03-27, snapshot-2008-08, snapshot-2008-09, sse2-packed-2008-11-12, snapshot-2008-05, snapshot-2008-06, snapshot-2008-07, intl-branch-working-2010-02-19-1000, unicode-string-buffer-impl-base, sse2-base, release-20b-pre1, release-20b-pre2, unicode-string-buffer-base, sse2-packed-base, sparc-tramp-assem-2010-07-19, amd64-dd-start, release-19f-pre1, snapshot-2008-12, snapshot-2008-11, intl-2-branch-base, GIT-CONVERSION, unicode-utf16-sync-2008-12, cross-sol-x86-merged, label-2009-03-16, release-19f-base, merge-sse2-packed, merge-with-19f, intl-branch-working-2010-02-11-1000, unicode-snapshot-2009-05, unicode-snapshot-2009-06, unicode-utf16-sync-2008-07, unicode-utf16-sync-2008-09, unicode-utf16-extfmts-sync-2008-12, RELEASE_20b, snapshot-2008-04, unicode-utf16-sync-label-2009-03-16, RELEASE_19f, release-20a-base, cross-sol-x86-base, unicode-utf16-char-support-2009-03-26, unicode-utf16-char-support-2009-03-25, unicode-utf16-extfmts-pre-sync-2008-11, snapshot-2008-10, snapshot-2010-12, snapshot-2010-11, unicode-utf16-sync-2008-11, snapshot-2011-09, snapshot-2011-06, snapshot-2011-07, snapshot-2011-04, snapshot-2011-02, snapshot-2011-03, snapshot-2011-01, pre-merge-intl-branch, snapshot-2010-05, snapshot-2010-04, snapshot-2010-07, snapshot-2010-06, snapshot-2010-01, snapshot-2010-03, snapshot-2010-02, snapshot-2010-08, label-2009-03-25, cross-sol-x86-2010-12-20, sse2-checkpoint-2008-10-01, intl-branch-2010-03-18-1300, sse2-merge-with-2008-11, sse2-merge-with-2008-10, RELEASE_20a, release-20a-pre1, snapshot-2009-11, snapshot-2009-12, unicode-utf16-extfmt-2009-06-11, portable-clx-import-2009-06-16, unicode-utf16-string-support, cross-sparc-branch-base, intl-branch-base, unicode-utf16-base, portable-clx-base, snapshot-2009-08, snapshot-2009-02, snapshot-2009-01, snapshot-2009-07, snapshot-2009-05, snapshot-2009-04, HEAD
Branch point for: RELEASE-19F-BRANCH, portable-clx-branch, cross-sparc-branch, RELEASE-20B-BRANCH, unicode-string-buffer-branch, sparc-tramp-assem-branch, sse2-packed-branch, RELEASE-20A-BRANCH, amd64-dd-branch, unicode-string-buffer-impl-branch, intl-branch, unicode-utf16-branch, cross-sol-x86-branch, sse2-branch, intl-2-branch, unicode-utf16-extfmt-branch
Changes since 1.10: +2 -2 lines
File MIME type: text/plain
Always use prototype style function definitions.  Consistently use the
void keyword to specify empty parameter lists.
1 /*
2
3 $Header: /tiger/var/lib/cvsroots/cmucl/src/lisp/alpha-arch.c,v 1.11 2008/03/19 09:17:10 cshapiro Rel $
4
5 This code was written as part of the CMU Common Lisp project at
6 Carnegie Mellon University, and has been placed in the public domain.
7
8 */
9
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "lisp.h"
14 #include "globals.h"
15 #include "validate.h"
16 #include "os.h"
17 #include "internals.h"
18 #include "arch.h"
19 #include "lispregs.h"
20 #include "signal.h"
21 #include "alloc.h"
22 #include "interrupt.h"
23 #include "interr.h"
24 #include "breakpoint.h"
25
26 extern char call_into_lisp_LRA[], call_into_lisp_end[];
27
28 #define BREAKPOINT_INST 0
29
30 char *
31 arch_init(void)
32 {
33 if (mmap((os_vm_address_t) call_into_lisp_LRA_page, OS_VM_DEFAULT_PAGESIZE,
34 OS_VM_PROT_ALL, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0)
35 == (os_vm_address_t) - 1)
36 perror("mmap");
37 memcpy(call_into_lisp_LRA_page, call_into_lisp_LRA, OS_VM_DEFAULT_PAGESIZE);
38 os_flush_icache((os_vm_address_t) call_into_lisp_LRA_page,
39 OS_VM_DEFAULT_PAGESIZE);
40 return NULL;
41 }
42
43 os_vm_address_t
44 arch_get_bad_addr(int sig, int code, struct sigcontext * scp)
45 {
46 unsigned int badinst;
47
48 if ((scp->sc_pc & 3) != 0)
49 return NULL;
50
51 if ((scp->sc_pc < READ_ONLY_SPACE_START ||
52 scp->sc_pc >= READ_ONLY_SPACE_START + READ_ONLY_SPACE_SIZE) &&
53 ((lispobj *) scp->sc_pc < current_dynamic_space ||
54 (lispobj *) scp->sc_pc >= current_dynamic_space + dynamic_space_size))
55 return NULL;
56
57 badinst = *(unsigned int *) scp->sc_pc;
58
59 if (((badinst >> 27) != 0x16) /* STL or STQ */
60 &&((badinst >> 27) != 0x13)) /* STS or STT */
61 return NULL; /* Otherwise forget about address */
62
63 return (os_vm_address_t) (scp->sc_regs[(badinst >> 16) & 0x1f] +
64 (badinst & 0xffff));
65 }
66
67 void
68 arch_skip_instruction(scp)
69 struct sigcontext *scp;
70 {
71 scp->sc_pc = +4;
72 }
73
74 unsigned char *
75 arch_internal_error_arguments(struct sigcontext *scp)
76 {
77 return (unsigned char *) (scp->sc_pc + 4);
78 }
79
80 boolean
81 arch_pseudo_atomic_atomic(struct sigcontext *scp)
82 {
83 return (scp->sc_regs[reg_ALLOC] & 1);
84 }
85
86 void
87 arch_set_pseudo_atomic_interrupted(struct sigcontext *scp)
88 {
89 #ifdef __linux__
90 scp->sc_regs[reg_ALLOC] |= (1 << 63);
91 #else
92 scp->sc_regs[reg_ALLOC] |= 2;
93 #endif
94 }
95
96 unsigned long
97 arch_install_breakpoint(void *pc)
98 {
99 unsigned int *ptr = (unsigned int *) pc;
100 unsigned long result = (unsigned long) *ptr;
101
102 *ptr = BREAKPOINT_INST;
103
104 os_flush_icache((os_vm_address_t) ptr, sizeof(unsigned long));
105
106 return result;
107 }
108
109 void
110 arch_remove_breakpoint(void *pc, unsigned long orig_inst)
111 {
112 unsigned int *ptr = (unsigned int) pc;
113
114 *ptr = orig_inst;
115 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
116 }
117
118 static unsigned int *skipped_break_addr, displaced_after_inst, after_breakpoint;
119
120 static sigset_t orig_sigmask;
121
122 unsigned int
123 emulate_branch(struct sigcontext *scp, unsigned long orig_inst)
124 {
125 int op = orig_inst >> 26;
126 int reg_a = (orig_inst >> 21) & 0x1f;
127 int reg_b = (orig_inst >> 16) & 0x1f;
128 int fn = orig_inst & 0xffff;
129 int disp =
130
131 (orig_inst & (1 << 20)) ? orig_inst | (-1 << 21) : orig_inst & 0x1fffff;
132 int next_pc = scp->sc_pc;
133 int branch = NULL;
134
135 switch (op) {
136 case 0x1a: /* jmp, jsr, jsr_coroutine, ret */
137 scp->sc_regs[reg_a] = scp->sc_pc;
138 scp->sc_pc = scp->sc_regs[reg_b] & ~3;
139 break;
140 case 0x30: /* br */
141 scp->sc_regs[reg_a] = scp->sc_pc;
142 branch = 1;
143 break;
144 case 0x31: /* fbeq */
145 if (scp->sc_fpregs[reg_a] == 0)
146 branch = 1;
147 break;
148 case 0x32: /* fblt */
149 if (scp->sc_fpregs[reg_a] < 0)
150 branch = 1;
151 break;
152 case 0x33: /* fble */
153 if (scp->sc_fpregs[reg_a] <= 0)
154 branch = 1;
155 break;
156 case 0x34: /* bsr */
157 scp->sc_regs[reg_a] = scp->sc_pc;
158 branch = 1;
159 break;
160 case 0x35: /* fbne */
161 if (scp->sc_regs[reg_a] != 0)
162 branch = 1;
163 break;
164 case 0x36: /* fbge */
165 if (scp->sc_fpregs[reg_a] >= 0)
166 branch = 1;
167 break;
168 case 0x37: /* fbgt */
169 if (scp->sc_fpregs[reg_a] > 0)
170 branch = 1;
171 break;
172 case 0x38: /* blbc */
173 if ((scp->sc_regs[reg_a] & 1) == 0)
174 branch = 1;
175 break;
176 case 0x39: /* beq */
177 if (scp->sc_regs[reg_a] == 0)
178 branch = 1;
179 break;
180 case 0x3a: /* blt */
181 if (scp->sc_regs[reg_a] < 0)
182 branch = 1;
183 break;
184 case 0x3b: /* ble */
185 if (scp->sc_regs[reg_a] <= 0)
186 branch = 1;
187 break;
188 case 0x3c: /* blbs */
189 if ((scp->sc_regs[reg_a] & 1) != 0)
190 branch = 1;
191 break;
192 case 0x3d: /* bne */
193 if (scp->sc_regs[reg_a] != 0)
194 branch = 1;
195 break;
196 case 0x3e: /* bge */
197 if (scp->sc_regs[reg_a] >= 0)
198 branch = 1;
199 break;
200 case 0x3f: /* bgt */
201 if (scp->sc_regs[reg_a] > 0)
202 branch = 1;
203 break;
204 }
205 if (branch)
206 next_pc += disp * 4;
207 return next_pc;
208 }
209
210 void
211 arch_do_displaced_inst(struct sigcontext *scp, unsigned long orig_inst)
212 {
213 unsigned int *pc = scp->sc_pc;
214 unsigned int *next_pc;
215 unsigned int next_inst;
216 int op = orig_inst >> 26;;
217
218 #if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
219 orig_sigmask = context->uc_sigmask;
220 FILLBLOCKSET(&context->uc_sigmask);
221 #else
222 {
223 sigset_t temp;
224
225 sigemptyset(&temp);
226 orig_sigmask.__val[0] = scp->uc_sigmask;
227 temp.__val[0] = scp->uc_sigmask;
228 FILLBLOCKSET(&temp);
229
230 scp->uc_sigmask = temp.__val[0];
231 }
232 #endif
233
234 /* Figure out where the displaced inst is going */
235 if (op == 0x1a || op & 0xf == 0x30) /* branch...ugh */
236 next_pc = (unsigned int *) emulate_branch(scp, orig_inst);
237 else
238 next_pc = pc + 1;
239
240 /* Put the original instruction back. */
241 *pc = orig_inst;
242 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
243
244 skipped_break_addr = pc;
245
246 /* set the after breakpoint */
247 displaced_after_inst = *next_pc;
248 *next_pc = BREAKPOINT_INST;
249 after_breakpoint = 1;
250 os_flush_icache((os_vm_address_t) next_pc, sizeof(unsigned long));
251
252 sigreturn(scp);
253 }
254
255 #define AfterBreakpoint 100
256
257 static void
258 sigtrap_handler(int signal, int code, struct sigcontext *scp)
259 {
260 /* Don't disallow recursive breakpoint traps. Otherwise, we can't */
261 /* use debugger breakpoints anywhere in here. */
262 sigsetmask(scp->sc_mask);
263
264 if (*(unsigned int *) (scp->sc_pc - 4) == BREAKPOINT_INST) {
265 if (after_breakpoint)
266 code = AfterBreakpoint;
267 else
268 code = trap_Breakpoint;
269 } else
270 code = *(u32 *) scp->sc_pc;
271
272 switch (code) {
273 case trap_PendingInterrupt:
274 arch_skip_instruction(scp);
275 interrupt_handle_pending(scp);
276 break;
277
278 case trap_Halt:
279 fake_foreign_function_call(scp);
280 lose("%%primitive halt called; the party is over.\n");
281
282 case trap_Error:
283 case trap_Cerror:
284 interrupt_internal_error(signal, code, scp, code == trap_Cerror);
285 break;
286
287 case trap_Breakpoint:
288 scp->sc_pc -= 4;
289 handle_breakpoint(signal, code, scp);
290 break;
291
292 case trap_FunctionEndBreakpoint:
293 scp->sc_pc -= 4;
294 scp->sc_pc = (int) handle_function_end_breakpoint(signal, code, scp);
295 break;
296
297 case AfterBreakpoint:
298 scp->sc_pc -= 4;
299 *skipped_break_addr = BREAKPOINT_INST;
300 os_flush_icache((os_vm_address_t) skipped_break_addr,
301
302 sizeof(unsigned long));
303 skipped_break_addr = NULL;
304 *(unsigned int *) scp->sc_pc = displaced_after_inst;
305 os_flush_icache((os_vm_address_t) scp->sc_pc, sizeof(unsigned long));
306
307 #if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
308 scp->sc_mask = orig_sigmask;
309 #else
310 scp->sc_mask = orig_sigmask.__val[0];
311 #endif
312 after_breakpoint = NULL;
313 break;
314
315 default:
316 interrupt_handle_now(signal, code, scp);
317 break;
318 }
319 }
320
321 static void
322 sigfpe_handler(int signal, int code, struct sigcontext *scp)
323 {
324 }
325
326 void
327 arch_install_interrupt_handlers(void)
328 {
329 interrupt_install_low_level_handler(SIGILL, sigtrap_handler);
330 interrupt_install_low_level_handler(SIGTRAP, sigtrap_handler);
331 interrupt_install_low_level_handler(SIGFPE, sigfpe_handler);
332 }
333
334 extern lispobj call_into_lisp(lispobj fun, lispobj * args, int nargs);
335
336 lispobj
337 funcall0(lispobj function)
338 {
339 lispobj *args = current_control_stack_pointer;
340
341 return call_into_lisp(function, args, 0);
342 }
343
344 lispobj
345 funcall1(lispobj function, lispobj arg0)
346 {
347 lispobj *args = current_control_stack_pointer;
348
349 current_control_stack_pointer += 1;
350 args[0] = arg0;
351
352 return call_into_lisp(function, args, 1);
353 }
354
355 lispobj
356 funcall2(lispobj function, lispobj arg0, lispobj arg1)
357 {
358 lispobj *args = current_control_stack_pointer;
359
360 current_control_stack_pointer += 2;
361 args[0] = arg0;
362 args[1] = arg1;
363
364 return call_into_lisp(function, args, 2);
365 }
366
367 lispobj
368 funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
369 {
370 lispobj *args = current_control_stack_pointer;
371
372 current_control_stack_pointer += 3;
373 args[0] = arg0;
374 args[1] = arg1;
375 args[2] = arg2;
376
377 return call_into_lisp(function, args, 3);
378 }
379
380
381 /* This is apparently called by emulate_branch, but isn't defined. So */
382 /* just do nothing and hope it works... */
383
384 void
385 cacheflush(void)
386 {
387 }

  ViewVC Help
Powered by ViewVC 1.1.5