Skip to content

Commit 0946a98

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 0946a98

File tree

4 files changed

+44
-7
lines changed

4 files changed

+44
-7
lines changed

src/decode.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -908,25 +908,40 @@ 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
{
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+
*/
921+
922+
const uint32_t funct3 = decode_funct3(insn);
923+
924+
switch (funct3) {
925+
case 0b000:
926+
ir->opcode = rv_insn_fence;
927+
return true;
928+
#if RV32_HAS(Zifencei)
918929
/* inst imm[11:0] rs1 funct3 rd opcode
919930
* ------+---------+---+------+--+-------
920931
* FENCEI imm[11:0] rs1 001 rd 0001111
921932
*/
922933

923934
/* FIXME: fill real implementations */
924-
ir->opcode = rv_insn_fencei;
925-
return true;
935+
case 0b001:
936+
ir->opcode = rv_insn_fencei;
937+
return true;
938+
#endif /* RV32_HAS(Zifencei) */
939+
default: /* illegal instruction */
940+
return false;
941+
}
942+
943+
return false;
926944
}
927-
#else
928-
#define op_misc_mem OP_UNIMP
929-
#endif /* RV32_HAS(Zifencei) */
930945

931946
#if RV32_HAS(EXT_A)
932947
/* 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,

0 commit comments

Comments
 (0)