riscv: Add full fence instruction support

This commit adds support for `fence`'s predecessor and successor
arguments.
This commit is contained in:
Ekaitz Zarraga 2024-04-23 15:01:05 +02:00
parent c994068175
commit 671d03f944
2 changed files with 56 additions and 4 deletions

View File

@ -132,9 +132,6 @@ static void asm_nullary_opcode(TCCState *s1, int token)
switch (token) {
// Sync instructions
case TOK_ASM_fence: // I
asm_emit_opcode((0x3 << 2) | 3 | (0 << 12));
return;
case TOK_ASM_fence_i: // I
asm_emit_opcode((0x3 << 2) | 3| (1 << 12));
return;
@ -435,6 +432,34 @@ static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Oper
gen_le32(opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
}
static int parse_fence_operand(){
int t = tok;
if ( tok == TOK_ASM_or ){
// we are in a fence instruction, parse as output read
t = TOK_ASM_or_fence;
}
next();
return t - (TOK_ASM_w_fence - 1);
}
static void asm_fence_opcode(TCCState *s1, int token){
// `fence` is both an instruction and a pseudoinstruction:
// `fence` expands to `fence iorw, iorw`
int succ = 0xF, pred = 0xF;
if (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF){
pred = parse_fence_operand();
if ( pred > 0xF || pred < 0) {
tcc_error("'%s': Expected first operand that is a valid predecessor operand", get_tok_str(token, NULL));
}
if ( tok == ',') next(); else expect("','");
succ = parse_fence_operand();
if ( succ > 0xF || succ < 0) {
tcc_error("'%s': Expected second operand that is a valid successor operand", get_tok_str(token, NULL));
}
}
asm_emit_opcode((0x3 << 2) | 3 | (0 << 12) | succ<<20 | pred<<24);
}
static void asm_binary_opcode(TCCState* s1, int token)
{
static const Operand zero = {.type = OP_REG, .reg = 0};
@ -1206,7 +1231,6 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
switch (token) {
case TOK_ASM_ebreak:
case TOK_ASM_ecall:
case TOK_ASM_fence: // XXX: it's missing iorw for pred and succ
case TOK_ASM_fence_i:
case TOK_ASM_hrts:
case TOK_ASM_mrth:
@ -1215,6 +1239,10 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
asm_nullary_opcode(s1, token);
return;
case TOK_ASM_fence:
asm_fence_opcode(s1, token);
return;
case TOK_ASM_rdcycle:
case TOK_ASM_rdcycleh:
case TOK_ASM_rdtime:

View File

@ -11,6 +11,9 @@
#define DEF_ASM_WITH_SUFFIXES(x, y, z) \
DEF(TOK_ASM_ ## x ## _ ## y ## _ ## z, #x "." #y "." #z)
#define DEF_ASM_FENCE(x) \
DEF(TOK_ASM_ ## x ## _fence, #x)
/* register */
/* integer */
DEF_ASM(x0)
@ -448,4 +451,25 @@
DEF_ASM_WITH_SUFFIXES(sc, d, rl)
DEF_ASM_WITH_SUFFIXES(sc, d, aqrl)
/* `fence` arguments */
/* NOTE: Order is important */
DEF_ASM_FENCE(w)
DEF_ASM_FENCE(r)
DEF_ASM_FENCE(rw)
DEF_ASM_FENCE(o)
DEF_ASM_FENCE(ow)
DEF_ASM_FENCE(or)
DEF_ASM_FENCE(orw)
DEF_ASM_FENCE(i)
DEF_ASM_FENCE(iw)
DEF_ASM_FENCE(ir)
DEF_ASM_FENCE(irw)
DEF_ASM_FENCE(io)
DEF_ASM_FENCE(iow)
DEF_ASM_FENCE(ior)
DEF_ASM_FENCE(iorw)
#undef DEF_ASM_WITH_SUFFIX