diff options
Diffstat (limited to 'gdb/hppa-tdep.c')
-rw-r--r-- | gdb/hppa-tdep.c | 216 |
1 files changed, 183 insertions, 33 deletions
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 8e50aef..699cd74 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -64,9 +64,20 @@ #include "target.h" #include "symfile.h" #include "objfiles.h" +#include "hppa-tdep.h" /* Some local constants. */ -static const int hppa_num_regs = 128; +static const int hppa32_num_regs = 128; +static const int hppa64_num_regs = 96; + +static const int hppa64_call_dummy_breakpoint_offset = 22 * 4; + +/* DEPRECATED_CALL_DUMMY_LENGTH is computed based on the size of a + word on the target machine, not the size of an instruction. Since + a word on this target holds two instructions we have to divide the + instruction size by two to get the word size of the dummy. */ +static const int hppa32_call_dummy_length = INSTRUCTION_SIZE * 28; +static const int hppa64_call_dummy_length = INSTRUCTION_SIZE * 26 / 2; /* Get at various relevent fields of an instruction word. */ #define MASK_5 0x1f @@ -164,16 +175,23 @@ int hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name); int hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name); CORE_ADDR hppa_saved_pc_after_call (struct frame_info *frame); int hppa_inner_than (CORE_ADDR lhs, CORE_ADDR rhs); -CORE_ADDR hppa_stack_align (CORE_ADDR sp); +CORE_ADDR hppa32_stack_align (CORE_ADDR sp); +CORE_ADDR hppa64_stack_align (CORE_ADDR sp); int hppa_pc_requires_run_before_use (CORE_ADDR pc); int hppa_instruction_nullified (void); int hppa_register_raw_size (int reg_nr); int hppa_register_byte (int reg_nr); -struct type * hppa_register_virtual_type (int reg_nr); +struct type * hppa32_register_virtual_type (int reg_nr); +struct type * hppa64_register_virtual_type (int reg_nr); void hppa_store_struct_return (CORE_ADDR addr, CORE_ADDR sp); -void hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf); -int hppa_use_struct_convention (int gcc_p, struct type *type); -void hppa_store_return_value (struct type *type, char *valbuf); +void hppa32_extract_return_value (struct type *type, char *regbuf, + char *valbuf); +void hppa64_extract_return_value (struct type *type, char *regbuf, + char *valbuf); +int hppa32_use_struct_convention (int gcc_p, struct type *type); +int hppa64_use_struct_convention (int gcc_p, struct type *type); +void hppa32_store_return_value (struct type *type, char *valbuf); +void hppa64_store_return_value (struct type *type, char *valbuf); CORE_ADDR hppa_extract_struct_value_address (char *regbuf); int hppa_cannot_store_register (int regnum); void hppa_init_extra_frame_info (int fromleaf, struct frame_info *frame); @@ -182,7 +200,6 @@ int hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe); int hppa_frameless_function_invocation (struct frame_info *frame); CORE_ADDR hppa_frame_saved_pc (struct frame_info *frame); CORE_ADDR hppa_frame_args_address (struct frame_info *fi); -CORE_ADDR hppa_frame_locals_address (struct frame_info *fi); int hppa_frame_num_args (struct frame_info *frame); void hppa_push_dummy_frame (void); void hppa_pop_frame (void); @@ -217,11 +234,19 @@ extern int exception_catchpoints_are_fragile; /* Should call_function allocate stack space for a struct return? */ int -hppa_use_struct_convention (int gcc_p, struct type *type) +hppa32_use_struct_convention (int gcc_p, struct type *type) { return (TYPE_LENGTH (type) > 2 * DEPRECATED_REGISTER_SIZE); } - + +/* Same as hppa32_use_struct_convention() for the PA64 ABI. */ + +int +hppa64_use_struct_convention (int gcc_p, struct type *type) +{ + /* RM: struct upto 128 bits are returned in registers */ + return TYPE_LENGTH (type) > 16; +} /* Routines to extract various sized constants out of hppa instructions. */ @@ -681,7 +706,7 @@ hppa_breakpoint_from_pc (CORE_ADDR *pc, int *len) /* Return the name of a register. */ const char * -hppa_register_name (int i) +hppa32_register_name (int i) { static char *names[] = { "flags", "r1", "rp", "r3", @@ -4782,7 +4807,7 @@ hppa_skip_permanent_breakpoint (void) Called only in the context of the "return" command. */ void -hppa_store_return_value (struct type *type, char *valbuf) +hppa32_store_return_value (struct type *type, char *valbuf) { /* For software floating point, the return value goes into the integer registers. But we do not have any flag to key this on, @@ -4800,6 +4825,32 @@ hppa_store_return_value (struct type *type, char *valbuf) valbuf, TYPE_LENGTH (type)); } +/* Same as hppa32_store_return_value(), but for the PA64 ABI. */ + +void +hppa64_store_return_value (struct type *type, char *valbuf) +{ + if (TYPE_CODE (type) == TYPE_CODE_FLT) + deprecated_write_register_bytes + (REGISTER_BYTE (FP4_REGNUM) + + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), + valbuf, TYPE_LENGTH (type)); + else if (is_integral_type(type)) + deprecated_write_register_bytes + (REGISTER_BYTE (28) + + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), + valbuf, TYPE_LENGTH (type)); + else if (TYPE_LENGTH (type) <= 8) + deprecated_write_register_bytes + (REGISTER_BYTE (28),valbuf, TYPE_LENGTH (type)); + else if (TYPE_LENGTH (type) <= 16) + { + deprecated_write_register_bytes (REGISTER_BYTE (28),valbuf, 8); + deprecated_write_register_bytes + (REGISTER_BYTE (29), valbuf + 8, TYPE_LENGTH (type) - 8); + } +} + /* Copy the function's return value into VALBUF. This function is called only in the context of "target function calls", @@ -4808,15 +4859,13 @@ hppa_store_return_value (struct type *type, char *valbuf) "return" command. */ void -hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf) +hppa32_extract_return_value (struct type *type, char *regbuf, char *valbuf) { if (TYPE_CODE (type) == TYPE_CODE_FLT) - memcpy (valbuf, - (char *)regbuf + REGISTER_BYTE (FP4_REGNUM), - TYPE_LENGTH (type)); + memcpy (valbuf, regbuf + REGISTER_BYTE (FP4_REGNUM), TYPE_LENGTH (type)); else memcpy (valbuf, - ((char *)regbuf + (regbuf + REGISTER_BYTE (28) + (TYPE_LENGTH (type) > 4 ? (8 - TYPE_LENGTH (type)) @@ -4824,6 +4873,34 @@ hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf) TYPE_LENGTH (type)); } +/* Same as hppa32_extract_return_value but for the PA64 ABI case. */ + +void +hppa64_extract_return_value (struct type *type, char *regbuf, char *valbuf) +{ + /* RM: Floats are returned in FR4R, doubles in FR4. + Integral values 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) + memcpy (valbuf, + regbuf + REGISTER_BYTE (FP4_REGNUM) + + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), + TYPE_LENGTH (type)); + else if (is_integral_type(type)) + memcpy (valbuf, + regbuf + REGISTER_BYTE (28) + + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), + TYPE_LENGTH (type)); + else if (TYPE_LENGTH (type) <= 8) + memcpy (valbuf, regbuf + REGISTER_BYTE (28), TYPE_LENGTH (type)); + else if (TYPE_LENGTH (type) <= 16) + { + memcpy (valbuf, regbuf + REGISTER_BYTE (28), 8); + memcpy (valbuf + 8, regbuf + REGISTER_BYTE (29), TYPE_LENGTH (type) - 8); + } +} + int hppa_reg_struct_has_addr (int gcc_p, struct type *type) { @@ -4840,7 +4917,7 @@ hppa_inner_than (CORE_ADDR lhs, CORE_ADDR rhs) } CORE_ADDR -hppa_stack_align (CORE_ADDR sp) +hppa32_stack_align (CORE_ADDR sp) { /* elz: adjust the quantity to the next highest value which is 64-bit aligned. This is used in valops.c, when the sp is adjusted. @@ -4848,6 +4925,13 @@ hppa_stack_align (CORE_ADDR sp) return ((sp % 8) ? (sp + 7) & -8 : sp); } +CORE_ADDR +hppa64_stack_align (CORE_ADDR sp) +{ + /* The PA64 ABI mandates a 16 byte stack alignment. */ + return ((sp % 16) ? (sp + 15) & -16 : sp); +} + int hppa_pc_requires_run_before_use (CORE_ADDR pc) { @@ -4901,14 +4985,16 @@ hppa_register_raw_size (int reg_nr) int hppa_register_byte (int reg_nr) { - return reg_nr * 4; + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + return reg_nr * tdep->bytes_per_address; } /* Return the GDB type object for the "standard" data type of data in register N. */ struct type * -hppa_register_virtual_type (int reg_nr) +hppa32_register_virtual_type (int reg_nr) { if (reg_nr < FP4_REGNUM) return builtin_type_int; @@ -4916,6 +5002,18 @@ hppa_register_virtual_type (int reg_nr) return builtin_type_float; } +/* Return the GDB type object for the "standard" data type of data + in register N. hppa64 version. */ + +struct type * +hppa64_register_virtual_type (int reg_nr) +{ + if (reg_nr < FP4_REGNUM) + return builtin_type_unsigned_long_long; + else + return builtin_type_double; +} + /* Store the address of the place in which to copy the structure the subroutine will return. This is called from call_function. */ @@ -4979,6 +5077,7 @@ hppa_fetch_pointer_argument (struct frame_info *frame, int argi, static struct gdbarch * hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { + struct gdbarch_tdep *tdep; struct gdbarch *gdbarch; /* Try to determine the ABI of the object we are loading. */ @@ -4995,9 +5094,70 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return (arches->gdbarch); /* If none found, then allocate and initialize one. */ - gdbarch = gdbarch_alloc (&info, NULL); + tdep = XMALLOC (struct gdbarch_tdep); + gdbarch = gdbarch_alloc (&info, tdep); + + /* Determine from the bfd_arch_info structure if we are dealing with + a 32 or 64 bits architecture. If the bfd_arch_info is not available, + then default to a 32bit machine. */ + if (info.bfd_arch_info != NULL) + tdep->bytes_per_address = + info.bfd_arch_info->bits_per_address / info.bfd_arch_info->bits_per_byte; + else + tdep->bytes_per_address = 4; + + /* Some parts of the gdbarch vector depend on whether we are running + on a 32 bits or 64 bits target. */ + switch (tdep->bytes_per_address) + { + case 4: + set_gdbarch_num_regs (gdbarch, hppa32_num_regs); + set_gdbarch_register_name (gdbarch, hppa32_register_name); + set_gdbarch_deprecated_register_virtual_type + (gdbarch, hppa32_register_virtual_type); + set_gdbarch_deprecated_call_dummy_length + (gdbarch, hppa32_call_dummy_length); + set_gdbarch_stack_align (gdbarch, hppa32_stack_align); + set_gdbarch_reg_struct_has_addr (gdbarch, hppa_reg_struct_has_addr); + set_gdbarch_deprecated_extract_return_value + (gdbarch, hppa32_extract_return_value); + set_gdbarch_use_struct_convention + (gdbarch, hppa32_use_struct_convention); + set_gdbarch_deprecated_store_return_value + (gdbarch, hppa32_store_return_value); + break; + case 8: + set_gdbarch_num_regs (gdbarch, hppa64_num_regs); + set_gdbarch_register_name (gdbarch, hppa64_register_name); + set_gdbarch_deprecated_register_virtual_type + (gdbarch, hppa64_register_virtual_type); + set_gdbarch_deprecated_call_dummy_breakpoint_offset + (gdbarch, hppa64_call_dummy_breakpoint_offset); + set_gdbarch_deprecated_call_dummy_length + (gdbarch, hppa64_call_dummy_length); + set_gdbarch_stack_align (gdbarch, hppa64_stack_align); + set_gdbarch_deprecated_extract_return_value + (gdbarch, hppa64_extract_return_value); + set_gdbarch_use_struct_convention + (gdbarch, hppa64_use_struct_convention); + set_gdbarch_deprecated_store_return_value + (gdbarch, hppa64_store_return_value); + break; + default: + internal_error (__FILE__, __LINE__, "Unsupported address size: %d", + tdep->bytes_per_address); + } + + /* The following gdbarch vector elements depend on other parts of this + vector which have been set above, depending on the ABI. */ + set_gdbarch_deprecated_register_bytes + (gdbarch, gdbarch_num_regs (gdbarch) * tdep->bytes_per_address); + set_gdbarch_long_bit (gdbarch, tdep->bytes_per_address * TARGET_CHAR_BIT); + set_gdbarch_long_long_bit (gdbarch, 64); + set_gdbarch_ptr_bit (gdbarch, tdep->bytes_per_address * TARGET_CHAR_BIT); - set_gdbarch_reg_struct_has_addr (gdbarch, hppa_reg_struct_has_addr); + /* The following gdbarch vector elements do not depend on the address + size, or in any other gdbarch element previously set. */ set_gdbarch_function_start_offset (gdbarch, 0); set_gdbarch_skip_prologue (gdbarch, hppa_skip_prologue); set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code); @@ -5006,28 +5166,19 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) hppa_in_solib_return_trampoline); set_gdbarch_deprecated_saved_pc_after_call (gdbarch, hppa_saved_pc_after_call); set_gdbarch_inner_than (gdbarch, hppa_inner_than); - set_gdbarch_stack_align (gdbarch, hppa_stack_align); set_gdbarch_decr_pc_after_break (gdbarch, 0); - set_gdbarch_deprecated_register_size (gdbarch, 4); - set_gdbarch_num_regs (gdbarch, hppa_num_regs); + set_gdbarch_deprecated_register_size (gdbarch, tdep->bytes_per_address); 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_npc_regnum (gdbarch, PCOQ_TAIL_REGNUM); set_gdbarch_deprecated_register_raw_size (gdbarch, hppa_register_raw_size); - set_gdbarch_deprecated_register_bytes (gdbarch, hppa_num_regs * 4); set_gdbarch_deprecated_register_byte (gdbarch, hppa_register_byte); set_gdbarch_deprecated_register_virtual_size (gdbarch, hppa_register_raw_size); - set_gdbarch_deprecated_max_register_raw_size (gdbarch, 4); + set_gdbarch_deprecated_max_register_raw_size (gdbarch, tdep->bytes_per_address); set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 8); - set_gdbarch_deprecated_register_virtual_type (gdbarch, hppa_register_virtual_type); - set_gdbarch_register_name (gdbarch, hppa_register_name); set_gdbarch_deprecated_store_struct_return (gdbarch, hppa_store_struct_return); - set_gdbarch_deprecated_extract_return_value (gdbarch, - hppa_extract_return_value); - set_gdbarch_use_struct_convention (gdbarch, hppa_use_struct_convention); - set_gdbarch_deprecated_store_return_value (gdbarch, hppa_store_return_value); set_gdbarch_deprecated_extract_struct_value_address (gdbarch, hppa_extract_struct_value_address); set_gdbarch_cannot_store_register (gdbarch, hppa_cannot_store_register); @@ -5040,7 +5191,6 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_frame_args_skip (gdbarch, 0); set_gdbarch_deprecated_push_dummy_frame (gdbarch, hppa_push_dummy_frame); set_gdbarch_deprecated_pop_frame (gdbarch, hppa_pop_frame); - set_gdbarch_deprecated_call_dummy_length (gdbarch, INSTRUCTION_SIZE * 28); /* set_gdbarch_deprecated_fix_call_dummy (gdbarch, hppa_fix_call_dummy); */ set_gdbarch_deprecated_push_arguments (gdbarch, hppa_push_arguments); set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address); |