diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/mips-tdep.c | 193 |
2 files changed, 157 insertions, 45 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3a4d722..e316d86 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2002-08-20 Andrew Cagney <ac131313@redhat.com> + * mips-tdep.c (mips_gdbarch_init): Update. + (mips_o32_extract_return_value): Rewrite. + (mips_o32_store_return_value): Rewrite. + (mips_o32_xfer_return_value): New function. + (mips_xfer_register): Tweak debug print message. Allow for + buf_offset when dumping the value transfered. + +2002-08-20 Andrew Cagney <ac131313@redhat.com> + * config/mips/tm-nbsd.h (MIPS_DEFAULT_ABI): Delete. * config/mips/tm-linux.h (MIPS_DEFAULT_ABI): Delete. * config/mips/tm-irix5.h (MIPS_DEFAULT_ABI): Delete. diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 8c18294..5bc44ba 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -185,6 +185,8 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length, { bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE); int reg_offset = 0; + /* Need to transfer the left or right part of the register, based on + the targets byte order. */ switch (endian) { case BFD_ENDIAN_BIG: @@ -200,14 +202,15 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length, internal_error (__FILE__, __LINE__, "bad switch"); } if (mips_debug) - fprintf_unfiltered (gdb_stderr, "xfer $%d[%d..%d] ", - reg_num, reg_offset, reg_offset + length); + fprintf_unfiltered (gdb_stderr, + "xfer $%d, reg offset %d, buf offset %d, length %d, ", + reg_num, reg_offset, buf_offset, length); if (mips_debug && out != NULL) { int i; - fprintf_unfiltered (gdb_stdlog, "out: "); + fprintf_unfiltered (gdb_stdlog, "out "); for (i = 0; i < length; i++) - fprintf_unfiltered (gdb_stdlog, "%02x", out[i]); + fprintf_unfiltered (gdb_stdlog, "%02x", out[buf_offset + i]); } if (in != NULL) regcache_raw_read_part (regcache, reg_num, reg_offset, length, in + buf_offset); @@ -216,9 +219,9 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length, if (mips_debug && in != NULL) { int i; - fprintf_unfiltered (gdb_stdlog, "in: "); + fprintf_unfiltered (gdb_stdlog, "in "); for (i = 0; i < length; i++) - fprintf_unfiltered (gdb_stdlog, "%02x", in[i]); + fprintf_unfiltered (gdb_stdlog, "%02x", in[buf_offset + i]); } if (mips_debug) fprintf_unfiltered (gdb_stdlog, "\n"); @@ -4542,25 +4545,6 @@ mips_eabi_extract_return_value (struct type *valtype, } static void -mips_o32_extract_return_value (struct type *valtype, - char regbuf[REGISTER_BYTES], - char *valbuf) -{ - struct return_value_word lo; - struct return_value_word hi; - return_value_location (valtype, &hi, &lo); - - memcpy (valbuf + lo.buf_offset, - regbuf + REGISTER_BYTE (lo.reg) + lo.reg_offset, - lo.len); - - if (hi.len > 0) - memcpy (valbuf + hi.buf_offset, - regbuf + REGISTER_BYTE (hi.reg) + hi.reg_offset, - hi.len); -} - -static void mips_o64_extract_return_value (struct type *valtype, char regbuf[REGISTER_BYTES], char *valbuf) @@ -4607,7 +4591,7 @@ mips_eabi_store_return_value (struct type *valtype, char *valbuf) } static void -mips_o32_store_return_value (struct type *valtype, char *valbuf) +mips_o64_store_return_value (struct type *valtype, char *valbuf) { char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); struct return_value_word lo; @@ -4630,31 +4614,150 @@ mips_o32_store_return_value (struct type *valtype, char *valbuf) } } +/* O32 ABI stuff. */ + static void -mips_o64_store_return_value (struct type *valtype, char *valbuf) +mips_o32_xfer_return_value (struct type *type, + struct regcache *regcache, + bfd_byte *in, const bfd_byte *out) { - char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE); - struct return_value_word lo; - struct return_value_word hi; - return_value_location (valtype, &hi, &lo); - - memset (raw_buffer, 0, sizeof (raw_buffer)); - memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len); - write_register_bytes (REGISTER_BYTE (lo.reg), - raw_buffer, - REGISTER_RAW_SIZE (lo.reg)); - - if (hi.len > 0) + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + if (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) == 4 + && tdep->mips_fpu_type != MIPS_FPU_NONE) { - memset (raw_buffer, 0, sizeof (raw_buffer)); - memcpy (raw_buffer + hi.reg_offset, valbuf + hi.buf_offset, hi.len); - write_register_bytes (REGISTER_BYTE (hi.reg), - raw_buffer, - REGISTER_RAW_SIZE (hi.reg)); + /* A single-precision floating-point value. It fits in the + least significant part of FP0. */ + if (mips_debug) + fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n"); + mips_xfer_register (regcache, FP0_REGNUM, TYPE_LENGTH (type), + TARGET_BYTE_ORDER, in, out, 0); + } + else if (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) == 8 + && tdep->mips_fpu_type != MIPS_FPU_NONE) + { + /* A double-precision floating-point value. It fits in the + least significant part of FP0/FP1 but with byte ordering + based on the target (???). */ + if (mips_debug) + fprintf_unfiltered (gdb_stderr, "Return float in $fp0/$fp1\n"); + switch (TARGET_BYTE_ORDER) + { + case BFD_ENDIAN_LITTLE: + mips_xfer_register (regcache, FP0_REGNUM + 0, 4, + TARGET_BYTE_ORDER, in, out, 0); + mips_xfer_register (regcache, FP0_REGNUM + 1, 4, + TARGET_BYTE_ORDER, in, out, 4); + break; + case BFD_ENDIAN_BIG: + mips_xfer_register (regcache, FP0_REGNUM + 1, 4, + TARGET_BYTE_ORDER, in, out, 0); + mips_xfer_register (regcache, FP0_REGNUM + 0, 4, + TARGET_BYTE_ORDER, in, out, 4); + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); + } + } +#if 0 + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT + && TYPE_NFIELDS (type) <= 2 + && TYPE_NFIELDS (type) >= 1 + && ((TYPE_NFIELDS (type) == 1 + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + == TYPE_CODE_FLT)) + || (TYPE_NFIELDS (type) == 2 + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + == TYPE_CODE_FLT) + && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1)) + == TYPE_CODE_FLT))) + && tdep->mips_fpu_type != MIPS_FPU_NONE) + { + /* A struct that contains one or two floats. Each value is part + in the least significant part of their floating point + register.. */ + bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE); + int regnum; + int field; + for (field = 0, regnum = FP0_REGNUM; + field < TYPE_NFIELDS (type); + field++, regnum += 2) + { + int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field]) + / TARGET_CHAR_BIT); + if (mips_debug) + fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n", offset); + mips_xfer_register (regcache, regnum, TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)), + TARGET_BYTE_ORDER, in, out, offset); + } + } +#endif +#if 0 + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION) + { + /* A structure or union. Extract the left justified value, + regardless of the byte order. I.e. DO NOT USE + mips_xfer_lower. */ + int offset; + int regnum; + for (offset = 0, regnum = V0_REGNUM; + offset < TYPE_LENGTH (type); + offset += REGISTER_RAW_SIZE (regnum), regnum++) + { + int xfer = REGISTER_RAW_SIZE (regnum); + if (offset + xfer > TYPE_LENGTH (type)) + xfer = TYPE_LENGTH (type) - offset; + if (mips_debug) + fprintf_unfiltered (gdb_stderr, "Return struct+%d:%d in $%d\n", + offset, xfer, regnum); + mips_xfer_register (regcache, regnum, xfer, BFD_ENDIAN_UNKNOWN, + in, out, offset); + } + } +#endif + else + { + /* A scalar extract each part but least-significant-byte + justified. o32 thinks registers are 4 byte, regardless of + the ISA. mips_stack_argsize controls this. */ + int offset; + int regnum; + for (offset = 0, regnum = V0_REGNUM; + offset < TYPE_LENGTH (type); + offset += mips_stack_argsize (), regnum++) + { + int xfer = mips_stack_argsize (); + int pos = 0; + if (offset + xfer > TYPE_LENGTH (type)) + xfer = TYPE_LENGTH (type) - offset; + if (mips_debug) + fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n", + offset, xfer, regnum); + mips_xfer_register (regcache, regnum, xfer, TARGET_BYTE_ORDER, + in, out, offset); + } } } static void +mips_o32_extract_return_value (struct type *type, + struct regcache *regcache, + char *valbuf) +{ + mips_o32_xfer_return_value (type, regcache, valbuf, NULL); +} + +static void +mips_o32_store_return_value (struct type *type, char *valbuf) +{ + mips_o32_xfer_return_value (type, current_regcache, NULL, valbuf); +} + +/* N32/N44 ABI stuff. */ + +static void mips_n32n64_xfer_return_value (struct type *type, struct regcache *regcache, bfd_byte *in, const bfd_byte *out) @@ -5570,7 +5673,7 @@ mips_gdbarch_init (struct gdbarch_info info, case MIPS_ABI_O32: set_gdbarch_push_arguments (gdbarch, mips_o32_push_arguments); set_gdbarch_store_return_value (gdbarch, mips_o32_store_return_value); - set_gdbarch_deprecated_extract_return_value (gdbarch, mips_o32_extract_return_value); + set_gdbarch_extract_return_value (gdbarch, mips_o32_extract_return_value); tdep->mips_default_saved_regsize = 4; tdep->mips_default_stack_argsize = 4; tdep->mips_fp_register_double = 0; |