Re: [RFA] New bitflags type and eflags on i386/x86-64

Michal Ludvig
2002-08-29T13:35:29Z

[-- Attachment #1: Type: text/plain, Size: 477 bytes --]

Andrew Cagney wrote:
> However, given that there are two implementations, I get the feeling
> that [possibly fee paying] users want something.

Here is the reworked patch. The print function was moved to valprint.c
and is called from all relevant <language>-valprint.c modules.
Also I've added support for MXCSR register both for i386 and x86-64.

Comments? Can I commit it?

Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* +420 2 9654 5373 * http://www.suse.cz

[-- Attachment #2: flags-3.diff --]
[-- Type: text/plain, Size: 16343 bytes --]

2002-08-29 Michal Ludvig <mludvig@suse.cz>

* gdbtypes.c (builtin_type_i386_eflags): Added.
(builtin_type_simd_mxcsr): Added.
(add_flag_ignore, add_flag_name, init_flags_type): Added.
(is_integral_type, rank_one_type, recursive_dump_type): Added
TYPE_CODE_FLAGS handling.
(build_gdbtypes): Added builtin_type_i386_eflags and
builtin_type_simd_mxcsr initialization.
* gdbtypes.h (type_code): Added TYPE_CODE_FLAGS.
(builtin_type_i386_eflags): Added.
(builtin_type_simd_mxcsr): Added.
* valprint.c (val_print_type_code_flags): Added.
* valprint.h (val_print_type_code_flags): Added.
* values.c (unpack_long): Added TYPE_CODE_FLAGS handling.
* i386-tdep.c (i386_register_virtual_type): Added eflags and
mxcsr registers handling.
* x86-64-tdep.c (x86_64_register_info_table): Changed type
of eflags and mxcsr registers.
* ada-valprint.c (ada_val_print_1): Added TYPE_CODE_FLAGS case.
* c-valprint.c (c_val_print): Ditto.
* f-valprint.c (f_val_print): Ditto.
* jv-valprint.c (java_val_print): Ditto.
* p-valprint.c (pascal_val_print): Ditto.

Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.56
diff -u -p -r1.56 gdbtypes.c
--- gdbtypes.c 20 Aug 2002 19:57:32 -0000 1.56
+++ gdbtypes.c 29 Aug 2002 13:08:13 -0000
@@ -116,6 +116,8 @@ struct type *builtin_type_void_data_ptr;
struct type *builtin_type_void_func_ptr;
struct type *builtin_type_CORE_ADDR;
struct type *builtin_type_bfd_vma;
+struct type *builtin_type_i386_eflags;
+struct type *builtin_type_simd_mxcsr;

int opaque_type_resolution = 1;
int overload_debug = 0;
@@ -782,6 +784,61 @@ create_set_type (struct type *result_typ
return (result_type);
}

+/*
+ * - The following three functions are intended to be used for BitFlags
+ * types (ie i386's EFLAGS register).
+ * - As a BitFlag we understand an integer where some bits may have
+ * a symbolic names that would be printed when the bit is set.
+ * - Printing is done in c_val_print() under a TYPE_CODE_FLAGS label.
+ * - Add a symbolic name of relevant bits using add_flag_name() after
+ * an initialisation of your type.
+ */
+void
+add_flag_ignore (struct type *type, int bitpos)
+{
+ TYPE_FIELD_BITPOS (type, bitpos) = -1;
+}
+
+void
+add_flag_name (struct type *type, int bitpos, char *name)
+{
+ int namelen;
+
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLAGS);
+ gdb_assert (bitpos < TYPE_NFIELDS (type));
+ gdb_assert (bitpos >= 0);
+
+ namelen=strlen(name)+1;
+ TYPE_FIELD_NAME (type, bitpos) = xmalloc (namelen);
+ snprintf(TYPE_FIELD_NAME (type, bitpos), namelen, "%s", name);
+
+ TYPE_FIELD_BITPOS (type, bitpos) = bitpos;
+}
+
+struct type *
+init_flags_type (int bitlength, char *name, struct objfile *objfile)
+{
+ register struct type *type;
+
+ type = alloc_type (objfile);
+
+ TYPE_CODE (type) = TYPE_CODE_FLAGS;
+ TYPE_LENGTH (type) = bitlength / 8 + ( bitlength % 8 ? 1 : 0 );
+ TYPE_FLAGS (type) = TYPE_FLAG_UNSIGNED;
+ TYPE_NFIELDS (type) = bitlength;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, bitlength * sizeof (struct field));
+ memset (TYPE_FIELDS (type), 0, sizeof (struct field));
+
+ if ((name != NULL) && (objfile != NULL))
+ TYPE_NAME (type) =
+ obsavestring (name, strlen (name), &objfile->type_obstack);
+ else
+ TYPE_NAME (type) = name;
+
+ return (type);
+}
+
/* Construct and return a type of the form:
struct NAME { ELT_TYPE ELT_NAME[N]; }
We use these types for SIMD registers. For example, the type of
@@ -1946,6 +2003,7 @@ is_integral_type (struct type *t)
return
((t != NULL)
&& ((TYPE_CODE (t) == TYPE_CODE_INT)
+ || (TYPE_CODE (t) == TYPE_CODE_FLAGS)
|| (TYPE_CODE (t) == TYPE_CODE_ENUM)
|| (TYPE_CODE (t) == TYPE_CODE_CHAR)
|| (TYPE_CODE (t) == TYPE_CODE_RANGE)
@@ -2479,6 +2537,7 @@ rank_one_type (struct type *parm, struct
case TYPE_CODE_FUNC:
return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
case TYPE_CODE_INT:
+ case TYPE_CODE_FLAGS:
case TYPE_CODE_ENUM:
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
@@ -2555,6 +2614,8 @@ rank_one_type (struct type *parm, struct
return INTEGER_PROMOTION_BADNESS;
else
return INTEGER_COERCION_BADNESS;
+ case TYPE_CODE_FLAGS:
+ return 0;
case TYPE_CODE_ENUM:
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
@@ -3000,6 +3061,9 @@ recursive_dump_type (struct type *type,
case TYPE_CODE_INT:
printf_filtered ("(TYPE_CODE_INT)");
break;
+ case TYPE_CODE_FLAGS:
+ printf_filtered ("(TYPE_CODE_FLAGS)");
+ break;
case TYPE_CODE_FLT:
printf_filtered ("(TYPE_CODE_FLT)");
break;
@@ -3433,6 +3497,49 @@ build_gdbtypes (void)
init_type (TYPE_CODE_INT, TARGET_BFD_VMA_BIT / 8,
TYPE_FLAG_UNSIGNED,
"__bfd_vma", (struct objfile *) NULL);
+
+ builtin_type_i386_eflags =
+ init_flags_type (32 /* EFLAGS_LENGTH */,
+ "__i386_eflags", (struct objfile *) NULL);
+ add_flag_name (builtin_type_i386_eflags, 0, "CF");
+ add_flag_ignore (builtin_type_i386_eflags, 1);
+ add_flag_name (builtin_type_i386_eflags, 2, "PF");
+ add_flag_name (builtin_type_i386_eflags, 4, "AF");
+ add_flag_name (builtin_type_i386_eflags, 6, "ZF");
+ add_flag_name (builtin_type_i386_eflags, 7, "SF");
+ add_flag_name (builtin_type_i386_eflags, 8, "TF");
+ add_flag_name (builtin_type_i386_eflags, 9, "IF");
+ add_flag_name (builtin_type_i386_eflags, 10, "DF");
+ add_flag_name (builtin_type_i386_eflags, 11, "OF");
+ add_flag_ignore (builtin_type_i386_eflags, 12);
+ add_flag_ignore (builtin_type_i386_eflags, 13);
+ add_flag_name (builtin_type_i386_eflags, 14, "NT");
+ add_flag_name (builtin_type_i386_eflags, 16, "RF");
+ add_flag_name (builtin_type_i386_eflags, 17, "VM");
+ add_flag_name (builtin_type_i386_eflags, 18, "AC");
+ add_flag_name (builtin_type_i386_eflags, 19, "VIF");
+ add_flag_name (builtin_type_i386_eflags, 20, "VIP");
+ add_flag_name (builtin_type_i386_eflags, 21, "ID");
+
+ builtin_type_simd_mxcsr =
+ init_flags_type (32 /* EFLAGS_LENGTH */,
+ "__simd_mxcsr", (struct objfile *) NULL);
+ add_flag_name (builtin_type_simd_mxcsr, 0, "IE");
+ add_flag_name (builtin_type_simd_mxcsr, 1, "DE");
+ add_flag_name (builtin_type_simd_mxcsr, 2, "ZE");
+ add_flag_name (builtin_type_simd_mxcsr, 3, "OE");
+ add_flag_name (builtin_type_simd_mxcsr, 4, "UE");
+ add_flag_name (builtin_type_simd_mxcsr, 5, "PE");
+ add_flag_name (builtin_type_simd_mxcsr, 6, "DAZ");
+ add_flag_name (builtin_type_simd_mxcsr, 7, "IM");
+ add_flag_name (builtin_type_simd_mxcsr, 8, "DM");
+ add_flag_name (builtin_type_simd_mxcsr, 9, "ZM");
+ add_flag_name (builtin_type_simd_mxcsr, 10, "OM");
+ add_flag_name (builtin_type_simd_mxcsr, 11, "UM");
+ add_flag_name (builtin_type_simd_mxcsr, 12, "PM");
+ add_flag_name (builtin_type_simd_mxcsr, 13, "RC1");
+ add_flag_name (builtin_type_simd_mxcsr, 14, "RC2");
+ add_flag_name (builtin_type_simd_mxcsr, 15, "FZ");
}

Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.35
diff -u -p -r1.35 gdbtypes.h
--- gdbtypes.h 10 Aug 2002 05:12:40 -0000 1.35
+++ gdbtypes.h 29 Aug 2002 13:08:13 -0000
@@ -85,6 +85,7 @@ enum type_code
TYPE_CODE_ENUM, /* Enumeration type */
TYPE_CODE_FUNC, /* Function type */
TYPE_CODE_INT, /* Integer type */
+ TYPE_CODE_FLAGS, /* BitFlags type */

/* Floating type. This is *NOT* a complex type. Beware, there are parts
of GDB which bogusly assume that TYPE_CODE_FLT can mean complex. */
@@ -926,6 +927,10 @@ extern struct type *builtin_type_void_fu

/* The target CPU's address type. This is the ISA address size. */
extern struct type *builtin_type_CORE_ADDR;
+
+/* Type for i386 EFLAGS register. */
+extern struct type *builtin_type_i386_eflags;
+
/* The symbol table address type. Some object file formats have a 32
bit address type even though the TARGET has a 64 bit pointer type
(cf MIPS). */
@@ -951,6 +956,9 @@ extern struct type *builtin_type_v8qi;
extern struct type *builtin_type_v8hi;
extern struct type *builtin_type_v4hi;
extern struct type *builtin_type_v2si;
+
+/* MXCSR SIMD control register. */
+extern struct type *builtin_type_simd_mxcsr;

/* Type for 64 bit vectors. */
extern struct type *builtin_type_vec64;
Index: valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/valprint.c,v
retrieving revision 1.28
diff -u -p -r1.28 valprint.c
--- valprint.c 24 Aug 2002 00:40:59 -0000 1.28
+++ valprint.c 29 Aug 2002 13:08:14 -0000
@@ -1183,6 +1183,39 @@ val_print_string (CORE_ADDR addr, int le
}
\f

+void
+val_print_type_code_flags (char *valaddr, struct type *type,
+ int format, int size,
+ struct ui_file *stream)
+{
+ unsigned int len;
+ int i;
+ LONGEST val;
+
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ {
+ len = TYPE_NFIELDS (type);
+ val = unpack_long (type, valaddr);
+ fputs_filtered("[", stream);
+ for (i = len-1; i >= 0; i--)
+ {
+ QUIT;
+ if (TYPE_FIELD_BITPOS (type, i) != -1 && val & (1 << i))
+ if (val & (1 << i))
+ {
+ if(TYPE_FIELD_NAME (type, i))
+ fprintf_filtered (stream, " %s", TYPE_FIELD_NAME (type, i));
+ else
+ fprintf_filtered (stream, " #%d", i);
+
+ }
+ }
+ fputs_filtered(" ]", stream);
+ }
+}
+
/* Validate an input or output radix setting, and make sure the user
knows what they really did here. Radix setting is confusing, e.g.
setting the input radix to "10" never changes it! */
Index: valprint.h
===================================================================
RCS file: /cvs/src/src/gdb/valprint.h,v
retrieving revision 1.3
diff -u -p -r1.3 valprint.h
--- valprint.h 21 Oct 2001 19:20:30 -0000 1.3
+++ valprint.h 29 Aug 2002 13:08:14 -0000
@@ -49,6 +49,10 @@ extern void val_print_array_elements (st
extern void val_print_type_code_int (struct type *, char *,
struct ui_file *);

+extern void val_print_type_code_flags (char *valaddr, struct type *type,
+ int format, int size,
+ struct ui_file *stream);
+
extern void print_binary_chars (struct ui_file *, unsigned char *,
unsigned int);

Index: values.c
===================================================================
RCS file: /cvs/src/src/gdb/values.c,v
retrieving revision 1.40
diff -u -p -r1.40 values.c
--- values.c 24 Aug 2002 00:21:35 -0000 1.40
+++ values.c 29 Aug 2002 13:08:14 -0000
@@ -696,6 +696,7 @@ unpack_long (struct type *type, char *va
case TYPE_CODE_ENUM:
case TYPE_CODE_BOOL:
case TYPE_CODE_INT:
+ case TYPE_CODE_FLAGS:
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
if (nosign)
Index: i386-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-tdep.c,v
retrieving revision 1.85
diff -u -p -r1.85 i386-tdep.c
--- i386-tdep.c 26 Aug 2002 18:35:25 -0000 1.85
+++ i386-tdep.c 29 Aug 2002 13:08:13 -0000
@@ -1102,6 +1102,12 @@ i386_register_virtual_type (int regnum)
if (regnum == PC_REGNUM || regnum == FP_REGNUM || regnum == SP_REGNUM)
return lookup_pointer_type (builtin_type_void);

+ if (regnum == PS_REGNUM)
+ return builtin_type_i386_eflags;
+
+ if (regnum == MXCSR_REGNUM)
+ return builtin_type_simd_mxcsr;
+
if (IS_FP_REGNUM (regnum))
return builtin_type_i387_ext;

Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.26
diff -u -p -r1.26 x86-64-tdep.c
--- x86-64-tdep.c 24 Aug 2002 00:21:35 -0000 1.26
+++ x86-64-tdep.c 29 Aug 2002 13:08:14 -0000
@@ -68,7 +68,7 @@ static struct register_info x86_64_regis
/* 14 */ {8, "r14", &builtin_type_int64},
/* 15 */ {8, "r15", &builtin_type_int64},
/* 16 */ {8, "rip", &builtin_type_void_func_ptr},
- /* 17 */ {4, "eflags", &builtin_type_int32},
+ /* 17 */ {4, "eflags", &builtin_type_i386_eflags},
/* 18 */ {4, "ds", &builtin_type_int32},
/* 19 */ {4, "es", &builtin_type_int32},
/* 20 */ {4, "fs", &builtin_type_int32},
@@ -105,7 +105,7 @@ static struct register_info x86_64_regis
/* 51 */ {16, "xmm13", &builtin_type_v4sf},
/* 52 */ {16, "xmm14", &builtin_type_v4sf},
/* 53 */ {16, "xmm15", &builtin_type_v4sf},
- /* 54 */ {4, "mxcsr", &builtin_type_int32}
+ /* 54 */ {4, "mxcsr", &builtin_type_simd_mxcsr}
};

/* This array is a mapping from Dwarf-2 register
Index: ada-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/ada-valprint.c,v
retrieving revision 1.4
diff -u -p -r1.4 ada-valprint.c
--- ada-valprint.c 18 Aug 2002 18:07:33 -0000 1.4
+++ ada-valprint.c 29 Aug 2002 13:08:12 -0000
@@ -777,6 +777,11 @@ ada_val_print_1 (struct type *type, char
fputs_filtered ("???", stream);
}
break;
+
+ case TYPE_CODE_FLAGS:
+ val_print_type_code_flags (valaddr + embedded_offset, type,
+ format, 0, stream);
+ break;
}
return 0;
}
Index: c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.14
diff -u -p -r1.14 c-valprint.c
--- c-valprint.c 27 Aug 2002 22:37:06 -0000 1.14
+++ c-valprint.c 29 Aug 2002 13:08:12 -0000
@@ -486,6 +486,11 @@ c_val_print (struct type *type, char *va
fprintf_filtered (stream, " * I");
break;

+ case TYPE_CODE_FLAGS:
+ val_print_type_code_flags (valaddr + embedded_offset, type,
+ format, 0, stream);
+ break;
+
default:
error ("Invalid C/C++ type code %d in symbol table.", TYPE_CODE (type));
}
Index: f-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/f-valprint.c,v
retrieving revision 1.6
diff -u -p -r1.6 f-valprint.c
--- f-valprint.c 7 Mar 2001 02:57:08 -0000 1.6
+++ f-valprint.c 29 Aug 2002 13:08:13 -0000
@@ -544,6 +544,11 @@ f_val_print (struct type *type, char *va
fprintf_filtered (stream, "<incomplete type>");
break;

+ case TYPE_CODE_FLAGS:
+ val_print_type_code_flags (valaddr + embedded_offset, type,
+ format, 0, stream);
+ break;
+
default:
error ("Invalid F77 type code %d in symbol table.", TYPE_CODE (type));
}
Index: jv-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/jv-valprint.c,v
retrieving revision 1.11
diff -u -p -r1.11 jv-valprint.c
--- jv-valprint.c 27 Aug 2002 22:37:06 -0000 1.11
+++ jv-valprint.c 29 Aug 2002 13:08:13 -0000
@@ -518,6 +518,11 @@ java_val_print (struct type *type, char
recurse, pretty);
break;

+ case TYPE_CODE_FLAGS:
+ val_print_type_code_flags (valaddr + embedded_offset, type,
+ format, 0, stream);
+ break;
+
default:
return c_val_print (type, valaddr, embedded_offset, address, stream,
format, deref_ref, recurse, pretty);
Index: p-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/p-valprint.c,v
retrieving revision 1.13
diff -u -p -r1.13 p-valprint.c
--- p-valprint.c 19 Aug 2002 13:12:09 -0000 1.13
+++ p-valprint.c 29 Aug 2002 13:08:13 -0000
@@ -524,6 +524,11 @@ pascal_val_print (struct type *type, cha
fprintf_filtered (stream, "<incomplete type>");
break;

+ case TYPE_CODE_FLAGS:
+ val_print_type_code_flags (valaddr + embedded_offset, type,
+ format, 0, stream);
+ break;
+
default:
error ("Invalid pascal type code %d in symbol table.", TYPE_CODE (type));
}