Skip to content

Commit 50bc9d8

Browse files
committed
Add RV32I memory ordering instruction FENCE
The RV32I memory ordering instruction FENCE is used to order device I/O and memory accesses as viewed by other RISC-V harts and external devices or coprocessors. Linux kernel leverage this instruction for synchronization, support emulating this instruction is needed to boot Linux kernel. The implemention of this instruction is straight forward since there is only single hart at present. Related: #310
1 parent 4bb8593 commit 50bc9d8

File tree

5 files changed

+45
-11
lines changed

5 files changed

+45
-11
lines changed

src/decode.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -908,25 +908,35 @@ static inline bool op_system(rv_insn_t *ir, const uint32_t insn)
908908
return true;
909909
}
910910

911-
#if RV32_HAS(Zifencei)
912911
/* MISC-MEM: I-type
913912
* 31 20 19 15 14 12 11 7 6 0
914913
* | imm[11:0] | rs1 | funct3 | rd | opcode |
915914
*/
916-
static inline bool op_misc_mem(rv_insn_t *ir, const uint32_t insn UNUSED)
915+
static inline bool op_misc_mem(rv_insn_t *ir, const uint32_t insn)
917916
{
918-
/* inst imm[11:0] rs1 funct3 rd opcode
919-
* ------+---------+---+------+--+-------
920-
* FENCEI imm[11:0] rs1 001 rd 0001111
917+
/* inst fm pred succ rs1 funct3 rd opcode
918+
* ------+---------+----------+-----------+-----+-------+----+-------
919+
* FENCE FM[3:0] pred[3:0] succ[3:0] rs1 000 rd 0001111
920+
* FENCEI imm[11:0] rs1 001 rd 0001111
921921
*/
922922

923-
/* FIXME: fill real implementations */
924-
ir->opcode = rv_insn_fencei;
925-
return true;
923+
const uint32_t funct3 = decode_funct3(insn);
924+
925+
switch (funct3) {
926+
case 0b000:
927+
ir->opcode = rv_insn_fence;
928+
return true;
929+
#if RV32_HAS(Zifencei)
930+
case 0b001:
931+
ir->opcode = rv_insn_fencei;
932+
return true;
933+
#endif /* RV32_HAS(Zifencei) */
934+
default: /* illegal instruction */
935+
return false;
936+
}
937+
938+
return false;
926939
}
927-
#else
928-
#define op_misc_mem OP_UNIMP
929-
#endif /* RV32_HAS(Zifencei) */
930940

931941
#if RV32_HAS(EXT_A)
932942
/* AMO: R-type

src/decode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ enum op_field {
7272
_(sra, 0, 4, 1, ENC(rs1, rs2, rd)) \
7373
_(or, 0, 4, 1, ENC(rs1, rs2, rd)) \
7474
_(and, 0, 4, 1, ENC(rs1, rs2, rd)) \
75+
_(fence, 1, 4, 0, ENC(rs1, rd)) \
7576
_(ecall, 1, 4, 1, ENC(rs1, rd)) \
7677
_(ebreak, 1, 4, 1, ENC(rs1, rd)) \
7778
/* RISC-V Privileged Instruction */ \

src/rv32_constopt.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,12 @@ CONSTOPT(and, {
356356
info->is_constant[ir->rd] = false;
357357
})
358358

359+
/*
360+
* FENCE: order device I/O and memory accesses as viewed by other
361+
* RISC-V harts and external devices or coprocessors
362+
*/
363+
CONSTOPT(fence, {})
364+
359365
/* ECALL: Environment Call */
360366
CONSTOPT(ecall, {})
361367

src/rv32_template.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,21 @@ RVOP(
927927
}))
928928
/* clang-format on */
929929

930+
/*
931+
* FENCE: order device I/O and memory accesses as viewed by other
932+
* RISC-V harts and external devices or coprocessors
933+
*/
934+
RVOP(
935+
fence,
936+
{
937+
PC += 4;
938+
/* FIXME: fill real implementations */
939+
goto end_op;
940+
},
941+
GEN({
942+
assert; /* FIXME: Implement */
943+
}))
944+
930945
/* ECALL: Environment Call */
931946
RVOP(
932947
ecall,

src/t2c_template.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ T2C_OP(and, {
281281
LLVMBuildStore(*builder, res, t2c_gen_rd_addr(start, builder, ir));
282282
})
283283

284+
T2C_OP(fence, { __UNREACHABLE; })
285+
284286
T2C_OP(ecall, {
285287
T2C_LLVM_GEN_STORE_IMM32(*builder, ir->pc,
286288
t2c_gen_PC_addr(start, builder, ir));

0 commit comments

Comments
 (0)