riscv.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _HARDWARE_RISCV_
8#define _HARDWARE_RISCV_
9
10#include "pico.h"
11#include "hardware/regs/rvcsr.h"
12
13#ifndef __ASSEMBLER__
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
26#define _riscv_read_csr(csrname) ({ \
27 uint32_t __csr_tmp_u32; \
28 asm volatile ("csrr %0, " #csrname : "=r" (__csr_tmp_u32)); \
29 __csr_tmp_u32; \
30})
31
32#define _riscv_write_csr(csrname, data) ({ \
33 if (__builtin_constant_p(data) && !((data) & -32u)) { \
34 asm volatile ("csrwi " #csrname ", %0" : : "i" (data)); \
35 } else { \
36 asm volatile ("csrw " #csrname ", %0" : : "r" (data)); \
37 } \
38})
39
40#define _riscv_set_csr(csrname, data) ({ \
41 if (__builtin_constant_p(data) && !((data) & -32u)) { \
42 asm volatile ("csrsi " #csrname ", %0" : : "i" (data)); \
43 } else { \
44 asm volatile ("csrs " #csrname ", %0" : : "r" (data)); \
45 } \
46})
47
48#define _riscv_clear_csr(csrname, data) ({ \
49 if (__builtin_constant_p(data) && !((data) & -32u)) { \
50 asm volatile ("csrci " #csrname ", %0" : : "i" (data)); \
51 } else { \
52 asm volatile ("csrc " #csrname ", %0" : : "r" (data)); \
53 } \
54})
55
56#define _riscv_read_write_csr(csrname, data) ({ \
57 uint32_t __csr_tmp_u32; \
58 if (__builtin_constant_p(data) && !((data) & -32u)) { \
59 asm volatile ("csrrwi %0, " #csrname ", %1": "=r" (__csr_tmp_u32) : "i" (data)); \
60 } else { \
61 asm volatile ("csrrw %0, " #csrname ", %1": "=r" (__csr_tmp_u32) : "r" (data)); \
62 } \
63 __csr_tmp_u32; \
64})
65
66#define _riscv_read_set_csr(csrname, data) ({ \
67 uint32_t __csr_tmp_u32; \
68 if (__builtin_constant_p(data) && !((data) & -32u)) { \
69 asm volatile ("csrrsi %0, " #csrname ", %1": "=r" (__csr_tmp_u32) : "i" (data)); \
70 } else { \
71 asm volatile ("csrrs %0, " #csrname ", %1": "=r" (__csr_tmp_u32) : "r" (data)); \
72 } \
73 __csr_tmp_u32; \
74})
75
76#define _riscv_read_clear_csr(csrname, data) ({ \
77 uint32_t __csr_tmp_u32; \
78 if (__builtin_constant_p(data) && !((data) & -32u)) { \
79 asm volatile ("csrrci %0, " #csrname ", %1": "=r" (__csr_tmp_u32) : "i" (data)); \
80 } else { \
81 asm volatile ("csrrc %0, " #csrname ", %1": "=r" (__csr_tmp_u32) : "r" (data)); \
82 } \
83 __csr_tmp_u32; \
84})
85
86// Argument macro expansion layer (CSR name may be a macro that expands to a
87// CSR number, or it may be a bare name that the assembler knows about.)
88#define riscv_read_csr(csrname) _riscv_read_csr(csrname)
89#define riscv_write_csr(csrname, data) _riscv_write_csr(csrname, data)
90#define riscv_set_csr(csrname, data) _riscv_set_csr(csrname, data)
91#define riscv_clear_csr(csrname, data) _riscv_clear_csr(csrname, data)
92#define riscv_read_write_csr(csrname, data) _riscv_read_write_csr(csrname, data)
93#define riscv_read_set_csr(csrname, data) _riscv_read_set_csr(csrname, data)
94#define riscv_read_clear_csr(csrname, data) _riscv_read_clear_csr(csrname, data)
95
96// Helpers for encoding RISC-V immediates
97
98// U format, e.g. lui
99static inline uint32_t riscv_encode_imm_u(uint32_t x) {
100 return (x >> 12) << 12;
101}
102
103// I format, e.g. addi
104static inline uint32_t riscv_encode_imm_i(uint32_t x) {
105 return (x & 0xfff) << 20;
106}
107
108// The U-format part of a U+I 32-bit immediate:
109static inline uint32_t riscv_encode_imm_u_hi(uint32_t x) {
110 // We will add a signed 12 bit constant to the "lui" value,
111 // so we need to correct for the carry here.
112 x += (x & 0x800) << 1;
113 return riscv_encode_imm_u(x);
114}
115
116// B format, e.g. bgeu
117static inline uint32_t riscv_encode_imm_b(uint32_t x) {
118 return
119 (((x >> 12) & 0x01) << 31) |
120 (((x >> 5) & 0x3f) << 25) |
121 (((x >> 1) & 0x0f) << 8) |
122 (((x >> 11) & 0x01) << 7);
123}
124
125// S format, e.g. sw
126static inline uint32_t riscv_encode_imm_s(uint32_t x) {
127 return
128 (((x >> 5) & 0x7f) << 25) |
129 (((x >> 0) & 0x1f) << 7);
130}
131
132// J format, e.g. jal
133static inline uint32_t riscv_encode_imm_j(uint32_t x) {
134 return
135 (((x >> 20) & 0x001) << 31) |
136 (((x >> 1) & 0x3ff) << 21) |
137 (((x >> 11) & 0x001) << 20) |
138 (((x >> 12) & 0x0ff) << 12);
139}
140
141// CJ format, e.g. c.jal
142static inline uint16_t riscv_encode_imm_cj(uint32_t x) {
143 return (uint16_t)(
144 (((x >> 11) & 0x1) << 12) |
145 (((x >> 4) & 0x1) << 11) |
146 (((x >> 8) & 0x3) << 9) |
147 (((x >> 10) & 0x1) << 8) |
148 (((x >> 6) & 0x1) << 7) |
149 (((x >> 7) & 0x1) << 6) |
150 (((x >> 1) & 0x7) << 3) |
151 (((x >> 5) & 0x1) << 2)
152 );
153}
154
155// CB format, e.g. c.beqz
156static inline uint16_t riscv_encode_imm_cb(uint32_t x) {
157 return (uint16_t)(
158 (((x >> 8) & 0x1) << 12) |
159 (((x >> 3) & 0x3) << 10) |
160 (((x >> 6) & 0x3) << 5) |
161 (((x >> 1) & 0x3) << 3) |
162 (((x >> 5) & 0x1) << 2)
163 );
164}
165
166// CI format, e.g. c.addi
167static inline uint16_t riscv_encode_imm_ci(uint32_t x) {
168 return (uint16_t)(
169 (((x >> 5) & 0x01) << 12) |
170 (((x >> 0) & 0x1f) << 2)
171 );
172}
173
174#ifdef __cplusplus
175}
176#endif
177
178#endif
179#endif