https://gcc.gnu.org/g:e42799be2bb2966487c27897294426a03a99f56d

commit r16-2362-ge42799be2bb2966487c27897294426a03a99f56d
Author: Dimitar Dimitrov <dimi...@dinux.eu>
Date:   Fri Jul 18 23:45:50 2025 +0300

    pru: Use signed HOST_WIDE_INT for handling ctable addresses
    
    The ctable base address for SBCO/LBCO load/store patterns was
    incorrectly stored as unsigned integer.  That prevented matching
    addresses with bit 31 set, because const_int RTL expression is expected
    to be sign-extended.
    
    Fix by using sign-extended 32-bit values for ctable base addresses.
    
            PR target/121124
    
    gcc/ChangeLog:
    
            * config/pru/pru-pragma.cc (pru_pragma_ctable_entry): Handle the
            ctable base address as signed 32-bit value, and sign-extend to
            HOST_WIDE_INT.
            * config/pru/pru-protos.h (struct pru_ctable_entry): Store the
            ctable base address as signed.
            (pru_get_ctable_exact_base_index): Pass base address as signed.
            (pru_get_ctable_base_index): Ditto.
            (pru_get_ctable_base_offset): Ditto.
            * config/pru/pru.cc (pru_get_ctable_exact_base_index): Ditto.
            (pru_get_ctable_base_index): Ditto.
            (pru_get_ctable_base_offset): Ditto.
            (pru_print_operand_address): Ditto.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/pru/pragma-ctable_entry-2.c: New test.

Diff:
---
 gcc/config/pru/pru-pragma.cc                       | 13 ++++++++-----
 gcc/config/pru/pru-protos.h                        |  8 ++++----
 gcc/config/pru/pru.cc                              |  8 ++++----
 .../gcc.target/pru/pragma-ctable_entry-2.c         | 22 ++++++++++++++++++++++
 4 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/gcc/config/pru/pru-pragma.cc b/gcc/config/pru/pru-pragma.cc
index c3f3d33d5470..933878051424 100644
--- a/gcc/config/pru/pru-pragma.cc
+++ b/gcc/config/pru/pru-pragma.cc
@@ -46,21 +46,24 @@ pru_pragma_ctable_entry (cpp_reader *)
   enum cpp_ttype type;
 
   type = pragma_lex (&ctable_index);
-  if (type == CPP_NUMBER && tree_fits_uhwi_p (ctable_index))
+  if (type == CPP_NUMBER && tree_fits_shwi_p (ctable_index))
     {
       type = pragma_lex (&base_addr);
-      if (type == CPP_NUMBER  && tree_fits_uhwi_p (base_addr))
+      if (type == CPP_NUMBER && tree_fits_shwi_p (base_addr))
        {
-         unsigned HOST_WIDE_INT i = tree_to_uhwi (ctable_index);
-         unsigned HOST_WIDE_INT base = tree_to_uhwi (base_addr);
+         HOST_WIDE_INT i = tree_to_shwi (ctable_index);
+         HOST_WIDE_INT base = sext_hwi (tree_to_shwi (base_addr),
+                                        POINTER_SIZE);
 
          type = pragma_lex (&base_addr);
          if (type != CPP_EOF)
            error ("junk at end of %<#pragma CTABLE_ENTRY%>");
-         else if (i >= ARRAY_SIZE (pru_ctable))
+         else if (!IN_RANGE (i, 0, ARRAY_SIZE (pru_ctable) - 1))
            error ("%<CTABLE_ENTRY%> index %wd is not valid", i);
          else if (pru_ctable[i].valid && pru_ctable[i].base != base)
            error ("redefinition of %<CTABLE_ENTRY %wd%>", i);
+         else if (!IN_RANGE (base, INT32_MIN, INT32_MAX))
+           error ("%<CTABLE_ENTRY%> base address does not fit in 32-bits");
          else
            {
              if (base & 0xff)
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
index c73fad870c21..4750f0e10077 100644
--- a/gcc/config/pru/pru-protos.h
+++ b/gcc/config/pru/pru-protos.h
@@ -23,7 +23,7 @@
 
 struct pru_ctable_entry {
     bool valid;
-    unsigned HOST_WIDE_INT base;
+    HOST_WIDE_INT base;
 };
 
 extern struct pru_ctable_entry pru_ctable[32];
@@ -66,9 +66,9 @@ pru_regno_ok_for_index_p (int regno, bool strict_p)
   return pru_regno_ok_for_base_p (regno, strict_p);
 }
 
-extern int pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr);
-extern int pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr);
-extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr);
+extern int pru_get_ctable_exact_base_index (HOST_WIDE_INT caddr);
+extern int pru_get_ctable_base_index (HOST_WIDE_INT caddr);
+extern int pru_get_ctable_base_offset (HOST_WIDE_INT caddr);
 
 extern int pru_symref2ioregno (rtx op);
 
diff --git a/gcc/config/pru/pru.cc b/gcc/config/pru/pru.cc
index 47e5f248ce79..322e3196a6e4 100644
--- a/gcc/config/pru/pru.cc
+++ b/gcc/config/pru/pru.cc
@@ -1428,7 +1428,7 @@ pru_valid_const_ubyte_offset (machine_mode mode, 
HOST_WIDE_INT offset)
 /* Recognize a CTABLE base address.  Return CTABLE entry index, or -1 if
    base was not found in the pragma-filled pru_ctable.  */
 int
-pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr)
+pru_get_ctable_exact_base_index (HOST_WIDE_INT caddr)
 {
   unsigned int i;
 
@@ -1444,7 +1444,7 @@ pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT 
caddr)
 /* Check if the given address can be addressed via CTABLE_BASE + UBYTE_OFFS,
    and return the base CTABLE index if possible.  */
 int
-pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr)
+pru_get_ctable_base_index (HOST_WIDE_INT caddr)
 {
   unsigned int i;
 
@@ -1461,7 +1461,7 @@ pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr)
 
 /* Return the offset from some CTABLE base for this address.  */
 int
-pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr)
+pru_get_ctable_base_offset (HOST_WIDE_INT caddr)
 {
   int i;
 
@@ -2004,7 +2004,7 @@ pru_print_operand_address (FILE *file, machine_mode mode, 
rtx op)
 
     case CONST_INT:
       {
-       unsigned HOST_WIDE_INT caddr = INTVAL (op);
+       HOST_WIDE_INT caddr = INTVAL (op);
        int base = pru_get_ctable_base_index (caddr);
        int offs = pru_get_ctable_base_offset (caddr);
        if (base < 0)
diff --git a/gcc/testsuite/gcc.target/pru/pragma-ctable_entry-2.c 
b/gcc/testsuite/gcc.target/pru/pragma-ctable_entry-2.c
new file mode 100644
index 000000000000..a1c707d5c466
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/pragma-ctable_entry-2.c
@@ -0,0 +1,22 @@
+/* Test for base addresses with bit 31 set (PR121124).  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant.  Without it LBCO/SBCO operations may
+   not be optimized to the respective instructions.  */
+
+
+#pragma ctable_entry 12 0x80beef00
+
+unsigned int
+test_ctable (unsigned int val1, unsigned int val2)
+{
+  ((volatile unsigned short int *)0x80beef00)[0] = val2;
+  ((volatile unsigned int *)0x80beef00)[val1] = val2;
+  return ((volatile unsigned int *)0x80beef00)[5];
+}
+
+/* { dg-final { scan-assembler "sbco\\tr15.b\[012\]?, 12, 0, 2" } } */
+/* { dg-final { scan-assembler "sbco\\tr15.b0, 12, r14, 4" } } */
+/* { dg-final { scan-assembler "lbco\\tr14.b0, 12, 20, 4" } } */

Reply via email to