This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 10/24] MIPS: override fscr/fir types and print control registers specially
- From: Bhushan Attarde <bhushan dot attarde at imgtec dot com>
- To: <gdb-patches at sourceware dot org>
- Cc: <Maciej dot Rozycki at imgtec dot com>, <Matthew dot Fortune at imgtec dot com>, <James dot Hogan at imgtec dot com>, <Andrew dot Bennett at imgtec dot com>, <Jaydeep dot Patil at imgtec dot com>, Bhushan Attarde <bhushan dot attarde at imgtec dot com>
- Date: Mon, 27 Jun 2016 20:19:37 +0530
- Subject: [PATCH 10/24] MIPS: override fscr/fir types and print control registers specially
- Authentication-results: sourceware.org; auth=none
- References: <1467038991-6600-1-git-send-email-bhushan dot attarde at imgtec dot com>
Define types for the MIPS floating point status and control register and
implementation register, allowing the fields to be decoded.
gdb/ChangeLog:
* mips-tdep.c (mips_frm_type, mips_fcflags_type, mips_fcsr_type,
mips_fir_type): New functions.
(mips_value_to_register): Return appropriat type for FP control
and implementation revision register.
(print_control_register): New function.
(mips_print_register): Use print_control_register to print
control registers.
(print_control_register_row): New function.
(mips_print_registers_info): Use print_control_register_row to
print a single complex control register row.
(mips_gdbarch_init): Initialize fp_rm_type, fp_cflags_type,
fp_csr_type and fp_ir_type types.
* mips-tdep.h (gdbarch_tdep): Add fp_rm_type, fp_cflags_type,
fp_csr_type and fp_ir_type fields.
---
gdb/mips-tdep.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
gdb/mips-tdep.h | 4 +
2 files changed, 261 insertions(+), 5 deletions(-)
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 0024edf..2cc49aa 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -1330,6 +1330,179 @@ mips_fp_type (struct gdbarch *gdbarch, int fpnum)
return mips_fp32_type (gdbarch);
}
+/* Get floating point rounding mode enumeration type */
+
+static struct type *
+mips_frm_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_rm_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t;
+ struct field *f;
+
+ t = arch_type (gdbarch, TYPE_CODE_ENUM, 1, "__gdb_builtin_type_fp_rm");
+ TYPE_UNSIGNED (t) = 1;
+ f = append_composite_type_field_raw (t, "NEAREST", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 0);
+ f = append_composite_type_field_raw (t, "ZERO", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 1);
+ f = append_composite_type_field_raw (t, "INF", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 2);
+ f = append_composite_type_field_raw (t, "NINF", bt->builtin_uint8);
+ SET_FIELD_ENUMVAL (*f, 3);
+
+ tdep->fp_rm_type = t;
+ }
+ return tdep->fp_rm_type;
+}
+
+/* Get floating point condition flags type */
+
+static struct type *
+mips_fcflags_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_cflags_type == NULL)
+ {
+ struct type *t;
+
+ /* Flags, Enables, Cause have common set of condition flags */
+ t = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_cflags", 1);
+ append_flags_type_flag (t, 0, "I");
+ append_flags_type_flag (t, 1, "U");
+ append_flags_type_flag (t, 2, "O");
+ append_flags_type_flag (t, 3, "Z");
+ append_flags_type_flag (t, 4, "V");
+ append_flags_type_flag (t, 5, "E"); /* Cause field only */
+
+ tdep->fp_cflags_type = t;
+ }
+ return tdep->fp_cflags_type;
+}
+
+static struct type *
+mips_fcsr_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_csr_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t, *cflags, *flags;
+ struct field *f;
+
+ /* Flags, Enables, Cause have common set of condition flags */
+ cflags = mips_fcflags_type (gdbarch);
+
+ /* Various bits at top end */
+ flags = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_csr_flags", 2);
+ append_flags_type_flag (flags, 0, "NAN2008");
+ append_flags_type_flag (flags, 1, "ABS2008");
+ append_flags_type_flag (flags, 2, "MAC2008");
+ append_flags_type_flag (flags, 3, "IMPL0");
+ append_flags_type_flag (flags, 4, "IMPL1");
+ append_flags_type_flag (flags, 5, "FCC0");
+ append_flags_type_flag (flags, 6, "FS");
+ append_flags_type_flag (flags, 7, "FCC1");
+ append_flags_type_flag (flags, 8, "FCC2");
+ append_flags_type_flag (flags, 9, "FCC3");
+ append_flags_type_flag (flags, 10, "FCC4");
+ append_flags_type_flag (flags, 11, "FCC5");
+ append_flags_type_flag (flags, 12, "FCC6");
+ append_flags_type_flag (flags, 13, "FCC7");
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_fp_csr",
+ TYPE_CODE_STRUCT);
+
+ /* rounding mode */
+ f = append_composite_type_field_raw (t, "rm", mips_frm_type (gdbarch));
+ SET_FIELD_BITPOS (*f, 0);
+ FIELD_BITSIZE (*f) = 2;
+
+ f = append_composite_type_field_raw (t, "flags", cflags);
+ SET_FIELD_BITPOS (*f, 2);
+ FIELD_BITSIZE (*f) = 5;
+
+ f = append_composite_type_field_raw (t, "enables", cflags);
+ SET_FIELD_BITPOS (*f, 7);
+ FIELD_BITSIZE (*f) = 5;
+
+ f = append_composite_type_field_raw (t, "cause", cflags);
+ SET_FIELD_BITPOS (*f, 12);
+ FIELD_BITSIZE (*f) = 6;
+
+ f = append_composite_type_field_raw (t, "", flags);
+ SET_FIELD_BITPOS (*f, 18);
+ FIELD_BITSIZE (*f) = 14;
+
+ TYPE_LENGTH (t) = 4;
+ TYPE_NAME (t) = "fp_csr";
+ tdep->fp_csr_type = t;
+ }
+
+ return tdep->fp_csr_type;
+}
+
+static struct type *
+mips_fir_type (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->fp_ir_type == NULL)
+ {
+ const struct builtin_type *bt = builtin_type (gdbarch);
+ struct type *t, *flags;
+ /* top half has flags */
+ flags = arch_flags_type (gdbarch, "__gdb_builtin_type_fp_ir_flags", 2);
+ append_flags_type_flag (flags, 0, "S");
+ append_flags_type_flag (flags, 1, "D");
+ append_flags_type_flag (flags, 2, "PS");
+ append_flags_type_flag (flags, 3, "3D");
+ append_flags_type_flag (flags, 4, "W");
+ append_flags_type_flag (flags, 5, "L");
+ append_flags_type_flag (flags, 6, "F64");
+ append_flags_type_flag (flags, 7, "HAS2008");
+ append_flags_type_flag (flags, 8, "IMPL0");
+ append_flags_type_flag (flags, 9, "IMPL1");
+ append_flags_type_flag (flags, 10, "IMPL2");
+ append_flags_type_flag (flags, 11, "IMPL3");
+ append_flags_type_flag (flags, 12, "UFRP");
+ append_flags_type_flag (flags, 13, "FREP");
+
+ t = arch_composite_type (gdbarch, "__gdb_builtin_type_fp_ir",
+ TYPE_CODE_STRUCT);
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+ {
+ /* bottom half has revision & processor id */
+ append_composite_type_field (t, "rev", bt->builtin_uint8);
+ append_composite_type_field (t, "prid", bt->builtin_uint8);
+
+ /* top half has flags */
+ append_composite_type_field (t, "", flags);
+ }
+ else
+ {
+ /* top half has flags */
+ append_composite_type_field (t, "", flags);
+
+ /* bottom half has revision & processor id */
+ append_composite_type_field (t, "prid", bt->builtin_uint8);
+ append_composite_type_field (t, "rev", bt->builtin_uint8);
+ }
+
+ TYPE_LENGTH (t) = 4;
+ TYPE_NAME (t) = "fp_ir";
+ tdep->fp_ir_type = t;
+ }
+
+ return tdep->fp_ir_type;
+}
+
static void
mips_value_to_register (struct frame_info *frame, int regnum,
struct type *type, const gdb_byte *from)
@@ -1415,9 +1588,10 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
Use the current setting for cooked registers. */
if (mips_float_register_p (gdbarch, regnum))
return mips_fp_type (gdbarch, rawnum - mips_regnum (gdbarch)->fp0);
- else if (rawnum == mips_regnum (gdbarch)->fp_control_status
- || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
- return builtin_type (gdbarch)->builtin_int32;
+ else if (rawnum == mips_regnum (gdbarch)->fp_control_status)
+ return mips_fcsr_type (gdbarch);
+ else if (rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+ return mips_fir_type (gdbarch);
else if (rawnum == mips_regnum (gdbarch)->config5)
return mips_config5_type (gdbarch);
else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
@@ -1492,6 +1666,12 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
&& rawnum < mips_regnum (gdbarch)->dspacc + 6)))
return builtin_type (gdbarch)->builtin_int32;
+ if (rawnum == mips_regnum (gdbarch)->fp_control_status)
+ return mips_fcsr_type (gdbarch);
+
+ if (rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+ return mips_fir_type (gdbarch);
+
if (rawnum == mips_regnum (gdbarch)->config5)
return mips_config5_type (gdbarch);
@@ -6741,9 +6921,52 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
}
}
+/* Print a single complex control register */
+
static void
-mips_print_register (struct ui_file *file, struct frame_info *frame,
- int regnum)
+print_control_register (struct ui_file *file, struct frame_info *frame,
+ int regnum)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ const char *name = gdbarch_register_name (gdbarch, regnum);
+ struct value *val = value_of_register (regnum, frame);
+ struct type *regtype = value_type (val);
+ enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype));
+ struct value_print_options opts;
+ const gdb_byte *valaddr;
+
+ fputs_filtered (name, file);
+ print_spaces_filtered (15 - strlen (name), file);
+
+ if (!value_entirely_available (val))
+ {
+ fprintf_filtered (file, "*value not available*\n");
+ return;
+ }
+ else if (value_optimized_out (val))
+ {
+ val_print_optimized_out (val, file);
+ fprintf_filtered (file, "\n");
+ return;
+ }
+
+ valaddr = value_contents_for_printing (val);
+
+ /* Print raw value */
+ fprintf_filtered (file, "\t");
+ print_hex_chars (file, valaddr, TYPE_LENGTH (regtype), byte_order);
+
+ /* Print it according to its natural format. */
+ get_user_print_options (&opts);
+ opts.deref_ref = 1;
+ fprintf_filtered (file, "\t");
+ val_print (regtype, valaddr,
+ value_embedded_offset (val), 0,
+ file, 0, val, &opts, current_language);
+}
+
+static void
+mips_print_register (struct ui_file *file, struct frame_info *frame, int regnum)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct value_print_options opts;
@@ -6755,6 +6978,14 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
return;
}
+ if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+ mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+ {
+ /* FP & MSA control registers */
+ print_control_register (file, frame, regnum);
+ return;
+ }
+
val = get_frame_register_value (frame, regnum);
fputs_filtered (gdbarch_register_name (gdbarch, regnum), file);
@@ -6972,6 +7203,19 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
return regnum;
}
+/* Print a single complex control register row */
+
+static int
+print_control_register_row (struct ui_file *file, struct frame_info *frame,
+ int regnum)
+{
+ print_control_register (file, frame, regnum);
+
+ fprintf_filtered (file, "\n");
+ ++regnum;
+ return regnum;
+}
+
/* MIPS_DO_REGISTERS_INFO(): called by "info register" command. */
static void
@@ -7001,6 +7245,10 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
else
regnum += MIPS_NUMREGS; /* Skip floating point regs. */
}
+ else if (mips_register_reggroup_p (gdbarch, regnum, float_reggroup) ||
+ mips_register_reggroup_p (gdbarch, regnum, vector_reggroup))
+ /* FP & MSA control registers */
+ regnum = print_control_register_row (file, frame, regnum);
else
regnum = print_gp_register_row (file, frame, regnum);
}
@@ -9033,6 +9281,10 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->fp_mode = ((struct gdbarch_tdep_info*)(info.tdep_info))->fp_mode;
tdep->fp_register_mode_fixed_p = 0;
tdep->config5_type = NULL;
+ tdep->fp_rm_type = NULL;
+ tdep->fp_cflags_type = NULL;
+ tdep->fp_csr_type = NULL;
+ tdep->fp_ir_type = NULL;
tdep->fp32_type = NULL;
tdep->fp64_type = NULL;
diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h
index 11353be..ad5cba3 100644
--- a/gdb/mips-tdep.h
+++ b/gdb/mips-tdep.h
@@ -130,6 +130,10 @@ struct gdbarch_tdep
/* ISA-specific data types. */
struct type *config5_type;
+ struct type *fp_rm_type;
+ struct type *fp_cflags_type;
+ struct type *fp_csr_type;
+ struct type *fp_ir_type;
struct type *fp32_type;
struct type *fp64_type;
--
1.9-rc2