diff options
author | Andrew Cagney <cagney@redhat.com> | 2004-03-07 17:06:21 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2004-03-07 17:06:21 +0000 |
commit | 449e11371210fe4bfd40786f835a4a51d7f74886 (patch) | |
tree | 8feded75413183841a9b2aa95ef65219effa51af | |
parent | 758d77bec11a769b8c2193934c5b0d94c857650a (diff) | |
download | gdb-449e11371210fe4bfd40786f835a4a51d7f74886.zip gdb-449e11371210fe4bfd40786f835a4a51d7f74886.tar.gz gdb-449e11371210fe4bfd40786f835a4a51d7f74886.tar.bz2 |
2004-03-07 Andrew Cagney <cagney@redhat.com>
* hppa-tdep.c: Replace PC_REGNUM with PCOQ_HEAD_REGNUM.
(hppa64_return_value, hppa64_push_dummy_call): Rewrite.
(hppa_gdbarch_init): Do not set PC_REGNUM.
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/hppa-tdep.c | 189 |
2 files changed, 98 insertions, 97 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f64a405..833396e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2004-03-07 Andrew Cagney <cagney@redhat.com> + + * hppa-tdep.c: Replace PC_REGNUM with PCOQ_HEAD_REGNUM. + (hppa64_return_value, hppa64_push_dummy_call): Rewrite. + (hppa_gdbarch_init): Do not set PC_REGNUM. + 2004-03-06 Mark Kettenis <kettenis@gnu.org> * config/alpha/tm-fbsd.h: Remove file. diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 549a811..3a0c0f1 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -303,7 +303,8 @@ hppa64_return_value (struct gdbarch *gdbarch, are in r28, padded on the left. Aggregates less that 65 bits are in r28, right padded. Aggregates upto 128 bits are in r28 and r29, right padded. */ - if (TYPE_CODE (type) == TYPE_CODE_FLT) + if (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) <= 8) { /* Floats are right aligned? */ int offset = register_size (gdbarch, FP4_REGNUM) - TYPE_LENGTH (type); @@ -333,15 +334,15 @@ hppa64_return_value (struct gdbarch *gdbarch, int b; for (b = 0; b < TYPE_LENGTH (type); b += 8) { - int part = (TYPE_LENGTH (type) - b - 1) % 8 + 1; + int part = min (8, TYPE_LENGTH (type) - b); if (readbuf != NULL) - regcache_cooked_read_part (regcache, 28, 0, part, + regcache_cooked_read_part (regcache, 28 + b / 8, 0, part, (char *) readbuf + b); if (writebuf != NULL) - regcache_cooked_write_part (regcache, 28, 0, part, + regcache_cooked_write_part (regcache, 28 + b / 8, 0, part, (const char *) writebuf + b); } - return RETURN_VALUE_REGISTER_CONVENTION; + return RETURN_VALUE_REGISTER_CONVENTION; } else return RETURN_VALUE_STRUCT_CONVENTION; @@ -1137,7 +1138,7 @@ hppa_frame_saved_pc (struct frame_info *frame) are saved in the exact same order as GDB numbers registers. How convienent. */ if (pc_in_interrupt_handler (pc)) - return read_memory_integer (get_frame_base (frame) + PC_REGNUM * 4, + return read_memory_integer (get_frame_base (frame) + PCOQ_HEAD_REGNUM * 4, TARGET_PTR_BIT / 8) & ~0x3; if ((get_frame_pc (frame) >= get_frame_base (frame) @@ -2292,111 +2293,106 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { - /* Array of arguments' offsets. */ - int *offset = (int *) alloca (nargs * sizeof (int)); - - /* Array of arguments' lengths: real lengths in bytes, not aligned - to word size. */ - int *lengths = (int *) alloca (nargs * sizeof (int)); - - /* The value of SP as it was passed into this function. */ - CORE_ADDR orig_sp = sp; - - /* The number of stack bytes occupied by the current argument. */ - int bytes_reserved; + /* NOTE: cagney/2004-02-27: This is a guess - its implemented by + reverse engineering testsuite failures. */ - /* The total number of bytes reserved for the arguments. */ - int cum_bytes_reserved = 0; + /* Stack base address at which any pass-by-reference parameters are + stored. */ + CORE_ADDR struct_end = 0; + /* Stack base address at which the first parameter is stored. */ + CORE_ADDR param_end = 0; - /* Similarly, but aligned. */ - int cum_bytes_aligned = 0; - int i; + /* The inner most end of the stack after all the parameters have + been pushed. */ + CORE_ADDR new_sp = 0; - /* Iterate over each argument provided by the user. */ - for (i = 0; i < nargs; i++) + /* Two passes. First pass computes the location of everything, + second pass writes the bytes out. */ + int write_pass; + for (write_pass = 0; write_pass < 2; write_pass++) { - struct type *arg_type = VALUE_TYPE (args[i]); - - /* Integral scalar values smaller than a register are padded on - the left. We do this by promoting them to full-width, - although the ABI says to pad them with garbage. */ - if (is_integral_type (arg_type) - && TYPE_LENGTH (arg_type) < DEPRECATED_REGISTER_SIZE) + CORE_ADDR struct_ptr = 0; + CORE_ADDR param_ptr = 0; + int i; + for (i = 0; i < nargs; i++) { - args[i] = value_cast ((TYPE_UNSIGNED (arg_type) - ? builtin_type_unsigned_long - : builtin_type_long), - args[i]); - arg_type = VALUE_TYPE (args[i]); + struct value *arg = args[i]; + struct type *type = check_typedef (VALUE_TYPE (arg)); + if ((TYPE_CODE (type) == TYPE_CODE_INT + || TYPE_CODE (type) == TYPE_CODE_ENUM) + && TYPE_LENGTH (type) <= 8) + { + /* Integer value store, right aligned. "unpack_long" + takes care of any sign-extension problems. */ + param_ptr += 8; + if (write_pass) + { + ULONGEST val = unpack_long (type, VALUE_CONTENTS (arg)); + int reg = 27 - param_ptr / 8; + write_memory_unsigned_integer (param_end - param_ptr, + val, 8); + if (reg >= 19) + regcache_cooked_write_unsigned (regcache, reg, val); + } + } + else + { + /* Small struct value, store left aligned? */ + int reg; + if (TYPE_LENGTH (type) > 8) + { + param_ptr = align_up (param_ptr, 16); + reg = 26 - param_ptr / 8; + param_ptr += align_up (TYPE_LENGTH (type), 16); + } + else + { + param_ptr = align_up (param_ptr, 8); + reg = 26 - param_ptr / 8; + param_ptr += align_up (TYPE_LENGTH (type), 8); + } + if (write_pass) + { + int byte; + write_memory (param_end - param_ptr, VALUE_CONTENTS (arg), + TYPE_LENGTH (type)); + for (byte = 0; byte < TYPE_LENGTH (type); byte += 8) + { + if (reg >= 19) + { + int len = min (8, TYPE_LENGTH (type) - byte); + regcache_cooked_write_part (regcache, reg, 0, len, + VALUE_CONTENTS (arg) + byte); + } + reg--; + } + } + } } - - lengths[i] = TYPE_LENGTH (arg_type); - - /* Align the size of the argument to the word size for this - target. */ - bytes_reserved = (lengths[i] + DEPRECATED_REGISTER_SIZE - 1) & -DEPRECATED_REGISTER_SIZE; - - offset[i] = cum_bytes_reserved; - - /* Aggregates larger than eight bytes (the only types larger - than eight bytes we have) are aligned on a 16-byte boundary, - possibly padded on the right with garbage. This may leave an - empty word on the stack, and thus an unused register, as per - the ABI. */ - if (bytes_reserved > 8) + /* Update the various stack pointers. */ + if (!write_pass) { - /* Round up the offset to a multiple of two slots. */ - int new_offset = ((offset[i] + 2*DEPRECATED_REGISTER_SIZE-1) - & -(2*DEPRECATED_REGISTER_SIZE)); - - /* Note the space we've wasted, if any. */ - bytes_reserved += new_offset - offset[i]; - offset[i] = new_offset; + struct_end = sp + struct_ptr; + /* PARAM_PTR already accounts for all the arguments passed + by the user. However, the ABI mandates minimum stack + space allocations for outgoing arguments. The ABI also + mandates minimum stack alignments which we must + preserve. */ + param_end = struct_end + max (align_up (param_ptr, 16), + REG_PARM_STACK_SPACE); } - - cum_bytes_reserved += bytes_reserved; } - /* CUM_BYTES_RESERVED already accounts for all the arguments passed - by the user. However, the ABIs mandate minimum stack space - allocations for outgoing arguments. - - The ABIs also mandate minimum stack alignments which we must - preserve. */ - cum_bytes_aligned = align_up (cum_bytes_reserved, 16); - sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE); - - /* Now write each of the args at the proper offset down the - stack. */ - for (i = 0; i < nargs; i++) - write_memory (orig_sp + offset[i], VALUE_CONTENTS (args[i]), lengths[i]); - /* If a structure has to be returned, set up register 28 to hold its address */ if (struct_return) write_register (28, struct_addr); - /* For the PA64 we must pass a pointer to the outgoing argument - list. The ABI mandates that the pointer should point to the - first byte of storage beyond the register flushback area. - - However, the call dummy expects the outgoing argument pointer to - be passed in register %r4. */ - write_register (4, orig_sp + REG_PARM_STACK_SPACE); - - /* ?!? This needs further work. We need to set up the global data - pointer for this procedure. This assumes the same global pointer - for every procedure. The call dummy expects the dp value to be - passed in register %r6. */ - write_register (6, read_register (27)); - /* Set the return address. */ regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr); - /* The stack will have 64 bytes of additional space for a frame - marker. */ - return sp + 64; - + /* The stack will have 32 bytes of additional space for a frame marker. */ + return param_end + 64; } static CORE_ADDR @@ -2946,7 +2942,7 @@ hppa_target_read_pc (ptid_t ptid) if (flags & 2) return read_register_pid (31, ptid) & ~0x3; - return read_register_pid (PC_REGNUM, ptid) & ~0x3; + return read_register_pid (PCOQ_HEAD_REGNUM, ptid) & ~0x3; } /* Write out the PC. If currently in a syscall, then also write the new @@ -2965,7 +2961,7 @@ hppa_target_write_pc (CORE_ADDR v, ptid_t ptid) if (flags & 2) write_register_pid (31, v | 0x3, ptid); - write_register_pid (PC_REGNUM, v, ptid); + write_register_pid (PCOQ_HEAD_REGNUM, v, ptid); write_register_pid (PCOQ_TAIL_REGNUM, v + 4, ptid); } @@ -4908,7 +4904,7 @@ hppa_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) static CORE_ADDR hppa_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { - return frame_unwind_register_signed (next_frame, PC_REGNUM) & ~3; + return frame_unwind_register_signed (next_frame, PCOQ_HEAD_REGNUM) & ~3; } /* Exception handling support for the HP-UX ANSI C++ compiler. @@ -5779,7 +5775,6 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_deprecated_fp_regnum (gdbarch, 3); set_gdbarch_sp_regnum (gdbarch, 30); set_gdbarch_fp0_regnum (gdbarch, 64); - set_gdbarch_pc_regnum (gdbarch, PCOQ_HEAD_REGNUM); set_gdbarch_deprecated_register_raw_size (gdbarch, hppa_register_raw_size); set_gdbarch_deprecated_register_byte (gdbarch, hppa_register_byte); set_gdbarch_deprecated_register_virtual_size (gdbarch, hppa_register_raw_size); |