Message ID | 20250409041444.106988-1-thiago.bauermann@linaro.org |
---|---|
State | New |
Headers | show |
Series | gdb: arm: Add CPSR fields to arm-core target description | expand |
Hi, On 4/9/25 05:14, Thiago Jung Bauermann wrote: > PR tdep/32840 mentions that the "info registers" output for CPSR (Current > Program Status Register) on 32-bit Arm isn't very helpful. > > Add a flags type with a couple of enums to provide better information on > the bits that are set. Example output: Thanks. That seems like a good improvement. We do have a situation with cpsr when we consider 32-bit [1] Arm and AArch32 [2] mode though. Most of the cpsr bits are common, but we seem to have differences. Maybe we should expose only the bits that are common between those two? There are also differences between particular architecture levels [3]. It might make sense to ignore really old architecture levels and go for the current bits though. [1] https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/Program-Status-Registers--PSRs-?lang=en#CIHJBHJA [2] https://developer.arm.com/documentation/ddi0601/2025-03/AArch32-Registers/CPSR--Current-Program-Status-Register [3] https://github.com/torvalds/linux/blob/a24588245776dafc227243a01bfbeb8a59bafba9/arch/arm/include/uapi/asm/ptrace.h#L78 > > (gdb) info reg cpsr > cpsr 0x40070030 [ M=user E=little GE=7 Z ] > > Regression tested on native armv8l-linux-gnueabihf. > > Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32840 > --- > gdb/features/arm/arm-core.c | 37 ++++++++++++++++++++++++- > gdb/features/arm/arm-core.xml | 52 ++++++++++++++++++++++++++++++++++- > 2 files changed, 87 insertions(+), 2 deletions(-) > > diff --git a/gdb/features/arm/arm-core.c b/gdb/features/arm/arm-core.c > index e401411fc5e7..7eb8d4de0923 100644 > --- a/gdb/features/arm/arm-core.c > +++ b/gdb/features/arm/arm-core.c > @@ -9,6 +9,41 @@ create_feature_arm_arm_core (struct target_desc *result, long regnum) > struct tdesc_feature *feature; > > feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core"); > + tdesc_type_with_fields *type_with_fields; > + type_with_fields = tdesc_create_enum (feature, "pe_mode", 1); > + tdesc_add_enum_value (type_with_fields, 16, "user"); > + tdesc_add_enum_value (type_with_fields, 17, "FIQ"); > + tdesc_add_enum_value (type_with_fields, 18, "IRQ"); > + tdesc_add_enum_value (type_with_fields, 19, "supervisor"); > + tdesc_add_enum_value (type_with_fields, 22, "monitor"); > + tdesc_add_enum_value (type_with_fields, 23, "abort"); > + tdesc_add_enum_value (type_with_fields, 26, "hyp"); > + tdesc_add_enum_value (type_with_fields, 27, "undefined"); > + tdesc_add_enum_value (type_with_fields, 31, "system"); > + > + type_with_fields = tdesc_create_enum (feature, "endianness", 1); > + tdesc_add_enum_value (type_with_fields, 0, "little"); > + tdesc_add_enum_value (type_with_fields, 1, "big"); > + > + type_with_fields = tdesc_create_flags (feature, "cpsr_flags", 4); > + tdesc_type *field_type; > + field_type = tdesc_named_type (feature, "pe_mode"); > + tdesc_add_typed_bitfield (type_with_fields, "M", 0, 4, field_type); > + tdesc_add_flag (type_with_fields, 6, "F"); > + tdesc_add_flag (type_with_fields, 7, "I"); > + tdesc_add_flag (type_with_fields, 8, "A"); > + field_type = tdesc_named_type (feature, "endianness"); > + tdesc_add_typed_bitfield (type_with_fields, "E", 9, 9, field_type); > + tdesc_add_bitfield (type_with_fields, "GE", 16, 19); > + tdesc_add_flag (type_with_fields, 21, "DIT"); > + tdesc_add_flag (type_with_fields, 22, "PAN"); > + tdesc_add_flag (type_with_fields, 23, "SSBS"); > + tdesc_add_flag (type_with_fields, 27, "Q"); > + tdesc_add_flag (type_with_fields, 28, "V"); > + tdesc_add_flag (type_with_fields, 29, "C"); > + tdesc_add_flag (type_with_fields, 30, "Z"); > + tdesc_add_flag (type_with_fields, 31, "N"); > + > tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "uint32"); > tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "uint32"); > tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "uint32"); > @@ -26,6 +61,6 @@ create_feature_arm_arm_core (struct target_desc *result, long regnum) > tdesc_create_reg (feature, "lr", regnum++, 1, NULL, 32, "int"); > tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr"); > regnum = 25; > - tdesc_create_reg (feature, "cpsr", regnum++, 1, NULL, 32, "int"); > + tdesc_create_reg (feature, "cpsr", regnum++, 1, NULL, 32, "cpsr_flags"); > return regnum; > } > diff --git a/gdb/features/arm/arm-core.xml b/gdb/features/arm/arm-core.xml > index 498aee1f8595..52edc66045a2 100644 > --- a/gdb/features/arm/arm-core.xml > +++ b/gdb/features/arm/arm-core.xml > @@ -24,8 +24,58 @@ > <reg name="lr" bitsize="32"/> > <reg name="pc" bitsize="32" type="code_ptr"/> > > + <enum id="pe_mode" size="1"> > + <evalue name="user" value="0x10"/> > + <evalue name="FIQ" value="0x11"/> > + <evalue name="IRQ" value="0x12"/> > + <evalue name="supervisor" value="0x13"/> > + <evalue name="monitor" value="0x16"/> > + <evalue name="abort" value="0x17"/> > + <evalue name="hyp" value="0x1A"/> > + <evalue name="undefined" value="0x1B"/> > + <evalue name="system" value="0x1F"/> > + </enum> > + <enum id="endianness" size="1"> > + <evalue name="little" value="0"/> > + <evalue name="big" value="1"/> > + </enum> > + <flags id="cpsr_flags" size="4"> > + <!-- Current mode of the PE. --> > + <field name="M" start="0" end="4" type="pe_mode"/> > + > + <!-- FIQ interrupt mask. --> > + <field name="F" start="6" end="6"/> > + <!-- IRQ interrupt mask. --> > + <field name="I" start="7" end="7"/> > + <!-- SError interrupt mask. --> > + <field name="A" start="8" end="8"/> > + <!-- Endianness of data accesses. --> > + <field name="E" start="9" end="9" type="endianness"/> > + > + <!-- Greater than or equal flags. --> > + <field name="GE" start="16" end="19"/> > + > + <!-- ARMv8.4-A: Data Independent Timing. --> > + <field name="DIT" start="21" end="21"/> > + <!-- ARMv8.1-A: Privileged Access Never. --> > + <field name="PAN" start="22" end="22"/> > + <!-- ARMv8.5-A: Speculative Store Bypass Safe. --> > + <field name="SSBS" start="23" end="23"/> > + > + <!-- Overflow or saturation flag. --> > + <field name="Q" start="27" end="27"/> > + > + <!-- Overflow Condition flag. --> > + <field name="V" start="28" end="28"/> > + <!-- Carry Condition flag. --> > + <field name="C" start="29" end="29"/> > + <!-- Zero Condition flag. --> > + <field name="Z" start="30" end="30"/> > + <!-- Negative Condition flag. --> > + <field name="N" start="31" end="31"/> > + </flags> > <!-- The CPSR is register 25, rather than register 16, because > the FPA registers historically were placed between the PC > and the CPSR in the "g" packet. --> > - <reg name="cpsr" bitsize="32" regnum="25"/> > + <reg name="cpsr" bitsize="32" type="cpsr_flags" regnum="25"/> > </feature> > > base-commit: faaee6b411411f3c1f45768d7ac15559fd27b980
diff --git a/gdb/features/arm/arm-core.c b/gdb/features/arm/arm-core.c index e401411fc5e7..7eb8d4de0923 100644 --- a/gdb/features/arm/arm-core.c +++ b/gdb/features/arm/arm-core.c @@ -9,6 +9,41 @@ create_feature_arm_arm_core (struct target_desc *result, long regnum) struct tdesc_feature *feature; feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core"); + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_enum (feature, "pe_mode", 1); + tdesc_add_enum_value (type_with_fields, 16, "user"); + tdesc_add_enum_value (type_with_fields, 17, "FIQ"); + tdesc_add_enum_value (type_with_fields, 18, "IRQ"); + tdesc_add_enum_value (type_with_fields, 19, "supervisor"); + tdesc_add_enum_value (type_with_fields, 22, "monitor"); + tdesc_add_enum_value (type_with_fields, 23, "abort"); + tdesc_add_enum_value (type_with_fields, 26, "hyp"); + tdesc_add_enum_value (type_with_fields, 27, "undefined"); + tdesc_add_enum_value (type_with_fields, 31, "system"); + + type_with_fields = tdesc_create_enum (feature, "endianness", 1); + tdesc_add_enum_value (type_with_fields, 0, "little"); + tdesc_add_enum_value (type_with_fields, 1, "big"); + + type_with_fields = tdesc_create_flags (feature, "cpsr_flags", 4); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "pe_mode"); + tdesc_add_typed_bitfield (type_with_fields, "M", 0, 4, field_type); + tdesc_add_flag (type_with_fields, 6, "F"); + tdesc_add_flag (type_with_fields, 7, "I"); + tdesc_add_flag (type_with_fields, 8, "A"); + field_type = tdesc_named_type (feature, "endianness"); + tdesc_add_typed_bitfield (type_with_fields, "E", 9, 9, field_type); + tdesc_add_bitfield (type_with_fields, "GE", 16, 19); + tdesc_add_flag (type_with_fields, 21, "DIT"); + tdesc_add_flag (type_with_fields, 22, "PAN"); + tdesc_add_flag (type_with_fields, 23, "SSBS"); + tdesc_add_flag (type_with_fields, 27, "Q"); + tdesc_add_flag (type_with_fields, 28, "V"); + tdesc_add_flag (type_with_fields, 29, "C"); + tdesc_add_flag (type_with_fields, 30, "Z"); + tdesc_add_flag (type_with_fields, 31, "N"); + tdesc_create_reg (feature, "r0", regnum++, 1, NULL, 32, "uint32"); tdesc_create_reg (feature, "r1", regnum++, 1, NULL, 32, "uint32"); tdesc_create_reg (feature, "r2", regnum++, 1, NULL, 32, "uint32"); @@ -26,6 +61,6 @@ create_feature_arm_arm_core (struct target_desc *result, long regnum) tdesc_create_reg (feature, "lr", regnum++, 1, NULL, 32, "int"); tdesc_create_reg (feature, "pc", regnum++, 1, NULL, 32, "code_ptr"); regnum = 25; - tdesc_create_reg (feature, "cpsr", regnum++, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "cpsr", regnum++, 1, NULL, 32, "cpsr_flags"); return regnum; } diff --git a/gdb/features/arm/arm-core.xml b/gdb/features/arm/arm-core.xml index 498aee1f8595..52edc66045a2 100644 --- a/gdb/features/arm/arm-core.xml +++ b/gdb/features/arm/arm-core.xml @@ -24,8 +24,58 @@ <reg name="lr" bitsize="32"/> <reg name="pc" bitsize="32" type="code_ptr"/> + <enum id="pe_mode" size="1"> + <evalue name="user" value="0x10"/> + <evalue name="FIQ" value="0x11"/> + <evalue name="IRQ" value="0x12"/> + <evalue name="supervisor" value="0x13"/> + <evalue name="monitor" value="0x16"/> + <evalue name="abort" value="0x17"/> + <evalue name="hyp" value="0x1A"/> + <evalue name="undefined" value="0x1B"/> + <evalue name="system" value="0x1F"/> + </enum> + <enum id="endianness" size="1"> + <evalue name="little" value="0"/> + <evalue name="big" value="1"/> + </enum> + <flags id="cpsr_flags" size="4"> + <!-- Current mode of the PE. --> + <field name="M" start="0" end="4" type="pe_mode"/> + + <!-- FIQ interrupt mask. --> + <field name="F" start="6" end="6"/> + <!-- IRQ interrupt mask. --> + <field name="I" start="7" end="7"/> + <!-- SError interrupt mask. --> + <field name="A" start="8" end="8"/> + <!-- Endianness of data accesses. --> + <field name="E" start="9" end="9" type="endianness"/> + + <!-- Greater than or equal flags. --> + <field name="GE" start="16" end="19"/> + + <!-- ARMv8.4-A: Data Independent Timing. --> + <field name="DIT" start="21" end="21"/> + <!-- ARMv8.1-A: Privileged Access Never. --> + <field name="PAN" start="22" end="22"/> + <!-- ARMv8.5-A: Speculative Store Bypass Safe. --> + <field name="SSBS" start="23" end="23"/> + + <!-- Overflow or saturation flag. --> + <field name="Q" start="27" end="27"/> + + <!-- Overflow Condition flag. --> + <field name="V" start="28" end="28"/> + <!-- Carry Condition flag. --> + <field name="C" start="29" end="29"/> + <!-- Zero Condition flag. --> + <field name="Z" start="30" end="30"/> + <!-- Negative Condition flag. --> + <field name="N" start="31" end="31"/> + </flags> <!-- The CPSR is register 25, rather than register 16, because the FPA registers historically were placed between the PC and the CPSR in the "g" packet. --> - <reg name="cpsr" bitsize="32" regnum="25"/> + <reg name="cpsr" bitsize="32" type="cpsr_flags" regnum="25"/> </feature>