]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
pru: Use signed HOST_WIDE_INT for handling ctable addresses
authorDimitar Dimitrov <dimitar@dinux.eu>
Fri, 18 Jul 2025 20:45:50 +0000 (23:45 +0300)
committerDimitar Dimitrov <dimitar@dinux.eu>
Sat, 19 Jul 2025 15:11:41 +0000 (18:11 +0300)
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.

gcc/config/pru/pru-pragma.cc
gcc/config/pru/pru-protos.h
gcc/config/pru/pru.cc
gcc/testsuite/gcc.target/pru/pragma-ctable_entry-2.c [new file with mode: 0644]

index c3f3d33d5470c3894684f598bd576777a99f44e6..9338780514246c7f7a8fa6292f828d731bc3ab12 100644 (file)
@@ -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)
index c73fad870c214aed12f102e3569892d71075a5d9..4750f0e100773c54dd8d550c727878ed1667ecf2 100644 (file)
@@ -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);
 
index 47e5f248ce79e33793304c60901a65418f110fea..322e3196a6e461a16dc6c045fd2197005905ff63 100644 (file)
@@ -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 (file)
index 0000000..a1c707d
--- /dev/null
@@ -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" } } */