From patchwork Mon Jun 27 14:49:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhushan Attarde X-Patchwork-Id: 13390 Received: (qmail 10692 invoked by alias); 27 Jun 2016 14:50:40 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 10589 invoked by uid 89); 27 Jun 2016 14:50:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=4.9 required=5.0 tests=AWL, BAYES_00, GARBLED_SUBJECT, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS, UNWANTED_LANGUAGE_BODY autolearn=no version=3.3.2 spammy=msa, Various, row, ZERO X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.59.15.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 27 Jun 2016 14:50:36 +0000 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 08E49D49EC92B for ; Mon, 27 Jun 2016 15:50:29 +0100 (IST) Received: from pudesk170.pu.imgtec.org (192.168.93.65) by hhmail02.hh.imgtec.org (10.100.10.20) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 27 Jun 2016 15:50:32 +0100 From: Bhushan Attarde To: CC: , , , , , Bhushan Attarde Subject: [PATCH 10/24] MIPS: override fscr/fir types and print control registers specially Date: Mon, 27 Jun 2016 20:19:37 +0530 Message-ID: <1467038991-6600-10-git-send-email-bhushan.attarde@imgtec.com> In-Reply-To: <1467038991-6600-1-git-send-email-bhushan.attarde@imgtec.com> References: <1467038991-6600-1-git-send-email-bhushan.attarde@imgtec.com> MIME-Version: 1.0 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;