]> git.ipfire.org Git - thirdparty/gcc.git/commit - gcc/config/pru/pru.cc
pru: Named address space for R30/R31 I/O access
authorDimitar Dimitrov <dimitar@dinux.eu>
Sun, 22 Aug 2021 15:49:31 +0000 (18:49 +0300)
committerDimitar Dimitrov <dimitar@dinux.eu>
Sat, 25 Sep 2021 13:44:54 +0000 (16:44 +0300)
commit8bafc9640f353ff11c0535a03096fb4db9a5bb95
treeffda3f4fc73f0bc39b064deb503937c679570da5
parent9a4293ed9bdd029dd44d19b412b1cdf12372801e
pru: Named address space for R30/R31 I/O access

The PRU architecture provides single-cycle access to GPIO pins via
special designated CPU registers - R30 and R31. These two registers can
of course be accessed in C code using inline assembly, but that can be
intimidating to users.

The TI proprietary compiler [1] can expose these I/O registers as global
volatile registers:
  volatile register unsigned int __R31;

Consequently, accessing them in user programs is as straightforward as
using a regular global variable:
  __R31 |= (1 << 2);

Unfortunately, global volatile registers are not supported by GCC [2].
I decided to implement convenient access to __R30 and __R31 using a new
named address space:
  extern volatile __regio_symbol unsigned int __R30;
Unlike global registers, volatile global memory variables are well
supported in GCC.  Memory writes and reads to the __regio_symbol address
space are converted to writes and reads to R30 and R31 CPU registers.
The declared variable name determines which of the two registers it is
representing.

With an ifdef for the __R30/__R31 declarations, user programs can now
be source-compatible with both TI and GCC toolchains.

[1] https://www.ti.com/lit/ug/spruhv7c/spruhv7c.pdf , "Global Register Variables"
[2] https://gcc.gnu.org/ml/gcc-patches/2015-01/msg02241.html

gcc/ChangeLog:

* config/pru/constraints.md (Rrio): New constraint.
* config/pru/predicates.md (regio_operand): New predicate.
* config/pru/pru-pragma.c (pru_register_pragmas): Register
the __regio_symbol address space.
* config/pru/pru-protos.h (pru_symref2ioregno): Declaration.
* config/pru/pru.c (pru_symref2ioregno): New helper function.
(pru_legitimate_address_p): Remove.
(pru_addr_space_legitimate_address_p): Use the address space
aware hook variant.
(pru_nongeneric_pointer_addrspace): New helper function.
(pru_insert_attributes): New function to validate __regio_symbol
usage.
(TARGET_INSERT_ATTRIBUTES): New macro.
(TARGET_LEGITIMATE_ADDRESS_P): Remove.
(TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P): New macro.
* config/pru/pru.h (enum reg_class): Add REGIO_REGS class.
* config/pru/pru.md (*regio_readsi): New pattern to read I/O
registers.
(*regio_nozext_writesi): New pattern to write to I/O registers.
(*regio_zext_write_r30<EQS0:mode>): Ditto.
* doc/extend.texi: Document the new PRU Named Address Space.

gcc/testsuite/ChangeLog:

* gcc.target/pru/regio-as-pointer.c: New negative test.
* gcc.target/pru/regio-as-pointer-2.c: New negative test.
* gcc.target/pru/regio-decl-2.c: New negative test.
* gcc.target/pru/regio-decl-3.c: New negative test.
* gcc.target/pru/regio-decl-4.c: New negative test.
* gcc.target/pru/regio-decl.c: New negative test.
* gcc.target/pru/regio-di.c: New negative test.
* gcc.target/pru/regio-hi.c: New negative test.
* gcc.target/pru/regio-qi.c: New negative test.
* gcc.target/pru/regio.c: New test.
* gcc.target/pru/regio.h: New helper header.

Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu>
19 files changed:
gcc/config/pru/constraints.md
gcc/config/pru/predicates.md
gcc/config/pru/pru-pragma.c
gcc/config/pru/pru-protos.h
gcc/config/pru/pru.c
gcc/config/pru/pru.h
gcc/config/pru/pru.md
gcc/doc/extend.texi
gcc/testsuite/gcc.target/pru/regio-as-pointer-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-as-pointer.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-decl-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-decl-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-decl-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-decl.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-di.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-hi.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio-qi.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio.c [new file with mode: 0644]
gcc/testsuite/gcc.target/pru/regio.h [new file with mode: 0644]