/* macros for all used commands (see a MIPS-manual for description) ***********/
+#define M_RESERVED M_RTYPE(0x3b, 0, 0, 0, 0, 0)
+
/* load/store macros use the form OPERATION(source/dest, base, offset) */
#define M_LDA(a,b,disp) \
uint32_t emit_trap(codegendata *cd)
{
- uint32_t mcode;
+ // Get machine code which is patched back in later. The trap is 1
+ // instruction word long.
+ uint32_t mcode = *((uint32_t*) cd->mcodeptr);
- /* Get machine code which is patched back in later. The
- trap is 1 instruction word long. */
-
- mcode = *((uint32_t *) cd->mcodeptr);
-
- M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
+ M_RESERVED;
return mcode;
}
/* fall-through */
- case TRAP_PATCHER:
- if (p == NULL) {
- /* We set the PC again because the cause may have changed
- the XPC. */
+ default:
+ _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
+ _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
+#if defined(__UCLIBC__)
+ _gregs[CTX_EPC] = (uintptr_t) asm_handle_exception;
+#else
+ _mc->pc = (uintptr_t) asm_handle_exception;
+#endif
+ }
+}
+
+
+/**
+ * Signal handler for patcher calls.
+ */
+void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
+{
+ ucontext_t* _uc = (struct ucontext *) _p;
+ mcontext_t* _mc = &_uc->uc_mcontext;
+ greg_t* _gregs;
#if defined(__UCLIBC__)
- _gregs[CTX_EPC] = (uintptr_t) xpc;
+ _gregs = _mc->gpregs;
+#else
+ _gregs = _mc->gregs;
+#endif
+
+ // In glibc's ucontext.h the registers are defined as long long
+ // int, even for MIPS32, so we cast them. This is not the case
+ // for uClibc.
+ void* pv = (void*) (uintptr_t) _gregs[REG_PV];
+ void* sp = (void*) (uintptr_t) _gregs[REG_SP];
+ void* ra = (void*) (uintptr_t) _gregs[REG_RA]; // The RA is correct for leaf methods.
+
+#if defined(__UCLIBC__)
+ void* xpc = (void*) (uintptr_t) _gregs[CTX_EPC];
#else
- _mc->pc = (uintptr_t) xpc;
+ void* xpc = (void*) (uintptr_t) _mc->pc;
#endif
- break;
- }
- /* fall-through */
-
- default:
+ // This signal is always a patcher.
+ int type = TRAP_PATCHER;
+ intptr_t val = 0;
+
+ // Handle the trap.
+ void* p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ // Set registers if we have an exception, continue execution
+ // otherwise.
+ if (p != NULL) {
_gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
_gregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
#if defined(__UCLIBC__)
_gregs[CTX_EPC] = (uintptr_t) asm_handle_exception;
#else
_mc->pc = (uintptr_t) asm_handle_exception;
+#endif
+ }
+ else {
+ // We set the PC again because the cause may have changed the
+ // XPC.
+#if defined(__UCLIBC__)
+ _gregs[CTX_EPC] = (uintptr_t) xpc;
+#else
+ _mc->pc = (uintptr_t) xpc;
#endif
}
}
void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p);
#endif
-#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
/* XXX use better defines for that (in arch.h) */
void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p);
#endif