X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fmips-arch.c;h=d63a3808f1176bc962ccc59e9b570d7107069d43;hb=b43b6e70ce48d959d77f7f56be9d11aa101fdd7d;hp=64392138571f4e44d2caaa345a7fe14530469ee4;hpb=5c85e3bd30098cd3dbc72264e7f36f022c5ae5e7;p=sbcl.git diff --git a/src/runtime/mips-arch.c b/src/runtime/mips-arch.c index 6439213..d63a380 100644 --- a/src/runtime/mips-arch.c +++ b/src/runtime/mips-arch.c @@ -19,7 +19,6 @@ #include "interrupt.h" #include "interr.h" #include "breakpoint.h" -#include "monitor.h" #include "genesis/constants.h" @@ -244,7 +243,7 @@ next_insn_addr(os_context_t *context, unsigned int inst) void arch_skip_instruction(os_context_t *context) { - /* Skip the offending instruction. Don't use os_context_insn here, + /* Skip the offending instruction. Don't use os_context_insn here, since in case of a branch we want the branch insn, not the delay slot. */ *os_context_pc_addr(context) @@ -274,13 +273,19 @@ arch_set_pseudo_atomic_interrupted(os_context_t *context) *os_context_register_addr(context, reg_NL4) |= -1LL<<31; } -unsigned long +void +arch_clear_pseudo_atomic_interrupted(os_context_t *context) +{ + *os_context_register_addr(context, reg_NL4) &= ~(-1LL<<31); +} + +unsigned int arch_install_breakpoint(void *pc) { unsigned int *ptr = (unsigned int *)pc; unsigned int insn; - /* Don't install over a branch/jump with delay slot. */ + /* Don't install over a branch/jump with delay slot. */ if (arch_insn_with_bdelay_p(*ptr)) ptr++; @@ -288,7 +293,7 @@ arch_install_breakpoint(void *pc) *ptr = (trap_Breakpoint << 6) | 0xd; os_flush_icache((os_vm_address_t)ptr, INSN_LEN); - return (unsigned long)insn; + return insn; } static inline unsigned int @@ -309,7 +314,7 @@ arch_install_after_breakpoint(void *pc) } void -arch_remove_breakpoint(void *pc, unsigned long orig_inst) +arch_remove_breakpoint(void *pc, unsigned int orig_inst) { unsigned int *ptr = (unsigned int *)pc; @@ -317,11 +322,11 @@ arch_remove_breakpoint(void *pc, unsigned long orig_inst) if (arch_insn_with_bdelay_p(*ptr)) ptr++; - *ptr = (unsigned int)orig_inst; + *ptr = orig_inst; os_flush_icache((os_vm_address_t)ptr, INSN_LEN); } -/* Perform the instruction that we overwrote with a breakpoint. As we +/* Perform the instruction that we overwrote with a breakpoint. As we don't have a single-step facility, this means we have to: - put the instruction back - put a second breakpoint at the following instruction, @@ -397,8 +402,7 @@ sigtrap_handler(int signal, siginfo_t *info, void *void_context) break; case 0x10: - /* Clear the pseudo-atomic flag */ - *os_context_register_addr(context, reg_NL4) &= ~(-1LL<<31); + arch_clear_pseudo_atomic_interrupted(context); arch_skip_instruction(context); interrupt_handle_pending(context); return; @@ -522,3 +526,45 @@ funcall3(lispobj function, lispobj arg0, lispobj arg1, lispobj arg2) return call_into_lisp(function, args, 3); } + +#ifdef LISP_FEATURE_LINKAGE_TABLE + +/* Linkage tables for MIPS + + Linkage entry size is 16, because we need 4 instructions to implement + a jump. The entry size constant is defined in parms.lisp. + + Define the register to use in the linkage jump table. For MIPS this + has to be the PIC call register $25 aka t9 aka reg_ALLOC. */ +#define LINKAGE_TEMP_REG reg_ALLOC + +/* Insert the necessary jump instructions at the given address. */ +void +arch_write_linkage_table_jmp(void* reloc_addr, void *target_addr) +{ + /* Make JMP to function entry. The instruction sequence is: + lui $25, 0, %hi(addr) + addiu $25, $25, %lo(addr) + jr $25 + nop */ + unsigned int *insn = (unsigned int *)reloc_addr; + unsigned int addr = (unsigned int)target_addr; + unsigned int hi = ((addr + 0x8000) >> 16) & 0xffff; + unsigned int lo = addr & 0xffff; + + *insn++ = (15 << 26) | (LINKAGE_TEMP_REG << 16) | hi; + *insn++ = ((9 << 26) | (LINKAGE_TEMP_REG << 21) + | (LINKAGE_TEMP_REG << 16) | lo); + *insn++ = (LINKAGE_TEMP_REG << 21) | 8; + *insn = 0; + + os_flush_icache((os_vm_address_t)reloc_addr, LINKAGE_TABLE_ENTRY_SIZE); +} + +void +arch_write_linkage_table_ref(void *reloc_addr, void *target_addr) +{ + *(unsigned int *)reloc_addr = (unsigned int)target_addr; +} + +#endif