Re: [PATCH][RFC] pru: Named address space for R30/R31 I/O access

2021-09-15 Thread Dimitar Dimitrov
On Wed, Sep 15, 2021 at 11:12:18AM +0200, Richard Biener wrote:
> On Tue, Sep 14, 2021 at 11:13 PM Dimitar Dimitrov  wrote:
> >
> > Hi,
> >
> > I'm sending this patch to get feedback for a new PRU CPU port feature.
> > My intention is to push it to master by end of September, so that it gets
> > included in GCC 12.
> >
> > 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].
> 
> Yes, a "register" write or read does not follow volatile semantics, so
> exposing those as registers isn't supported (I consider the GPIO regs
> similar to MSRs on other CPUs?).

Yes, they are a lot like MSRs.

> 
> > 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.
> 
> I think that's reasonable.  I do wonder whether it's possible to prevent
> taking the address of __R30 though - otherwise I guess the backend
> will crash or do weird things on such code?

I believe I have handled those cases, and suitable error messages are
emitted by the compiler.  See the negative test cases added in
regio-as-pointer*.c and regio-decl*.c.

Thanks,
Dimitar

> 
> > 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): 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-pointer2.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 
> > ---
> >  gcc/config/pru/constraints.md |   5 +
> >  gcc/config/pru/predicates.md  |  19 +++
> >  gcc/config/pru/pru-pragma.c   |   2 +
> >  gcc/config/pru/pru-protos.h   |   3 +
> >  gcc/config/pru/pru.c  | 155 +-
> >  gcc/config/pru/pru.h  |   5 +
> >  gcc/config/pru/pru.md | 102 +++-
> >  gcc/doc/extend.texi   |  19 ++-
> >  .../gcc.target/pru/regio-as-pointer.c |  11 ++
> >  .../gcc.target/pru/regio-as-pointer2.c|  11 ++
> >  

Re: [PATCH][RFC] pru: Named address space for R30/R31 I/O access

2021-09-15 Thread Richard Biener via Gcc-patches
On Tue, Sep 14, 2021 at 11:13 PM Dimitar Dimitrov  wrote:
>
> Hi,
>
> I'm sending this patch to get feedback for a new PRU CPU port feature.
> My intention is to push it to master by end of September, so that it gets
> included in GCC 12.
>
> 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].

Yes, a "register" write or read does not follow volatile semantics, so
exposing those as registers isn't supported (I consider the GPIO regs
similar to MSRs on other CPUs?).

> 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.

I think that's reasonable.  I do wonder whether it's possible to prevent
taking the address of __R30 though - otherwise I guess the backend
will crash or do weird things on such code?

> 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): 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-pointer2.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 
> ---
>  gcc/config/pru/constraints.md |   5 +
>  gcc/config/pru/predicates.md  |  19 +++
>  gcc/config/pru/pru-pragma.c   |   2 +
>  gcc/config/pru/pru-protos.h   |   3 +
>  gcc/config/pru/pru.c  | 155 +-
>  gcc/config/pru/pru.h  |   5 +
>  gcc/config/pru/pru.md | 102 +++-
>  gcc/doc/extend.texi   |  19 ++-
>  .../gcc.target/pru/regio-as-pointer.c |  11 ++
>  .../gcc.target/pru/regio-as-pointer2.c|  11 ++
>  gcc/testsuite/gcc.target/pru/regio-decl-2.c   |  13 ++
>  gcc/testsuite/gcc.target/pru/regio-decl-3.c   |  19 +++
>  gcc/testsuite/gcc.target/pru/regio-decl-4.c   |  17 ++
>  gcc/testsuite/gcc.target/pru/regio-decl.c |  15 ++
>  gcc/testsuite/gcc.target/pru/regio-di.c   |   9 +
>  gcc/testsuite/gcc.target/pru/regio-hi.c   |   9 +
>  gcc/testsuite/gcc.target/pru/regio-qi.c   |   9 +
>  gcc/testsuite/gcc.target/pru/regio.c  |  58 +++
>  gcc/testsuite/gcc.target/pru/regio.h  

[PATCH][RFC] pru: Named address space for R30/R31 I/O access

2021-09-14 Thread Dimitar Dimitrov
Hi,

I'm sending this patch to get feedback for a new PRU CPU port feature.
My intention is to push it to master by end of September, so that it gets
included in GCC 12.

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): 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-pointer2.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 
---
 gcc/config/pru/constraints.md |   5 +
 gcc/config/pru/predicates.md  |  19 +++
 gcc/config/pru/pru-pragma.c   |   2 +
 gcc/config/pru/pru-protos.h   |   3 +
 gcc/config/pru/pru.c  | 155 +-
 gcc/config/pru/pru.h  |   5 +
 gcc/config/pru/pru.md | 102 +++-
 gcc/doc/extend.texi   |  19 ++-
 .../gcc.target/pru/regio-as-pointer.c |  11 ++
 .../gcc.target/pru/regio-as-pointer2.c|  11 ++
 gcc/testsuite/gcc.target/pru/regio-decl-2.c   |  13 ++
 gcc/testsuite/gcc.target/pru/regio-decl-3.c   |  19 +++
 gcc/testsuite/gcc.target/pru/regio-decl-4.c   |  17 ++
 gcc/testsuite/gcc.target/pru/regio-decl.c |  15 ++
 gcc/testsuite/gcc.target/pru/regio-di.c   |   9 +
 gcc/testsuite/gcc.target/pru/regio-hi.c   |   9 +
 gcc/testsuite/gcc.target/pru/regio-qi.c   |   9 +
 gcc/testsuite/gcc.target/pru/regio.c  |  58 +++
 gcc/testsuite/gcc.target/pru/regio.h  |   7 +
 19 files changed, 477 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-as-pointer.c
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-as-pointer2.c
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-decl-2.c
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-decl-3.c
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-decl-4.c
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-decl.c
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-di.c
 create mode 100644 gcc/testsuite/gcc.target/pru/regio-hi.c
 create mode 100644