diff --git a/src/decode.c b/src/decode.c index ac65d3db..71990cc9 100644 --- a/src/decode.c +++ b/src/decode.c @@ -908,25 +908,35 @@ static inline bool op_system(rv_insn_t *ir, const uint32_t insn) return true; } -#if RV32_HAS(Zifencei) /* MISC-MEM: I-type * 31 20 19 15 14 12 11 7 6 0 * | imm[11:0] | rs1 | funct3 | rd | opcode | */ -static inline bool op_misc_mem(rv_insn_t *ir, const uint32_t insn UNUSED) +static inline bool op_misc_mem(rv_insn_t *ir, const uint32_t insn) { - /* inst imm[11:0] rs1 funct3 rd opcode - * ------+---------+---+------+--+------- - * FENCEI imm[11:0] rs1 001 rd 0001111 + /* inst fm pred succ rs1 funct3 rd opcode + * ------+---------+----------+-----------+-----+-------+----+------- + * FENCE FM[3:0] pred[3:0] succ[3:0] rs1 000 rd 0001111 + * FENCEI imm[11:0] rs1 001 rd 0001111 */ - /* FIXME: fill real implementations */ - ir->opcode = rv_insn_fencei; - return true; + const uint32_t funct3 = decode_funct3(insn); + + switch (funct3) { + case 0b000: + ir->opcode = rv_insn_fence; + return true; +#if RV32_HAS(Zifencei) + case 0b001: + ir->opcode = rv_insn_fencei; + return true; +#endif /* RV32_HAS(Zifencei) */ + default: /* illegal instruction */ + return false; + } + + return false; } -#else -#define op_misc_mem OP_UNIMP -#endif /* RV32_HAS(Zifencei) */ #if RV32_HAS(EXT_A) /* AMO: R-type diff --git a/src/decode.h b/src/decode.h index 4ff38b6e..6af8ef2e 100644 --- a/src/decode.h +++ b/src/decode.h @@ -72,6 +72,7 @@ enum op_field { _(sra, 0, 4, 1, ENC(rs1, rs2, rd)) \ _(or, 0, 4, 1, ENC(rs1, rs2, rd)) \ _(and, 0, 4, 1, ENC(rs1, rs2, rd)) \ + _(fence, 1, 4, 0, ENC(rs1, rd)) \ _(ecall, 1, 4, 1, ENC(rs1, rd)) \ _(ebreak, 1, 4, 1, ENC(rs1, rd)) \ /* RISC-V Privileged Instruction */ \ diff --git a/src/rv32_constopt.c b/src/rv32_constopt.c index adc35dee..9ae5a4e3 100644 --- a/src/rv32_constopt.c +++ b/src/rv32_constopt.c @@ -356,6 +356,12 @@ CONSTOPT(and, { info->is_constant[ir->rd] = false; }) +/* + * FENCE: order device I/O and memory accesses as viewed by other + * RISC-V harts and external devices or coprocessors + */ +CONSTOPT(fence, {}) + /* ECALL: Environment Call */ CONSTOPT(ecall, {}) diff --git a/src/rv32_template.c b/src/rv32_template.c index cf66ced6..03a1273c 100644 --- a/src/rv32_template.c +++ b/src/rv32_template.c @@ -927,6 +927,21 @@ RVOP( })) /* clang-format on */ +/* + * FENCE: order device I/O and memory accesses as viewed by other + * RISC-V harts and external devices or coprocessors + */ +RVOP( + fence, + { + PC += 4; + /* FIXME: fill real implementations */ + goto end_op; + }, + GEN({ + assert; /* FIXME: Implement */ + })) + /* ECALL: Environment Call */ RVOP( ecall, diff --git a/src/t2c_template.c b/src/t2c_template.c index 1ce4dd78..864cb641 100644 --- a/src/t2c_template.c +++ b/src/t2c_template.c @@ -281,6 +281,8 @@ T2C_OP(and, { LLVMBuildStore(*builder, res, t2c_gen_rd_addr(start, builder, ir)); }) +T2C_OP(fence, { __UNREACHABLE; }) + T2C_OP(ecall, { T2C_LLVM_GEN_STORE_IMM32(*builder, ir->pc, t2c_gen_PC_addr(start, builder, ir));