Skip to content

Commit e0be2d6

Browse files
committed
Add operand constraint for inline asm statement.
Add miminal common operand constraint between LLVM and GCC. Plan to extend this like vector register constraint in future.
1 parent dccfa30 commit e0be2d6

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

riscv-c-api.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,66 @@ long __riscv_clmul (long a, long b); // clmul rd, rs1, rs2
213213
#include <riscv_vector.h> // make RISC-V vector intrinsics available
214214
vint8m1_t __riscv_vadd_vv_i8m1(vint8m1_t vs2, vint8m1_t vs1, size_t vl); // vadd.vv vd, vs2, vs1
215215
```
216+
217+
## Constraints on Operands of Inline Assembly Statements
218+
219+
This section lists operand constraints that can be used with inline assembly
220+
statements, including both RISC-V specific and common operand constraints.
221+
222+
223+
| Constraint | | Note |
224+
| ------------------ | ---------------------------------- | ----------- |
225+
| m | An address that is held in a general-purpose register with offset. | |
226+
| A | An address that is held in a general-purpose register. | |
227+
| r | General purpose register | |
228+
| f | Floating-point register | |
229+
| i | Immediate integer operand | |
230+
| I | 12-bit signed immediate integer operand | |
231+
| K | 5-bit unsigned immediate integer operand | |
232+
| J | Zero integer immediate operand | |
233+
234+
NOTE: Immediate value must be a compile-time constant.
235+
236+
### The Difference Between `m` and `A` Constraints
237+
238+
The difference between `m` and `A` is whether the operand can have an offset;
239+
some instructions in RISC-V do not allow an offset for the address operand,
240+
such as atomic or vector load/store instructions.
241+
242+
The following example demonstrates the difference; it is trying
243+
to load value from `foo[10]` and using `m` and `A` to pass that address.
244+
245+
```c
246+
int *foo;
247+
void bar() {
248+
int x;
249+
__asm__ volatile ("lw %0, %1" : "=r"(x) : "m" (foo[10]));
250+
__asm__ volatile ("lw %0, %1" : "=r"(x) : "A" (foo[10]));
251+
}
252+
```
253+
254+
Then we compile with GCC with `-O` option:
255+
256+
```shell
257+
$ riscv64-unknown-elf-gcc x.c -o - -O -S
258+
...
259+
bar:
260+
lui a5,%hi(foo)
261+
ld a5,%lo(foo)(a5)
262+
#APP
263+
# 4 "x.c" 1
264+
lw a4, 40(a5)
265+
# 0 "" 2
266+
#NO_APP
267+
addi a5,a5,40
268+
#APP
269+
# 5 "x.c" 1
270+
lw a5, 0(a5)
271+
# 0 "" 2
272+
#NO_APP
273+
ret
274+
275+
```
276+
277+
The compiler uses an immediate offset of 40 for the `m` constraint, but for the
278+
`A` constraint uses an extra addi instruction instead.

0 commit comments

Comments
 (0)