Re: [PATCH][RFC] pru: Named address space for R30/R31 I/O access
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
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
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