CORE_ADDR ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); ULONGEST saved_sp; int argspace = 0; /* 0 is an initial wrong guess. */ int write_pass; gdb_assert (tdep->wordsize == 4); regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch), &saved_sp); /* Go through the argument list twice. Pass 1: Figure out how much new stack space is required for arguments and pushed values. Unlike the PowerOpen ABI, the SysV ABI doesn't reserve any extra space for parameters which are put in registers, but does always push structures and then pass their address. Pass 2: Replay the same computation but this time also write the values out to the target. */ for (write_pass = 0; write_pass < 2; write_pass++) { int argno; /* Next available floating point register for float and double arguments. */ int freg = 1; /* Next available general register for non-float, non-vector arguments. */ int greg = 3; /* Next available vector register for vector arguments. */ int vreg = 2; /* Arguments start above the "LR save word" and "Back chain". */ int argoffset = 2 * tdep->wordsize; /* Structures start after the arguments. */ int structoffset = argoffset + argspace; /* If the function is returning a `struct', then the first word (which will be passed in r3) is used for struct return address. In that case we should advance one word and start from r4 register to copy parameters. */ if (struct_return) { if (write_pass) regcache_cooked_write_signed (regcache, tdep->ppc_gp0_regnum + greg, struct_addr); greg++; } for (argno = 0; argno < nargs; argno++) { struct value *arg = args[argno]; struct type *type = check_typedef (value_type (arg)); int len = TYPE_LENGTH (type); const bfd_byte *val = value_contents (arg); if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8 && !tdep->soft_float) { /* Floating point value converted to "double" then passed in an FP register, when the registers run out, 8 byte aligned stack is used. */ if (freg <= 8) { if (write_pass) { /* Always store the floating point value using the register's floating-point format. */ gdb_byte regval[MAX_REGISTER_SIZE]; struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum + freg); convert_typed_floating (val, type, regval, regtype); regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, regval); } freg++; } else { /* The SysV ABI tells us to convert floats to doubles before writing them to an 8 byte aligned stack location. Unfortunately GCC does not do that, and stores floats into 4 byte aligned locations without converting them to doubles. Since there is no know compiler that actually follows the ABI here, we implement the GCC convention. */ /* Align to 4 bytes or 8 bytes depending on the type of the argument (float or double). */ argoffset = align_up (argoffset, len); if (write_pass) write_memory (sp + argoffset, val, len); argoffset += len; } } else if (TYPE_CODE (type) == TYPE_CODE_FLT && len == 16 && !tdep->soft_float && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double)) { /* IBM long double passed in two FP registers if available, otherwise 8-byte aligned stack. */ if (freg <= 7) { if (write_pass) { regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, val); regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg + 1, val + 8); } freg += 2; } else { argoffset = align_up (argoffset, 8); if (write_pass) write_memory (sp + argoffset, val, len); argoffset += 16; } } else if (len == 8 && (TYPE_CODE (type) == TYPE_CODE_INT /* long long */ || TYPE_CODE (type) == TYPE_CODE_FLT /* double */ || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && tdep->soft_float))) { /* "long long" or soft-float "double" or "_Decimal64" passed in an odd/even register pair with the low addressed word in the odd register and the high addressed word in the even register, or when the registers run out an 8 byte aligned stack location. */ if (greg > 9) { /* Just in case GREG was 10. */ greg = 11; argoffset = align_up (argoffset, 8); if (write_pass) write_memory (sp + argoffset, val, len); argoffset += 8; } else { /* Must start on an odd register - r3/r4 etc. */ if ((greg & 1) == 0) greg++; if (write_pass) { regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 0, val + 0); regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 1, val + 4); } greg += 2; } } else if (len == 16 && ((TYPE_CODE (type) == TYPE_CODE_FLT && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double)) || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && tdep->soft_float))) { /* Soft-float IBM long double or _Decimal128 passed in four consecutive registers, or on the stack. The registers are not necessarily odd/even pairs. */ if (greg > 7) { greg = 11; argoffset = align_up (argoffset, 8); if (write_pass) write_memory (sp + argoffset, val, len); argoffset += 16; } else { if (write_pass) { regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 0, val + 0); regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 1, val + 4); regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 2, val + 8); regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 3, val + 12); } greg += 4; } } else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len <= 8 && !tdep->soft_float) { /* 32-bit and 64-bit decimal floats go in f1 .. f8. They can end up in memory. */ if (freg <= 8) { if (write_pass) { gdb_byte regval[MAX_REGISTER_SIZE]; const gdb_byte *p; /* 32-bit decimal floats are right aligned in the doubleword. */ if (TYPE_LENGTH (type) == 4) { memcpy (regval + 4, val, 4); p = regval; } else p = val; regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, p); } freg++; } else { argoffset = align_up (argoffset, len); if (write_pass) /* Write value in the stack's parameter save area. */ write_memory (sp + argoffset, val, len); argoffset += len; } } else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len == 16 && !tdep->soft_float) { /* 128-bit decimal floats go in f2 .. f7, always in even/odd pairs. They can end up in memory, using two doublewords. */ if (freg <= 6) { /* Make sure freg is even. */ freg += freg & 1; if (write_pass) { regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, val); regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg + 1, val + 8); } } else { argoffset = align_up (argoffset, 8); if (write_pass) write_memory (sp + argoffset, val, 16); argoffset += 16; } /* If a 128-bit decimal float goes to the stack because only f7 and f8 are free (thus there's no even/odd register pair available), these registers should be marked as occupied. Hence we increase freg even when writing to memory. */ freg += 2; } else if (len == 16 && TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && tdep->vector_abi == POWERPC_VEC_ALTIVEC) { /* Vector parameter passed in an Altivec register, or when that runs out, 16 byte aligned stack location. */ if (vreg <= 13) { if (write_pass) regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + vreg, val); vreg++; } else { argoffset = align_up (argoffset, 16); if (write_pass) write_memory (sp + argoffset, val, 16); argoffset += 16; } } else if (len == 8 && TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && tdep->vector_abi == POWERPC_VEC_SPE) { /* Vector parameter passed in an e500 register, or when that runs out, 8 byte aligned stack location. Note that since e500 vector and general purpose registers both map onto the same underlying register set, a "greg" and not a "vreg" is consumed here. A cooked write stores the value in the correct locations within the raw register cache. */ if (greg <= 10) { if (write_pass) regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + greg, val); greg++; } else { argoffset = align_up (argoffset, 8); if (write_pass) write_memory (sp + argoffset, val, 8); argoffset += 8; } } else { /* Reduce the parameter down to something that fits in a "word". */ gdb_byte word[MAX_REGISTER_SIZE]; memset (word, 0, MAX_REGISTER_SIZE); if (len > tdep->wordsize || TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_UNION) { /* Structs and large values are put in an aligned stack slot ... */ if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && len >= 16) structoffset = align_up (structoffset, 16); else structoffset = align_up (structoffset, 8); if (write_pass) write_memory (sp + structoffset, val, len); /* ... and then a "word" pointing to that address is passed as the parameter. */ store_unsigned_integer (word, tdep->wordsize, byte_order, sp + structoffset); structoffset += len; } else if (TYPE_CODE (type) == TYPE_CODE_INT) /* Sign or zero extend the "int" into a "word". */ store_unsigned_integer (word, tdep->wordsize, byte_order, unpack_long (type, val)); else /* Always goes in the low address. */ memcpy (word, val, len); /* Store that "word" in a register, or on the stack. The words have "4" byte alignment. */ if (greg <= 10) { if (write_pass) regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, word); greg++; } else { argoffset = align_up (argoffset, tdep->wordsize); if (write_pass) write_memory (sp + argoffset, word, tdep->wordsize); argoffset += tdep->wordsize; } } } /* Compute the actual stack space requirements. */ if (!write_pass) { /* Remember the amount of space needed by the arguments. */ argspace = argoffset; /* Allocate space for both the arguments and the structures. */ sp -= (argoffset + structoffset); /* Ensure that the stack is still 16 byte aligned. */ sp = align_down (sp, 16); } /* The psABI says that "A caller of a function that takes a variable argument list shall set condition register bit 6 to 1 if it passes one or more arguments in the floating-point registers. It is strongly recommended that the caller set the bit to 0 otherwise..." Doing this for normal functions too shouldn't hurt. */ if (write_pass) { ULONGEST cr; regcache_cooked_read_unsigned (regcache, tdep->ppc_cr_regnum, &cr); if (freg > 1) cr |= 0x02000000; else cr &= ~0x02000000; regcache_cooked_write_unsigned (regcache, tdep->ppc_cr_regnum, cr); } } /* Update %sp. */ regcache_cooked_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp); /* Write the backchain (it occupies WORDSIZED bytes). */ write_memory_signed_integer (sp, tdep->wordsize, byte_order, saved_sp); /* Point the inferior function call's return address at the dummy's breakpoint. */ regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr); return sp; }
static void store_register (struct regcache *regcache, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); int addr[MAX_REGISTER_SIZE]; int nr, isfloat; /* Fetch the register's value from the register cache. */ regcache_raw_collect (regcache, regno, addr); /* -1 can be a successful return value, so infer errors from errno. */ errno = 0; nr = regmap (gdbarch, regno, &isfloat); /* Floating-point registers. */ if (isfloat) rs6000_ptrace32 (PT_WRITE_FPR, PIDGET (inferior_ptid), addr, nr, 0); /* Bogus register number. */ else if (nr < 0) { if (regno >= gdbarch_num_regs (gdbarch)) fprintf_unfiltered (gdb_stderr, "gdb error: register no %d not implemented.\n", regno); } /* Fixed-point registers. */ else { if (regno == gdbarch_sp_regnum (gdbarch)) /* Execute one dummy instruction (which is a breakpoint) in inferior process to give kernel a chance to do internal housekeeping. Otherwise the following ptrace(2) calls will mess up user stack since kernel will get confused about the bottom of the stack (%sp). */ exec_one_dummy_insn (regcache); /* The PT_WRITE_GPR operation is rather odd. For 32-bit inferiors, the register's value is passed by value, but for 64-bit inferiors, the address of a buffer containing the value is passed. */ if (!ARCH64 ()) rs6000_ptrace32 (PT_WRITE_GPR, PIDGET (inferior_ptid), (int *) nr, *addr, 0); else { /* PT_WRITE_GPR requires the buffer parameter to point to an 8-byte area, even if the register is really only 32 bits. */ long long buf; if (register_size (gdbarch, regno) == 8) memcpy (&buf, addr, 8); else buf = *addr; rs6000_ptrace64 (PT_WRITE_GPR, PIDGET (inferior_ptid), nr, 0, &buf); } } if (errno) { perror (_("ptrace write")); errno = 0; } }
void dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, void **tailcall_cachep, const LONGEST *entry_cfa_sp_offsetp) { CORE_ADDR prev_pc = 0, prev_sp = 0; /* GCC warning. */ int prev_sp_p = 0; CORE_ADDR this_pc; struct gdbarch *prev_gdbarch; struct call_site_chain *chain = NULL; struct tailcall_cache *cache; gdb_assert (*tailcall_cachep == NULL); /* PC may be after the function if THIS_FRAME calls noreturn function, get_frame_address_in_block will decrease it by 1 in such case. */ this_pc = get_frame_address_in_block (this_frame); /* Catch any unwinding errors. */ TRY { int sp_regnum; prev_gdbarch = frame_unwind_arch (this_frame); /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ prev_pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); /* call_site_find_chain can throw an exception. */ chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc); if (entry_cfa_sp_offsetp == NULL) break; sp_regnum = gdbarch_sp_regnum (prev_gdbarch); if (sp_regnum == -1) break; prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum); prev_sp_p = 1; } CATCH (except, RETURN_MASK_ERROR) { if (entry_values_debug) exception_print (gdb_stdout, except); return; } END_CATCH /* Ambiguous unwind or unambiguous unwind verified as matching. */ if (chain == NULL || chain->length == 0) { xfree (chain); return; } cache = cache_new_ref1 (this_frame); *tailcall_cachep = cache; cache->chain = chain; cache->prev_pc = prev_pc; cache->chain_levels = pretended_chain_levels (chain); cache->prev_sp_p = prev_sp_p; if (cache->prev_sp_p) { cache->prev_sp = prev_sp; cache->entry_cfa_sp_offset = *entry_cfa_sp_offsetp; } gdb_assert (cache->chain_levels > 0); }
static CORE_ADDR rs6000_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int ii; int len = 0; int argno; /* current argument number */ int argbytes; /* current argument byte */ gdb_byte tmp_buffer[50]; int f_argno = 0; /* current floating point argno */ int wordsize = gdbarch_tdep (gdbarch)->wordsize; CORE_ADDR func_addr = find_function_addr (function, NULL); struct value *arg = 0; struct type *type; ULONGEST saved_sp; /* The calling convention this function implements assumes the processor has floating-point registers. We shouldn't be using it on PPC variants that lack them. */ gdb_assert (ppc_floating_point_unit_p (gdbarch)); /* The first eight words of ther arguments are passed in registers. Copy them appropriately. */ ii = 0; /* If the function is returning a `struct', then the first word (which will be passed in r3) is used for struct return address. In that case we should advance one word and start from r4 register to copy parameters. */ if (struct_return) { regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3, struct_addr); ii++; } /* effectively indirect call... gcc does... return_val example( float, int); eabi: float in fp0, int in r3 offset of stack on overflow 8/16 for varargs, must go by type. power open: float in r3&r4, int in r5 offset of stack on overflow different both: return in r3 or f0. If no float, must study how gcc emulates floats; pay attention to arg promotion. User may have to cast\args to handle promotion correctly since gdb won't know if prototype supplied or not. */ for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii) { int reg_size = register_size (gdbarch, ii + 3); arg = args[argno]; type = check_typedef (value_type (arg)); len = TYPE_LENGTH (type); if (TYPE_CODE (type) == TYPE_CODE_FLT) { /* Floating point arguments are passed in fpr's, as well as gpr's. There are 13 fpr's reserved for passing parameters. At this point there is no way we would run out of them. */ gdb_assert (len <= 8); regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + f_argno, value_contents (arg)); ++f_argno; } if (len > reg_size) { /* Argument takes more than one register. */ while (argbytes < len) { gdb_byte word[MAX_REGISTER_SIZE]; memset (word, 0, reg_size); memcpy (word, ((char *) value_contents (arg)) + argbytes, (len - argbytes) > reg_size ? reg_size : len - argbytes); regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 + ii, word); ++ii, argbytes += reg_size; if (ii >= 8) goto ran_out_of_registers_for_arguments; } argbytes = 0; --ii; } else { /* Argument can fit in one register. No problem. */ int adj = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? reg_size - len : 0; gdb_byte word[MAX_REGISTER_SIZE]; memset (word, 0, reg_size); memcpy (word, value_contents (arg), len); regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word); } ++argno; } ran_out_of_registers_for_arguments: regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch), &saved_sp); /* Location for 8 parameters are always reserved. */ sp -= wordsize * 8; /* Another six words for back chain, TOC register, link register, etc. */ sp -= wordsize * 6; /* Stack pointer must be quadword aligned. */ sp &= -16; /* If there are more arguments, allocate space for them in the stack, then push them starting from the ninth one. */ if ((argno < nargs) || argbytes) { int space = 0, jj; if (argbytes) { space += ((len - argbytes + 3) & -4); jj = argno + 1; } else jj = argno; for (; jj < nargs; ++jj) { struct value *val = args[jj]; space += ((TYPE_LENGTH (value_type (val))) + 3) & -4; } /* Add location required for the rest of the parameters. */ space = (space + 15) & -16; sp -= space; /* This is another instance we need to be concerned about securing our stack space. If we write anything underneath %sp (r1), we might conflict with the kernel who thinks he is free to use this area. So, update %sp first before doing anything else. */ regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp); /* If the last argument copied into the registers didn't fit there completely, push the rest of it into stack. */ if (argbytes) { write_memory (sp + 24 + (ii * 4), value_contents (arg) + argbytes, len - argbytes); ++argno; ii += ((len - argbytes + 3) & -4) / 4; } /* Push the rest of the arguments into stack. */ for (; argno < nargs; ++argno) { arg = args[argno]; type = check_typedef (value_type (arg)); len = TYPE_LENGTH (type); /* Float types should be passed in fpr's, as well as in the stack. */ if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13) { gdb_assert (len <= 8); regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + f_argno, value_contents (arg)); ++f_argno; } write_memory (sp + 24 + (ii * 4), value_contents (arg), len); ii += ((len + 3) & -4) / 4; } } /* Set the stack pointer. According to the ABI, the SP is meant to be set _before_ the corresponding stack space is used. On AIX, this even applies when the target has been completely stopped! Not doing this can lead to conflicts with the kernel which thinks that it still has control over this not-yet-allocated stack region. */ regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp); /* Set back chain properly. */ store_unsigned_integer (tmp_buffer, wordsize, byte_order, saved_sp); write_memory (sp, tmp_buffer, wordsize); /* Point the inferior function call's return address at the dummy's breakpoint. */ regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr); /* Set the TOC register value. */ regcache_raw_write_signed (regcache, tdep->ppc_toc_regnum, solib_aix_get_toc_value (func_addr)); target_store_registers (regcache, -1); return sp; }
static struct libunwind_frame_cache * libunwind_frame_cache (struct frame_info *this_frame, void **this_cache) { unw_accessors_t *acc; unw_addr_space_t as; unw_word_t fp; unw_regnum_t uw_sp_regnum; struct libunwind_frame_cache *cache; struct libunwind_descr *descr; struct gdbarch *gdbarch = get_frame_arch (this_frame); int i, ret; if (*this_cache) return *this_cache; /* Allocate a new cache. */ cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache); cache->func_addr = get_frame_func (this_frame); if (cache->func_addr == 0) /* This can happen when the frame corresponds to a function for which there is no debugging information nor any entry in the symbol table. This is probably a static function for which an entry in the symbol table was not created when the objfile got linked (observed in libpthread.so on ia64-hpux). The best we can do, in that case, is use the frame PC as the function address. We don't need to give up since we still have the unwind record to help us perform the unwinding. There is also another compelling to continue, because abandonning now means stopping the backtrace, which can never be helpful for the user. */ cache->func_addr = get_frame_pc (this_frame); /* Get a libunwind cursor to the previous frame. We do this by initializing a cursor. Libunwind treats a new cursor as the top of stack and will get the current register set via the libunwind register accessor. Now, we provide the platform-specific accessors and we set up the register accessor to use the frame register unwinding interfaces so that we properly get the registers for the current frame rather than the top. We then use the unw_step function to move the libunwind cursor back one frame. We can later use this cursor to find previous registers via the unw_get_reg interface which will invoke libunwind's special logic. */ descr = libunwind_descr (gdbarch); acc = descr->accessors; as = unw_create_addr_space_p (acc, gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? __BIG_ENDIAN : __LITTLE_ENDIAN); unw_init_remote_p (&cache->cursor, as, this_frame); if (unw_step_p (&cache->cursor) < 0) { unw_destroy_addr_space_p (as); return NULL; } /* To get base address, get sp from previous frame. */ uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch)); ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp); if (ret < 0) { unw_destroy_addr_space_p (as); error (_("Can't get libunwind sp register.")); } cache->base = (CORE_ADDR)fp; cache->as = as; *this_cache = cache; return cache; }
static struct trad_frame_cache * mips_sde_frame_cache (struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); const struct mips_regnum *regs = mips_regnum (gdbarch); const int sizeof_reg_t = mips_abi_regsize (gdbarch); enum mips_abi abi = mips_abi (gdbarch); struct trad_frame_cache *cache; CORE_ADDR xcpt_frame; CORE_ADDR start_addr; CORE_ADDR stack_addr; CORE_ADDR pc; int i; if (*this_cache != NULL) return (struct trad_frame_cache *) *this_cache; cache = trad_frame_cache_zalloc (this_frame); *this_cache = cache; /* The previous registers are held in struct xcptcontext which is at $sp+offs struct xcptcontext { reg_t sr; CP0 Status reg_t cr; CP0 Cause reg_t epc; CP0 EPC reg_t vaddr; CP0 BadVAddr reg_t regs[32]; General registers reg_t mdlo; LO reg_t mdhi; HI reg_t mdex; ACX ... }; */ stack_addr = get_frame_register_signed (this_frame, gdbarch_sp_regnum (gdbarch)); switch (abi) { case MIPS_ABI_O32: /* 40: XCPTCONTEXT 24: xcpt_gen() argspace (16 bytes) 16: _xcptcall() saved ra, rounded up ( 8 bytes) 00: _xcptcall() argspace (16 bytes) */ xcpt_frame = stack_addr + 40; break; case MIPS_ABI_N32: case MIPS_ABI_N64: default: /* Wild guess. */ /* 16: XCPTCONTEXT 16: xcpt_gen() argspace ( 0 bytes) 00: _xcptcall() saved ra, rounded up (16 bytes) */ xcpt_frame = stack_addr + 16; break; } trad_frame_set_reg_addr (cache, MIPS_PS_REGNUM + gdbarch_num_regs (gdbarch), xcpt_frame + 0 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->cause + gdbarch_num_regs (gdbarch), xcpt_frame + 1 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->pc + gdbarch_num_regs (gdbarch), xcpt_frame + 2 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->badvaddr + gdbarch_num_regs (gdbarch), xcpt_frame + 3 * sizeof_reg_t); for (i = 0; i < MIPS_NUMREGS; i++) trad_frame_set_reg_addr (cache, i + MIPS_ZERO_REGNUM + gdbarch_num_regs (gdbarch), xcpt_frame + (4 + i) * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->lo + gdbarch_num_regs (gdbarch), xcpt_frame + 36 * sizeof_reg_t); trad_frame_set_reg_addr (cache, regs->hi + gdbarch_num_regs (gdbarch), xcpt_frame + 37 * sizeof_reg_t); pc = get_frame_pc (this_frame); find_pc_partial_function (pc, NULL, &start_addr, NULL); trad_frame_set_id (cache, frame_id_build (start_addr, stack_addr)); return cache; }