- int badinst;
- u32 code;
- sigset_t *mask;
- mask=(os_context_sigmask_addr(context));
- sigsetmask(mask);
- code=*((u32 *)(*os_context_pc_addr(context)));
- if (code == ((3 << 26) | (16 << 21) | (reg_ALLOC << 16))) {
- /* twlti reg_ALLOC,0 - check for deferred interrupt */
- *os_context_register_addr(context,reg_ALLOC)
- -= PSEUDO_ATOMIC_INTERRUPTED_BIAS;
- arch_skip_instruction(context);
- /* interrupt or GC was requested in PA; now we're done with the
- PA section we may as well get around to it */
- interrupt_handle_pending(context);
- return;
-
- }
- if ((code >> 16) == ((3 << 10) | (6 << 5))) {
- /* twllei reg_ZERO,N will always trap if reg_ZERO = 0 */
- int trap = code & 0x1f, extra = (code >> 5) & 0x1f;
-
- switch (trap) {
- case trap_Halt:
- fake_foreign_function_call(context);
- lose("%%primitive halt called; the party is over.\n");
-
- case trap_Error:
- case trap_Cerror:
- interrupt_internal_error(signal, code, context, trap == trap_Cerror);
- break;
-
- case trap_PendingInterrupt:
- /* when do we run this branch instead of the twlti code above? */
- arch_skip_instruction(context);
- interrupt_handle_pending(context);
- break;
-
- case trap_Breakpoint:
- handle_breakpoint(signal, code, context);
- break;
-
- case trap_FunEndBreakpoint:
- *os_context_pc_addr(context)
- =(int)handle_fun_end_breakpoint(signal, code, context);
- break;
-
- case trap_AfterBreakpoint:
- *skipped_break_addr = trap_Breakpoint;
- skipped_break_addr = NULL;
- *(unsigned long *)*os_context_pc_addr(context)
- = displaced_after_inst;
- *os_context_sigmask_addr(context)= orig_sigmask;
-
- os_flush_icache((os_vm_address_t) *os_context_pc_addr(context),
- sizeof(unsigned long));
- break;
-
- default:
- interrupt_handle_now(signal, code, context);
- break;
- }
- }
- if (((code >> 26) == 3) && (((code >> 21) & 31) == 24)) {
- interrupt_internal_error(signal, code, context, 0);
+ int result;
+ unsigned int *pc;
+ unsigned inst;
+ unsigned opcode;
+ unsigned src;
+ unsigned dst;
+
+ result = 0;
+
+ /*
+ * First, the instruction has to be a TWLGE temp, NL3, which has the
+ * format.
+ * | 6| 5| 5 | 5 | 10|1| width
+ * |31|5 |dst|src| 4|0| field
+ */
+ pc = (unsigned int *) (*os_context_pc_addr(context));
+ inst = *pc;
+
+#if 0
+ fprintf(stderr, "allocation_trap_p at %p: inst = 0x%08x\n", pc, inst);
+#endif
+
+ opcode = inst >> 26;
+ src = (inst >> 11) & 0x1f;
+ dst = (inst >> 16) & 0x1f;
+ if ((opcode == 31) && (src == reg_NL3) && (5 == ((inst >> 21) & 0x1f))
+ && (4 == ((inst >> 1) & 0x3ff))) {
+ /*
+ * We got the instruction. Now, look back to make sure it was
+ * proceeded by what we expected. 2 instructions back should be
+ * an ADD or ADDI instruction.
+ */
+ unsigned int add_inst;
+
+ add_inst = pc[-3];
+#if 0
+ fprintf(stderr, " add inst at %p: inst = 0x%08x\n",
+ pc - 3, add_inst);
+#endif
+ opcode = add_inst >> 26;
+ if ((opcode == 31) && (266 == ((add_inst >> 1) & 0x1ff))) {
+ return 1;
+ } else if ((opcode == 14)) {
+ return 1;
+ } else {
+ fprintf(stderr,
+ "Whoa! Got allocation trap but could not find ADD or ADDI instruction: 0x%08x in the proper place\n",
+ add_inst);
+ }