📄 i960-tdep.c
字号:
struct frame_saved_regs *fsr;{ register CORE_ADDR next_addr; register CORE_ADDR *saved_regs; register int regnum; register struct frame_saved_regs *cache_fsr; extern struct obstack frame_cache_obstack; CORE_ADDR ip; struct symtab_and_line sal; CORE_ADDR limit; if (!fi->fsr) { cache_fsr = (struct frame_saved_regs *) obstack_alloc (&frame_cache_obstack, sizeof (struct frame_saved_regs)); bzero (cache_fsr, sizeof (struct frame_saved_regs)); fi->fsr = cache_fsr; /* Find the start and end of the function prologue. If the PC is in the function prologue, we only consider the part that has executed already. */ ip = get_pc_function_start (fi->pc); sal = find_pc_line (ip, 0); limit = (sal.end && sal.end < fi->pc) ? sal.end: fi->pc; examine_prologue (ip, limit, fi->frame, cache_fsr); /* Record the addresses at which the local registers are saved. Strictly speaking, we should only do this for non-leaf procedures, but no one will ever look at these values if it is a leaf procedure, since local registers are always caller-saved. */ next_addr = (CORE_ADDR) fi->frame; saved_regs = cache_fsr->regs; for (regnum = R0_REGNUM; regnum <= R15_REGNUM; regnum++) { *saved_regs++ = next_addr; next_addr += 4; } cache_fsr->regs[FP_REGNUM] = cache_fsr->regs[PFP_REGNUM]; } *fsr = *fi->fsr; /* Fetch the value of the sp from memory every time, since it is conceivable that it has changed since the cache was flushed. This unfortunately undoes much of the savings from caching the saved register values. I suggest adding an argument to get_frame_saved_regs () specifying the register number we're interested in (or -1 for all registers). This would be passed through to FRAME_FIND_SAVED_REGS (), permitting more efficient computation of saved register addresses (e.g., on the i960, we don't have to examine the prologue to find local registers). -- markf@wrs.com FIXME, we don't need to refetch this, since the cache is cleared every time the child process is restarted. If GDB itself modifies SP, it has to clear the cache by hand (does it?). -gnu */ fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[SP_REGNUM], 4);}/* Return the address of the argument block for the frame described by FI. Returns 0 if the address is unknown. */CORE_ADDRframe_args_address (fi, must_be_correct) struct frame_info *fi;{ register FRAME frame; struct frame_saved_regs fsr; CORE_ADDR ap; /* If g14 was saved in the frame by the function prologue code, return the saved value. If the frame is current and we are being sloppy, return the value of g14. Otherwise, return zero. */ frame = FRAME_INFO_ID (fi); get_frame_saved_regs (fi, &fsr); if (fsr.regs[G14_REGNUM]) ap = read_memory_integer (fsr.regs[G14_REGNUM],4); else { if (must_be_correct) return 0; /* Don't cache this result */ if (get_next_frame (frame)) ap = 0; else ap = read_register (G14_REGNUM); if (ap == 0) ap = fi->frame; } fi->arg_pointer = ap; /* Cache it for next time */ return ap;}/* Return the address of the return struct for the frame described by FI. Returns 0 if the address is unknown. */CORE_ADDRframe_struct_result_address (fi) struct frame_info *fi;{ register FRAME frame; struct frame_saved_regs fsr; CORE_ADDR ap; /* If the frame is non-current, check to see if g14 was saved in the frame by the function prologue code; return the saved value if so, zero otherwise. If the frame is current, return the value of g14. FIXME, shouldn't this use the saved value as long as we are past the function prologue, and only use the current value if we have no saved value and are at TOS? -- gnu@cygnus.com */ frame = FRAME_INFO_ID (fi); if (get_next_frame (frame)) { get_frame_saved_regs (fi, &fsr); if (fsr.regs[G13_REGNUM]) ap = read_memory_integer (fsr.regs[G13_REGNUM],4); else ap = 0; } else { ap = read_register (G13_REGNUM); } return ap;}/* Return address to which the currently executing leafproc will return, or 0 if ip is not in a leafproc (or if we can't tell if it is). Do this by finding the starting address of the routine in which ip lies. If the instruction there is "mov g14, gx" (where x is in [0,7]), this is a leafproc and the return address is in register gx. Well, this is true unless the return address points at a RET instruction in the current procedure, which indicates that we have a 'dual entry' routine that has been entered through the CALL entry point. */CORE_ADDRleafproc_return (ip) CORE_ADDR ip; /* ip from currently executing function */{ register struct minimal_symbol *msymbol; char *p; int dst; unsigned int insn1, insn2; CORE_ADDR return_addr; char *index (); if ((msymbol = lookup_minimal_symbol_by_pc (ip)) != NULL) { if ((p = index (msymbol -> name, '.')) && !strcmp (p, ".lf")) { if (next_insn (msymbol -> address, &insn1, &insn2) && (insn1 & 0xff87ffff) == 0x5c80161e /* mov g14, gx */ && (dst = REG_SRCDST (insn1)) <= G0_REGNUM + 7) { /* Get the return address. If the "mov g14, gx" instruction hasn't been executed yet, read the return address from g14; otherwise, read it from the register into which g14 was moved. */ return_addr = read_register ((ip == msymbol->address) ? G14_REGNUM : dst); /* We know we are in a leaf procedure, but we don't know whether the caller actually did a "bal" to the ".lf" entry point, or a normal "call" to the non-leaf entry point one instruction before. In the latter case, the return address will be the address of a "ret" instruction within the procedure itself. We test for this below. */ if (!next_insn (return_addr, &insn1, &insn2) || (insn1 & 0xff000000) != 0xa000000 /* ret */ || lookup_minimal_symbol_by_pc (return_addr) != msymbol) return (return_addr); } } } return (0);}/* Immediately after a function call, return the saved pc. Can't go through the frames for this because on some machines the new frame is not set up until the new function executes some instructions. On the i960, the frame *is* set up immediately after the call, unless the function is a leaf procedure. */CORE_ADDRsaved_pc_after_call (frame) FRAME frame;{ CORE_ADDR saved_pc; CORE_ADDR get_frame_pc (); saved_pc = leafproc_return (get_frame_pc (frame)); if (!saved_pc) saved_pc = FRAME_SAVED_PC (frame); return (saved_pc);}/* Discard from the stack the innermost frame, restoring all saved registers. */pop_frame (){ register struct frame_info *current_fi, *prev_fi; register int i; CORE_ADDR save_addr; CORE_ADDR leaf_return_addr; struct frame_saved_regs fsr; char local_regs_buf[16 * 4]; current_fi = get_frame_info (get_current_frame ()); /* First, undo what the hardware does when we return. If this is a non-leaf procedure, restore local registers from the save area in the calling frame. Otherwise, load the return address obtained from leafproc_return () into the rip. */ leaf_return_addr = leafproc_return (current_fi->pc); if (!leaf_return_addr) { /* Non-leaf procedure. Restore local registers, incl IP. */ prev_fi = get_frame_info (get_prev_frame (FRAME_INFO_ID (current_fi))); read_memory (prev_fi->frame, local_regs_buf, sizeof (local_regs_buf)); write_register_bytes (REGISTER_BYTE (R0_REGNUM), local_regs_buf, sizeof (local_regs_buf)); /* Restore frame pointer. */ write_register (FP_REGNUM, prev_fi->frame); } else { /* Leaf procedure. Just restore the return address into the IP. */ write_register (RIP_REGNUM, leaf_return_addr); } /* Now restore any global regs that the current function had saved. */ get_frame_saved_regs (current_fi, &fsr); for (i = G0_REGNUM; i < G14_REGNUM; i++) { if (save_addr = fsr.regs[i]) write_register (i, read_memory_integer (save_addr, 4)); } /* Flush the frame cache, create a frame for the new innermost frame, and make it the current frame. */ flush_cached_frames (); set_current_frame (create_new_frame (read_register (FP_REGNUM), read_pc ()));}/* Print out text describing a "signal number" with which the i80960 halted. See the file "fault.c" in the nindy monitor source code for a list of stop codes. */voidprint_fault( siggnal ) int siggnal; /* Signal number, as returned by target_wait() */{ static char unknown[] = "Unknown fault or trace"; static char *sigmsgs[] = { /* FAULTS */ "parallel fault", /* 0x00 */ unknown, /* 0x01 */ "operation fault", /* 0x02 */ "arithmetic fault", /* 0x03 */ "floating point fault", /* 0x04 */ "constraint fault", /* 0x05 */ "virtual memory fault", /* 0x06 */ "protection fault", /* 0x07 */ "machine fault", /* 0x08 */ "structural fault", /* 0x09 */ "type fault", /* 0x0a */ "reserved (0xb) fault", /* 0x0b */ "process fault", /* 0x0c */ "descriptor fault", /* 0x0d */ "event fault", /* 0x0e */ "reserved (0xf) fault", /* 0x0f */ /* TRACES */ "single-step trace", /* 0x10 */ "branch trace", /* 0x11 */ "call trace", /* 0x12 */ "return trace", /* 0x13 */ "pre-return trace", /* 0x14 */ "supervisor call trace",/* 0x15 */ "breakpoint trace", /* 0x16 */ };# define NUMMSGS ((int)( sizeof(sigmsgs) / sizeof(sigmsgs[0]) )) if (siggnal < NSIG) { printf ("\nProgram received signal %d, %s\n", siggnal, safe_strsignal (siggnal)); } else { /* The various target_wait()s bias the 80960 "signal number" by adding NSIG to it, so it won't get confused with any of the Unix signals elsewhere in GDB. We need to "unbias" it before using it. */ siggnal -= NSIG; printf("Program stopped for reason #%d: %s.\n", siggnal, (siggnal < NUMMSGS && siggnal >= 0)? sigmsgs[siggnal] : unknown ); }}/* Initialization stub */_initialize_i960_tdep (){ check_host ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -