static void frv_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int reg, const gdb_byte *buffer) { if (reg == iacc0_regnum) { regcache_raw_write (regcache, iacc0h_regnum, buffer); regcache_raw_write (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4); } else if (accg0_regnum <= reg && reg <= accg7_regnum) { /* The accg raw registers have four values in each slot with the lowest register number occupying the first byte. */ int raw_regnum = accg0123_regnum + (reg - accg0_regnum) / 4; int byte_num = (reg - accg0_regnum) % 4; char buf[4]; regcache_raw_read (regcache, raw_regnum, buf); buf[byte_num] = ((bfd_byte *) buffer)[0]; regcache_raw_write (regcache, raw_regnum, buf); } }
static void m68k_store_return_value (struct type *type, struct regcache *regcache, const gdb_byte *valbuf) { int len = TYPE_LENGTH (type); if (len <= 4) regcache_raw_write_part (regcache, M68K_D0_REGNUM, 4 - len, len, valbuf); else if (len <= 8) { regcache_raw_write_part (regcache, M68K_D0_REGNUM, 8 - len, len - 4, valbuf); regcache_raw_write (regcache, M68K_D1_REGNUM, valbuf + (len - 4)); } else internal_error (__FILE__, __LINE__, _("Cannot store return value of %d bytes long."), len); }
static void fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, CORE_ADDR reg_addr) { char *srcp = core_reg_sect; int regsize = mips_isa_regsize (current_gdbarch); int regno; /* If regsize is 8, this is a N32 or N64 core file. If regsize is 4, this is an O32 core file. */ if (core_reg_size != regsize * NUM_REGS) { warning (_("wrong size gregset struct in core file")); return; } for (regno = 0; regno < NUM_REGS; regno++) { regcache_raw_write (current_regcache, regno, srcp); srcp += regsize; } }
static void ppc_push_argument (struct ppc_stack_abi *abi, struct ppc_stack_context *c, struct value *arg, int argno, int do_copy, int floatonly) { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); struct type *type = check_typedef (value_type (arg)); int len = TYPE_LENGTH (type); gdb_byte buf[16]; c->argoffset = ROUND_UP (c->argoffset, 4); switch (TYPE_CODE (type)) { case TYPE_CODE_FLT: { if (c->freg <= abi->last_freg) { struct value *rval; struct type *rtype; int rlen; /* APPLE LOCAL: If the thing is already a long double type, don't cast it to a builtin type double, since there are two long double types, and we will pass an 16 byte long double wrong if we assume it is an 8 byte double. */ if (strcmp (TYPE_NAME (type), "long double") != 0) { rval = value_cast (builtin_type_double, arg); rtype = check_typedef (value_type (rval)); rlen = TYPE_LENGTH (rtype); } else { rval = arg; rtype = type; rlen = len; } /* APPLE LOCAL: GCC 4.0 has 16 byte long doubles */ if ((len != 4) && (len != 8) && (len != 16)) error ("floating point parameter had unexpected size"); if (rlen != 8 && rlen != 16) error ("floating point parameter had unexpected size"); if (do_copy) regcache_raw_write (current_regcache, FP0_REGNUM + c->freg, value_contents (rval)); if (do_copy && ! floatonly && abi->fregs_shadow_gregs) ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, len, value_contents (arg)); if (do_copy && ! floatonly && abi->regs_shadow_stack) write_memory (c->sp + c->argoffset, value_contents (arg), len); c->freg++; /* APPLE LOCAL: We took up two registers... */ if (rlen == 16) c->freg++; if (! floatonly && (abi->fregs_shadow_gregs) && (c->greg <= abi->last_greg)) c->greg += len / 4; if (! floatonly && abi->regs_shadow_stack) c->argoffset += len; } else if (! floatonly) { if ((len != 4) && (len != 8) && (len != 16)) error ("floating point parameter had unexpected size"); c->argoffset = ROUND_UP (c->argoffset, len); if (do_copy) write_memory (c->sp + c->argoffset, value_contents (arg), len); c->argoffset += len; } break; } case TYPE_CODE_INT: case TYPE_CODE_ENUM: case TYPE_CODE_PTR: case TYPE_CODE_REF: { int nregs; gdb_byte *val_contents; if (floatonly) break; /* APPLE LOCAL: Huge Hack... The problem is that if we are a 32 bit app on Mac OS X, the registers are really 64 bits, but we don't want to pass all 64 bits. So if we get passed a value that came from a register, and it's length is > the wordsize, cast it to the wordsize first before passing it in. */ if (VALUE_REGNUM (arg) != -1 && len == 8 && tdep->wordsize == 4) { len = 4; val_contents = value_contents (arg) + 4; } else val_contents = value_contents (arg); /* END APPLE LOCAL */ nregs = (len <= 4) ? 1 : 2; if ((len != 1) && (len != 2) && (len != 4) && (len != 8)) error ("integer parameter had unexpected size"); if (c->greg <= abi->last_greg) { /* If the parameter fits in the remaining argument registers, write it to the registers, and to the stack if the abi requires it. */ if (do_copy) { /* Split the argument between registers & the stack if it doesn't fit in the remaining registers. */ int regs_avaliable = abi->last_greg - c->greg + 1; if (regs_avaliable >= nregs) regs_avaliable = nregs; ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, regs_avaliable * 4, val_contents); } if (do_copy && abi->regs_shadow_stack) write_memory (c->sp + c->argoffset, val_contents, len); c->greg += nregs; if (abi->regs_shadow_stack) c->argoffset += (nregs * 4); } else { /* If we've filled up the registers, then just write it on the stack. */ if (do_copy) write_memory (c->sp + c->argoffset, val_contents, len); c->argoffset += (nregs * 4); } break; } case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: { if (! abi->structs_with_args) { if (floatonly) break; if (len > 4) { /* Rounding to the nearest multiple of 8 may not be necessary, but it is safe. Particularly since we don't know the field types of the structure */ c->structoffset = ROUND_UP (c->structoffset, 8); if (do_copy) { write_memory (c->sp + c->structoffset, value_contents (arg), len); store_unsigned_integer (buf, 4, c->sp + c->structoffset); } c->structoffset += ROUND_UP (len, 8); } else if (do_copy) { memset (buf, 0, 4); memcpy (buf, value_contents (arg), len); } if (c->greg <= abi->last_greg) { if (do_copy) ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, 4, buf); c->greg++; } else { if (do_copy) write_memory (c->sp + c->argoffset, buf, 4); c->argoffset += 4; } break; } else { int i; int regspace = (abi->last_greg - c->greg + 1) * 4; int stackspace = (len <= regspace) ? 0 : (len - regspace); int writereg = (regspace > len) ? len : regspace; int writestack = abi->regs_shadow_stack ? len : stackspace; for (i = 0; i < TYPE_NFIELDS (type); i++) { struct value *subarg = value_field (arg, i); ppc_push_argument (abi, c, subarg, argno, do_copy, 1); } if (floatonly) break; if (do_copy) { gdb_byte *ptr = value_contents (arg); if (len < 4) { memset (buf, 0, 4); if ((len == 1) || (len == 2)) memcpy (buf + 4 - len, ptr, len); else memcpy (buf, ptr, len); ptr = buf; } ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, (writereg < 4) ? 4 : writereg, ptr); write_memory (c->sp + c->argoffset, ptr, (writestack < 4) ? 4 : writestack); } c->greg += ROUND_UP (writereg, 4) / 4; c->argoffset += writestack; } break; } case TYPE_CODE_ARRAY: { if (floatonly) break; if (! TYPE_VECTOR (type)) error ("non-vector array type"); if (len != 16) error ("unexpected vector length"); if (c->vreg <= abi->last_vreg) { if (do_copy) regcache_raw_write (current_regcache, tdep->ppc_vr0_regnum + c->vreg, value_contents (arg)); c->vreg++; } else { /* Vector arguments must be aligned to 16 bytes on the stack. */ c->argoffset = ROUND_UP (c->argoffset, 16); if (do_copy) write_memory (c->sp + c->argoffset, value_contents (arg), len); c->argoffset += len; } break; } default: error ("argument %d has unknown type code 0x%x (%s)", argno, TYPE_CODE (type), type_code_name (TYPE_CODE (type))); } return; }
static CORE_ADDR m88k_store_arguments (struct regcache *regcache, int nargs, struct value **args, CORE_ADDR sp) { struct gdbarch *gdbarch = get_regcache_arch (regcache); int num_register_words = 0; int num_stack_words = 0; int i; for (i = 0; i < nargs; i++) { struct type *type = value_type (args[i]); int len = TYPE_LENGTH (type); if (m88k_integral_or_pointer_p (type) && len < 4) { args[i] = value_cast (builtin_type (gdbarch)->builtin_int32, args[i]); type = value_type (args[i]); len = TYPE_LENGTH (type); } if (m88k_in_register_p (type)) { int num_words = 0; if (num_register_words % 2 == 1 && m88k_8_byte_align_p (type)) num_words++; num_words += ((len + 3) / 4); if (num_register_words + num_words <= 8) { num_register_words += num_words; continue; } /* We've run out of available registers. Pass the argument on the stack. */ } if (num_stack_words % 2 == 1 && m88k_8_byte_align_p (type)) num_stack_words++; num_stack_words += ((len + 3) / 4); } /* Allocate stack space. */ sp = align_down (sp - 32 - num_stack_words * 4, 16); num_stack_words = num_register_words = 0; for (i = 0; i < nargs; i++) { const bfd_byte *valbuf = value_contents (args[i]); struct type *type = value_type (args[i]); int len = TYPE_LENGTH (type); int stack_word = num_stack_words; if (m88k_in_register_p (type)) { int register_word = num_register_words; if (register_word % 2 == 1 && m88k_8_byte_align_p (type)) register_word++; gdb_assert (len == 4 || len == 8); if (register_word + len / 8 < 8) { int regnum = M88K_R2_REGNUM + register_word; regcache_raw_write (regcache, regnum, valbuf); if (len > 4) regcache_raw_write (regcache, regnum + 1, valbuf + 4); num_register_words = (register_word + len / 4); continue; } } if (stack_word % 2 == -1 && m88k_8_byte_align_p (type)) stack_word++; write_memory (sp + stack_word * 4, valbuf, len); num_stack_words = (stack_word + (len + 3) / 4); } return sp; }
static CORE_ADDR i386_darwin_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); gdb_byte buf[4]; int i; int write_pass; /* Determine the total space required for arguments and struct return address in a first pass, then push arguments in a second pass. */ for (write_pass = 0; write_pass < 2; write_pass++) { int args_space = 0; int num_m128 = 0; if (struct_return) { if (write_pass) { /* Push value address. */ store_unsigned_integer (buf, 4, byte_order, struct_addr); write_memory (sp, buf, 4); } args_space += 4; } for (i = 0; i < nargs; i++) { struct type *arg_type = value_enclosing_type (args[i]); if (i386_m128_p (arg_type) && num_m128 < 4) { if (write_pass) { const gdb_byte *val = value_contents_all (args[i]); regcache_raw_write (regcache, I387_MM0_REGNUM(tdep) + num_m128, val); } num_m128++; } else { args_space = align_up (args_space, i386_darwin_arg_type_alignment (arg_type)); if (write_pass) write_memory (sp + args_space, value_contents_all (args[i]), TYPE_LENGTH (arg_type)); /* The System V ABI says that: "An argument's size is increased, if necessary, to make it a multiple of [32-bit] words. This may require tail padding, depending on the size of the argument." This makes sure the stack stays word-aligned. */ args_space += align_up (TYPE_LENGTH (arg_type), 4); } } /* Darwin i386 ABI: 1. The caller ensures that the stack is 16-byte aligned at the point of the function call. */ if (!write_pass) sp = align_down (sp - args_space, 16); } /* Store return address. */ sp -= 4; store_unsigned_integer (buf, 4, byte_order, bp_addr); write_memory (sp, buf, 4); /* Finally, update the stack pointer... */ store_unsigned_integer (buf, 4, byte_order, sp); regcache_cooked_write (regcache, I386_ESP_REGNUM, buf); /* ...and fake a frame pointer. */ regcache_cooked_write (regcache, I386_EBP_REGNUM, buf); /* MarkK wrote: This "+ 8" is all over the place: (i386_frame_this_id, i386_sigtramp_frame_this_id, i386_dummy_id). It's there, since all frame unwinders for a given target have to agree (within a certain margin) on the definition of the stack address of a frame. Otherwise frame id comparison might not work correctly. Since DWARF2/GCC uses the stack address *before* the function call as a frame's CFA. On the i386, when %ebp is used as a frame pointer, the offset between the contents %ebp and the CFA as defined by GCC. */ return sp + 8; }