3 $Header: /Volumes/share2/src/cmucl/cvs2git/cvsroot/src/lisp/alpha-arch.c,v 1.11 2008/03/19 09:17:10 cshapiro Rel $
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.
17 #include "internals.h"
22 #include "interrupt.h"
24 #include "breakpoint.h"
26 extern char call_into_lisp_LRA[], call_into_lisp_end[];
28 #define BREAKPOINT_INST 0
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)
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);
44 arch_get_bad_addr(int sig, int code, struct sigcontext * scp)
48 if ((scp->sc_pc & 3) != 0)
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))
57 badinst = *(unsigned int *) scp->sc_pc;
59 if (((badinst >> 27) != 0x16) /* STL or STQ */
60 &&((badinst >> 27) != 0x13)) /* STS or STT */
61 return NULL; /* Otherwise forget about address */
63 return (os_vm_address_t) (scp->sc_regs[(badinst >> 16) & 0x1f] +
68 arch_skip_instruction(scp)
69 struct sigcontext *scp;
75 arch_internal_error_arguments(struct sigcontext *scp)
77 return (unsigned char *) (scp->sc_pc + 4);
81 arch_pseudo_atomic_atomic(struct sigcontext *scp)
83 return (scp->sc_regs[reg_ALLOC] & 1);
87 arch_set_pseudo_atomic_interrupted(struct sigcontext *scp)
90 scp->sc_regs[reg_ALLOC] |= (1 << 63);
92 scp->sc_regs[reg_ALLOC] |= 2;
97 arch_install_breakpoint(void *pc)
99 unsigned int *ptr = (unsigned int *) pc;
100 unsigned long result = (unsigned long) *ptr;
102 *ptr = BREAKPOINT_INST;
104 os_flush_icache((os_vm_address_t) ptr, sizeof(unsigned long));
110 arch_remove_breakpoint(void *pc, unsigned long orig_inst)
112 unsigned int *ptr = (unsigned int) pc;
115 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
118 static unsigned int *skipped_break_addr, displaced_after_inst, after_breakpoint;
120 static sigset_t orig_sigmask;
123 emulate_branch(struct sigcontext *scp, unsigned long orig_inst)
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;
131 (orig_inst & (1 << 20)) ? orig_inst | (-1 << 21) : orig_inst & 0x1fffff;
132 int next_pc = scp->sc_pc;
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;
141 scp->sc_regs[reg_a] = scp->sc_pc;
144 case 0x31: /* fbeq */
145 if (scp->sc_fpregs[reg_a] == 0)
148 case 0x32: /* fblt */
149 if (scp->sc_fpregs[reg_a] < 0)
152 case 0x33: /* fble */
153 if (scp->sc_fpregs[reg_a] <= 0)
157 scp->sc_regs[reg_a] = scp->sc_pc;
160 case 0x35: /* fbne */
161 if (scp->sc_regs[reg_a] != 0)
164 case 0x36: /* fbge */
165 if (scp->sc_fpregs[reg_a] >= 0)
168 case 0x37: /* fbgt */
169 if (scp->sc_fpregs[reg_a] > 0)
172 case 0x38: /* blbc */
173 if ((scp->sc_regs[reg_a] & 1) == 0)
177 if (scp->sc_regs[reg_a] == 0)
181 if (scp->sc_regs[reg_a] < 0)
185 if (scp->sc_regs[reg_a] <= 0)
188 case 0x3c: /* blbs */
189 if ((scp->sc_regs[reg_a] & 1) != 0)
193 if (scp->sc_regs[reg_a] != 0)
197 if (scp->sc_regs[reg_a] >= 0)
201 if (scp->sc_regs[reg_a] > 0)
211 arch_do_displaced_inst(struct sigcontext *scp, unsigned long orig_inst)
213 unsigned int *pc = scp->sc_pc;
214 unsigned int *next_pc;
215 unsigned int next_inst;
216 int op = orig_inst >> 26;;
218 #if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
219 orig_sigmask = context->uc_sigmask;
220 FILLBLOCKSET(&context->uc_sigmask);
226 orig_sigmask.__val[0] = scp->uc_sigmask;
227 temp.__val[0] = scp->uc_sigmask;
230 scp->uc_sigmask = temp.__val[0];
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);
240 /* Put the original instruction back. */
242 os_flush_icache((os_vm_address_t) pc, sizeof(unsigned long));
244 skipped_break_addr = pc;
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));
255 #define AfterBreakpoint 100
258 sigtrap_handler(int signal, int code, struct sigcontext *scp)
260 /* Don't disallow recursive breakpoint traps. Otherwise, we can't */
261 /* use debugger breakpoints anywhere in here. */
262 sigsetmask(scp->sc_mask);
264 if (*(unsigned int *) (scp->sc_pc - 4) == BREAKPOINT_INST) {
265 if (after_breakpoint)
266 code = AfterBreakpoint;
268 code = trap_Breakpoint;
270 code = *(u32 *) scp->sc_pc;
273 case trap_PendingInterrupt:
274 arch_skip_instruction(scp);
275 interrupt_handle_pending(scp);
279 fake_foreign_function_call(scp);
280 lose("%%primitive halt called; the party is over.\n");
284 interrupt_internal_error(signal, code, scp, code == trap_Cerror);
287 case trap_Breakpoint:
289 handle_breakpoint(signal, code, scp);
292 case trap_FunctionEndBreakpoint:
294 scp->sc_pc = (int) handle_function_end_breakpoint(signal, code, scp);
297 case AfterBreakpoint:
299 *skipped_break_addr = BREAKPOINT_INST;
300 os_flush_icache((os_vm_address_t) skipped_break_addr,
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));
307 #if !defined(__linux__) || (defined(__linux__) && (__GNU_LIBRARY__ < 6))
308 scp->sc_mask = orig_sigmask;
310 scp->sc_mask = orig_sigmask.__val[0];
312 after_breakpoint = NULL;
316 interrupt_handle_now(signal, code, scp);
322 sigfpe_handler(int signal, int code, struct sigcontext *scp)
327 arch_install_interrupt_handlers(void)
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);
334 extern lispobj call_into_lisp(lispobj fun, lispobj * args, int nargs);
337 funcall0(lispobj function)
339 lispobj *args = current_control_stack_pointer;
341 return call_into_lisp(function, args, 0);
345 funcall1(lispobj function, lispobj arg0)
347 lispobj *args = current_control_stack_pointer;
349 current_control_stack_pointer += 1;
352 return call_into_lisp(function, args, 1);
356 funcall2(lispobj function, lispobj arg0, lispobj arg1)
358 lispobj *args = current_control_stack_pointer;
360 current_control_stack_pointer += 2;
364 return call_into_lisp(function, args, 2);
368 funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2)
370 lispobj *args = current_control_stack_pointer;
372 current_control_stack_pointer += 3;
377 return call_into_lisp(function, args, 3);
381 /* This is apparently called by emulate_branch, but isn't defined. So */
382 /* just do nothing and hope it works... */