diff --git a/ldb/breakpoint.c b/ldb/breakpoint.c new file mode 100644 index 0000000000000000000000000000000000000000..8d7d5e63a3e383c469ee768219e6d50f987ef3de --- /dev/null +++ b/ldb/breakpoint.c @@ -0,0 +1,104 @@ +#include <stdio.h> +#include <signal.h> + +#include "lisp.h" +#include "os.h" +#include "lispregs.h" +#include "globals.h" + +#ifdef ibmrt +typedef unsigned short inst; +#else +typedef unsigned long inst; +#endif + + +static inst swap_insts(code_obj, pc_offset, new_inst) + lispobj code_obj; + int pc_offset; + inst new_inst; +{ + struct code *code; + inst *addr, old_inst; + + code = (struct code *)PTR(code_obj); + addr = (inst *)((char *)code + HeaderValue(code->header)*sizeof(lispobj) + + pc_offset); + old_inst = *addr; + *addr = new_inst; + os_flush_icache((os_vm_address_t)addr, sizeof(inst)); + return old_inst; +} + +inst breakpoint_install(code_obj, pc_offset) + lispobj code_obj; + int pc_offset; +{ + return swap_insts(code_obj, pc_offset, (trap_Breakpoint << 16) | 0xd); +} + +void breakpoint_remove(code_obj, pc_offset, orig_inst) + lispobj code_obj; + int pc_offset; + inst orig_inst; +{ + swap_insts(code_obj, pc_offset, orig_inst); +} + +static int calc_offset(code, pc) + struct code *code; + unsigned long pc; +{ + unsigned long code_start; + int offset; + + code_start = (unsigned long)code + + HeaderValue(code->header)*sizeof(lispobj); + if (pc < code_start) + return 0; + offset = pc - code_start; + if (offset >= code->code_size) + return 0; + return offset; +} + +int breakpoint_after_offset(scp) + struct sigcontext *scp; +{ + struct code *code = (struct code *)PTR(scp->sc_regs[CODE]); + +#ifdef sparc + return calc_offset(code, scp->sc_npc); +#endif + +#ifdef mips + inst cur_inst = *(inst *)scp->sc_pc; + int opcode = cur_inst >> 26; + struct sigcontext tmp; + + if (opcode == 1 || ((opcode & 0x3c) == 0x4) || ((cur_inst & 0xf00e0000) == 0x80000000)) { + tmp = *scp; + emulate_branch(&tmp, cur_inst); + return calc_offset(code, tmp.sc_pc); + } + else + return calc_offset(code, scp->sc_pc + 4); +#endif +} + + +handle_breakpoint(signal, code, scp) + struct sigcontext *scp; +{ + struct code *code = (struct code *)PTR(scp->sc_regs[CODE]); + lispobj *args; + + args = current_control_stack_pointer; + current_control_stack_pointer += 3; + args[0] = fixnum(calc_offset(code, scp->sc_pc)); + args[1] = scp->sc_regs[CODE]; + args[2] = alloc_sap(scp); + call_into_lisp(HANDLE_BREAKPOINT, SymbolFunction(HANDLE_BREAKPOINT), + args, 3); + scp->sc_mask = sigblock(0); +}