diff mbox series

gdb: arm: Add CPSR fields to arm-core target description

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

Commit Message

Thiago Jung Bauermann April 9, 2025, 4:14 a.m. UTC
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:

  (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(-)


base-commit: faaee6b411411f3c1f45768d7ac15559fd27b980

Comments

Luis Machado April 9, 2025, 8:49 a.m. UTC | #1
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 mbox series

Patch

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>