1

I'm trying to write the following code :

#define CONFIG_PMP_SLOTS 16
#define PMPCFG_STRIDE 4
#define CSR_PMPCFG_BASE  0x3a0

void csr_pmp_check(){
    for(int i = 0; i < (CONFIG_PMP_SLOTS / PMPCFG_STRIDE); i++)
    {
        int pmp_cfg;
        __asm__ volatile("csrrs %0, %1, x0"
                         : "=r" (pmp_cfg)      // output operand
                         : "r" (CSR_PMPCFG_BASE + PMPCFG_STRIDE * i )   // input operand
                         );
    }
}

But when i try to compile I get the following error :
test.c: Assembler messages:
test.c:9: Error: unknown CSR `a5'

I tried to replace :

: "r" (CSR_PMPCFG_BASE + PMPCFG_STRIDE * i )   // input operand

By :

: "i" (CSR_PMPCFG_BASE + PMPCFG_STRIDE * i )   // input operand

But if i do so i got an error telling me warning: 'asm' operand 1 probably does not match constraints.
Btw i compile like this :

    riscv32-unknown-elf-gcc -nostdlib  test.c
Lovis XII
  • 39
  • 5
  • 1
    Try `I` (capital). But that is just a warning anyway so it should still work. – Jester Jan 07 '23 at 11:42
  • I tried and I got this : ``` test.c: In function 'csr_pmp_check': test.c:9:3: warning: 'asm' operand 1 probably does not match constraints 9 | __asm__ volatile("csrr %0, %1" | ^~~~~~~ test.c:9:3: error: impossible constraint in 'asm' ``` And no output is generated so i can't even objdump it to see what's going wrong I aslo tried without -nostdlib just in case (i added a main toa void the warning on __start) but it doesn't work either – Lovis XII Jan 07 '23 at 11:43
  • 1
    Ahha, you need a compile time constant there but since you used a variable this would only work if the loop was unrolled. As such it seems to work at `-O2`. You might want to mark the function with `__attribute__((optimize(2)))` (or figure out what specific optimization is needed) so it can be compiled even if optimization is not globally enabled. – Jester Jan 07 '23 at 12:27
  • I did this according to what you said : ```c #define CONFIG_PMP_SLOTS 16 #define PMPCFG_STRIDE 4 #define CSR_PMPCFG_BASE 0x3a0 __attribute__((optimize(2))) void csr_pmp_check(){ for(int i = 0; i < (CONFIG_PMP_SLOTS / PMPCFG_STRIDE); i++) { int pmp_cfg; __asm__ volatile("csrr %0, %1" : "=r" (pmp_cfg) // output operand : "r" (CSR_PMPCFG_BASE + PMPCFG_STRIDE * i ) // input operand ); } } ``` I compiled with : ``` riscv32-unknown-elf-gcc -nostdlib -O2 test.c ``` It doesn't seems to work either – Lovis XII Jan 07 '23 at 12:35
  • And i don't get why unrolling the loop could solve the issue ? – Lovis XII Jan 07 '23 at 12:36
  • Since each different `i` value needs to be embedded into the machine code (as an immediate operand), the only way for the `asm` statement to run with `n` different `i` values is to repeat it `n` times, i.e.e loop unrolling. Otherwise `"I" (CSR_PMPCFG_BASE + PMPCFG_STRIDE * i)` won't actually be a compile-time constant. – Peter Cordes Jan 07 '23 at 12:47
  • You need to keep the `i` constraint. – Jester Jan 07 '23 at 12:53
  • I don't see any instructions that can take a CSR number in a register, unlike x86 `rdmsr`/`wrmsr`. `csrrs` definitely needs the CSR number as an immediate; read the manual and look at the machine code format for it: https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf – Peter Cordes Jan 07 '23 at 12:54
  • Thanks for those answer, so : If i get it well it means that when i write CSR_PMPCFG_BASE + PMPCFG_STRIDE * i, the i value will not be reevaluate by the compiler since it's known at run time ? Then there is indeed no csrr instruction in the riscv spec. In fact when you re writing csrr it's an crrs instruction but with rs1 to 0 and the compiler is suppose to understand that. Just like when you're using li (load immediate) which doesn't exist in the spec but is understood by the compiler – Lovis XII Jan 07 '23 at 13:52
  • 1
    Okay yeah with "i" and the __attribe__ statement i works, thanks ! – Lovis XII Jan 07 '23 at 14:46

1 Answers1

2

So this code seems to work. Thanks a lot to Peter and Jester.

#define CONFIG_PMP_SLOTS 16
#define PMPCFG_STRIDE 4
#define CSR_PMPCFG_BASE  0x3a0

__attribute__((optimize(2))) void csr_pmp_check(){
    for(int i = 0; i < (CONFIG_PMP_SLOTS / PMPCFG_STRIDE); i++)
    {
        int pmp_cfg;
        __asm__ volatile("csrr %0, %1"
                         : "=r" (pmp_cfg)      // output operand
                         : "i" (CSR_PMPCFG_BASE + i )   // input operand
                         );
    }
}
Lovis XII
  • 39
  • 5