Skip to content

Commit

Permalink
riscv: Add full fence instruction support
Browse files Browse the repository at this point in the history
This commit adds support for `fence`'s predecessor and successor
arguments.
  • Loading branch information
ekaitz-zarraga committed Apr 23, 2024
1 parent c994068 commit 671d03f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 4 deletions.
36 changes: 32 additions & 4 deletions riscv64-asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down
24 changes: 24 additions & 0 deletions riscv64-tok.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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

0 comments on commit 671d03f

Please sign in to comment.