Skip to content

Commit

Permalink
Feature: implemented privileged instructions in the RiscV disassembler.
Browse files Browse the repository at this point in the history
  • Loading branch information
uxmal committed Jan 19, 2024
1 parent 1c99ca2 commit b2011c9
Show file tree
Hide file tree
Showing 6 changed files with 422 additions and 57 deletions.
47 changes: 39 additions & 8 deletions src/Arch/RiscV/InstructionSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -501,19 +501,50 @@ public Decoder[] CreateRootDecoders()
Nyi("amo - 111"));

var system = Mask(12, 3, " system",
Sparse(20, 12, "system", // 0b11100
Sparse(25, 7, " system 000",
Nyi("system 000"),
(0, Instr(Mnemonic.ecall, InstrClass.Transfer | InstrClass.Call)),
(1, Instr(Mnemonic.ebreak, InstrClass.Terminates)),
(0b0000000_00010, Instr(Mnemonic.uret, InstrClass.Transfer | InstrClass.Return)),
(0b0001000_00010, Instr(Mnemonic.sret, InstrClass.Transfer | InstrClass.Return)),
(0b0011000_00010, Instr(Mnemonic.mret, InstrClass.Transfer | InstrClass.Return)),
(0b0001000_00101, Instr(Mnemonic.wfi, InstrClass.Linear))),
(0x00, Sparse(20, 5, " system 0x00", Nyi("system 0x00"),
(0, Instr(Mnemonic.ecall, InstrClass.Transfer | InstrClass.Call)),
(1, Instr(Mnemonic.ebreak, InstrClass.Terminates)),
(2, Instr(Mnemonic.uret, InstrClass.Transfer | InstrClass.Return)))),
(0x08, Sparse(20, 5, " system 0x08", Nyi("system 0x08"),
(2, Instr(Mnemonic.sret, InstrClass.Privileged | InstrClass.Transfer | InstrClass.Return)),
(5, Instr(Mnemonic.wfi, InstrClass.Privileged | InstrClass.Linear)))),
(0x09, Instr(Mnemonic.sfence_vma, InstrClass.Privileged | InstrClass.Linear, R2, Mem(PrimitiveType.Word32, 15))),
(0x0B, Instr(Mnemonic.sfence_inval, InstrClass.Privileged | InstrClass.Linear, Mem(PrimitiveType.Word32, 15))),
(0x0C, Sparse(20, 5, " system 0x0C", Nyi("system 0x0C"),
(0, Instr(Mnemonic.sfence_w_inval, InstrClass.Privileged | InstrClass.Linear)),
(1, Instr(Mnemonic.sfence_inval_ir, InstrClass.Privileged | InstrClass.Linear)))),
(0x11, Instr(Mnemonic.hfence_vvma, InstrClass.Privileged | InstrClass.Linear, R2, Mem(PrimitiveType.Word32, 15))),
(0x13, Instr(Mnemonic.hinval_vvma, InstrClass.Privileged | InstrClass.Linear, R2, Mem(PrimitiveType.Word32, 15))),
(0x31, Instr(Mnemonic.hfence_gvma, InstrClass.Privileged | InstrClass.Linear, R2, Mem(PrimitiveType.Word32, 15))),
(0x33, Instr(Mnemonic.hinval_gvma, InstrClass.Privileged | InstrClass.Linear, R2, Mem(PrimitiveType.Word32, 15))),

(0x18, Sparse(20, 5, " system 11000", Nyi("system 11000"),
(2, Instr(Mnemonic.mret, InstrClass.Privileged | InstrClass.Transfer | InstrClass.Return))))),

Instr(Mnemonic.csrrw, d, Csr20, r1),
Instr(Mnemonic.csrrs, d, Csr20, r1),
Instr(Mnemonic.csrrc, d, Csr20, r1),
invalid,
Sparse(25, 7, " system 100",
Nyi("system 100"),
(0x30, Sparse(20, 5, " system 0x30", Nyi("system 0x30"),
(0, Instr(Mnemonic.hlv_b, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.Int8, 15))),
(1, Instr(Mnemonic.hlv_bu, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.UInt8, 15))))),
(0x32, Sparse(20, 5, " system 0x32", Nyi("system 0x32"),
(0, Instr(Mnemonic.hlv_h, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.Int16, 15))),
(1, Instr(Mnemonic.hlv_hu, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.UInt16, 15))),
(3, Instr(Mnemonic.hlvx_hu, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.UInt16, 15))))),
(0x34, Sparse(20, 5, " system 0x34", Nyi("system 0x34"),
(0, Instr(Mnemonic.hlv_w, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.Int32, 15))),
(1, Instr(Mnemonic.hlv_wu, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.UInt32, 15))),
(3, Instr(Mnemonic.hlvx_wu, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.UInt32, 15))))),
(0x36, Sparse(20, 5, " system 0x36", Nyi("system 0x36"),
(0, Instr(Mnemonic.hlv_d, InstrClass.Privileged | InstrClass.Linear, Rd, Mem(PrimitiveType.UInt64, 15))))),
(0x31, Instr(Mnemonic.hsv_b, InstrClass.Privileged | InstrClass.Linear, Mem(PrimitiveType.Byte, 15), R2)),
(0x33, Instr(Mnemonic.hsv_h, InstrClass.Privileged | InstrClass.Linear, Mem(PrimitiveType.Word16, 15), R2)),
(0x35, Instr(Mnemonic.hsv_w, InstrClass.Privileged | InstrClass.Linear, Mem(PrimitiveType.Word32, 15), R2)),
(0x37, Instr(Mnemonic.hsv_d, InstrClass.Privileged | InstrClass.Linear, Mem(PrimitiveType.Word64, 15), R2))),
Instr(Mnemonic.csrrwi, d, Csr20, Imm(15, 5)),
Instr(Mnemonic.csrrsi, d, Csr20, Imm(15, 5)),
Instr(Mnemonic.csrrci, d, Csr20, Imm(15, 5)));
Expand Down
22 changes: 22 additions & 0 deletions src/Arch/RiscV/Mnemonic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,5 +287,27 @@ public enum Mnemonic
wfi,
xor,
xori,
sfence_vma,
sfence_inval,
sfence_w_inval,
sfence_inval_ir,
hfence_vvma,
hinval_vvma,
hfence_gvma,
hinval_gvma,

hlv_b,
hlv_bu,
hlv_h,
hlv_hu,
hlvx_hu,
hlv_w,
hlvx_wu,
hsv_b,
hsv_h,
hsv_w,
hsv_d,
hlv_wu,
hlv_d,
}
}
6 changes: 6 additions & 0 deletions src/Arch/RiscV/RiscVDisassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,19 @@ public override RiscVInstruction CreateInvalidInstruction()
};
}

/// <summary>
/// Register encoded at bit position 15
/// </summary>
private static bool r1(uint wInstr, RiscVDisassembler dasm)
{
var op = dasm.GetRegister(wInstr, 15);
dasm.state.ops.Add(op);
return true;
}

/// <summary>
/// Register encoded at bit position 20
/// </summary>
private static bool r2(uint wInstr, RiscVDisassembler dasm)
{
var op = dasm.GetRegister(wInstr, 20);
Expand Down
192 changes: 159 additions & 33 deletions src/UnitTests/Arch/RiscV/RiscVDisassemblerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
using Reko.Core.Machine;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Reflection.PortableExecutable;
using System.Security.Cryptography;

namespace Reko.UnitTests.Arch.RiscV
{
Expand All @@ -35,15 +37,14 @@ public class RiscVDisassemblerTests : DisassemblerTestBase<RiscVInstruction>

public RiscVDisassemblerTests()
{
Reko.Core.Machine.Decoder.trace.Level = System.Diagnostics.TraceLevel.Verbose;
}

[SetUp]
public void Setup()
{
this.arch = new RiscVArchitecture(
new ServiceContainer(),
"riscV",
"riscV",
new Dictionary<string, object>
{
{ ProcessorOption.WordSize, "64" },
Expand Down Expand Up @@ -760,35 +761,160 @@ public void RiscV_dasm_sllw()
[Test]
public void RiscV_dasm_regressions1()
{

AssertCode("fence.i", "0f100000"); // invalid
AssertCode("csrrw\ts2,00000315,t0", "73995231"); // invalid
AssertCode("csrrs\ta1,sstatus,a5", "f3a50710"); // csrrs a1,sstatus,a5
AssertCode("csrrc\ttp,000005F0,s0", "7332045f"); // invalid
AssertCode("csrrc\ttp,000005F0,zero", "7332005f"); // invalid
AssertCode("csrrsi\ts2,000006E6,0000001E", "73696f6e"); // invalid
AssertCode("csrrci\ts0,000006A5,0000001A", "73745d6a"); // invalid
AssertCode("mul\ta0,s5,s7", "33857a03"); // add a0,s5,s7
AssertCode("mulh\tt5,a7,s1", "339f9802"); // sll t5,a7,s1
AssertCode("mulhsu\tt3,sp,a6", "332e0103"); // slt t3,sp,a6
AssertCode("mulhu\tt3,sp,a6", "333e0103"); // sltu t3,sp,a6
AssertCode("mulhsu\tt3,sp,a6", "332e0103"); // slt t3,sp,a6
AssertCode("divu\tt4,t3,t2", "b35e7e02"); // srl t4,t3,t2
AssertCode("rem\ta4,a1,a2", "33e7c502"); // or a4,a1,a2
AssertCode("remu\ta6,a1,t2", "33f87502"); // and a6,a1,t2
AssertCode("fsw\tfs1,72(a1)", "27a49504"); // fsw fs1,288(a1)
AssertCode("fmadd.s\tfs10,ft10,ft5,fa0,rmm", "434d5f50"); // fmadd.s fs10,ft10,ft5,fa0
AssertCode("fmsub.s\tft8,ft10,fs11,ft7,rdn", "472ebf39"); // fmsub.s ft8,ft10,fs11,ft7
AssertCode("fnmsub.s\tfs7,fa4,fs3,fs0,rne", "cb0b3741"); // fnmsub.s fs7,fa4,fs3,fs0
AssertCode("fnmadd.s\tfa4,ft4,fs5,fs0,rmm", "4f475241"); // fnmadd.s fa4,ft4,fs5,fs0
AssertCode("fclass.s\ta3,fa2", "d31606e0"); // fmv.x.w a3,fa2
AssertCode("fsd\tfs4,312(sp)", "273c4113"); // fsd fs4,2496(a0)
AssertCode("fmsub.d\tft0,ft0,fs0,fa6,rne", "47008082"); // fmsub.s ft0,ft0,fs0,fa6
AssertCode("fnmsub.d\tfs0,ft4,ft2,fa5,rdn", "4b24227a"); // fnmsub.s fs0,ft4,ft2,fa5
AssertCode("fnmadd.d\tfa2,ft10,ft5,fa0,rmm", "4f465f52"); // fnmadd.s fa2,ft10,ft5,fa0
AssertCode("fcvt.l.d\tra,ft1,rtz", "d39020c2"); // fcvt.l.d ra,ft1
AssertCode("fcvt.lu.d\ta0,fa3,rtz", "539536c2"); // fcvt.lu.d a0,fa3
}


AssertCode("fence.i", "0f100000"); // invalid
AssertCode("csrrw\ts2,00000315,t0", "73995231"); // invalid
AssertCode("csrrs\ta1,sstatus,a5", "f3a50710"); // csrrs a1,sstatus,a5
AssertCode("csrrc\ttp,000005F0,s0", "7332045f"); // invalid
AssertCode("csrrc\ttp,000005F0,zero", "7332005f"); // invalid
AssertCode("csrrsi\ts2,000006E6,0000001E", "73696f6e"); // invalid
AssertCode("csrrci\ts0,000006A5,0000001A", "73745d6a"); // invalid
AssertCode("mul\ta0,s5,s7", "33857a03"); // add a0,s5,s7
AssertCode("mulh\tt5,a7,s1", "339f9802"); // sll t5,a7,s1
AssertCode("mulhsu\tt3,sp,a6", "332e0103"); // slt t3,sp,a6
AssertCode("mulhu\tt3,sp,a6", "333e0103"); // sltu t3,sp,a6
AssertCode("mulhsu\tt3,sp,a6", "332e0103"); // slt t3,sp,a6
AssertCode("divu\tt4,t3,t2", "b35e7e02"); // srl t4,t3,t2
AssertCode("rem\ta4,a1,a2", "33e7c502"); // or a4,a1,a2
AssertCode("remu\ta6,a1,t2", "33f87502"); // and a6,a1,t2
AssertCode("fsw\tfs1,72(a1)", "27a49504"); // fsw fs1,288(a1)
AssertCode("fmadd.s\tfs10,ft10,ft5,fa0,rmm", "434d5f50"); // fmadd.s fs10,ft10,ft5,fa0
AssertCode("fmsub.s\tft8,ft10,fs11,ft7,rdn", "472ebf39"); // fmsub.s ft8,ft10,fs11,ft7
AssertCode("fnmsub.s\tfs7,fa4,fs3,fs0,rne", "cb0b3741"); // fnmsub.s fs7,fa4,fs3,fs0
AssertCode("fnmadd.s\tfa4,ft4,fs5,fs0,rmm", "4f475241"); // fnmadd.s fa4,ft4,fs5,fs0
AssertCode("fclass.s\ta3,fa2", "d31606e0"); // fmv.x.w a3,fa2
AssertCode("fsd\tfs4,312(sp)", "273c4113"); // fsd fs4,2496(a0)
AssertCode("fmsub.d\tft0,ft0,fs0,fa6,rne", "47008082"); // fmsub.s ft0,ft0,fs0,fa6
AssertCode("fnmsub.d\tfs0,ft4,ft2,fa5,rdn", "4b24227a"); // fnmsub.s fs0,ft4,ft2,fa5
AssertCode("fnmadd.d\tfa2,ft10,ft5,fa0,rmm", "4f465f52"); // fnmadd.s fa2,ft10,ft5,fa0
AssertCode("fcvt.l.d\tra,ft1,rtz", "d39020c2"); // fcvt.l.d ra,ft1
AssertCode("fcvt.lu.d\ta0,fa3,rtz", "539536c2"); // fcvt.lu.d a0,fa3
}

[Test]
public void RiscV_dasm_sret()
{
AssertCode("sret", 0b0001000_00010_00000_000_00000_1110011);
}

[Test]
public void RiscV_dasm_sfence_vma()
{
AssertCode("sfence.vma\ts5,0(s11)", 0b0001001_10101_11011_000_00000_1110011);
}

[Test]
public void RiscV_dasm_sfence_w_inval()
{
AssertCode("sfence.w.inval", 0b0001100_00000_00000_000_00000_1110011);
}

[Test]
public void RiscV_dasm_sfence_inval_ir()
{
AssertCode("sfence.inval.ir", 0b0001100_00001_00000_000_00000_1110011);
}

[Test]
public void RiscV_dasm_hfence_vvma()
{
AssertCode("hfence.vvma\ts5,0(a7)", 0b0010001_10101_10001_000_00000_1110011);
}

[Test]
public void RiscV_dasm_hfence_gvma()
{
AssertCode("hfence.gvma\ts5,0(a7)", 0b0110001_10101_10001_000_00000_1110011);
}

[Test]
public void RiscV_dasm_hinval_vvma()
{
AssertCode("hinval.vvma\ts5,0(a7)", 0b0010011_10101_10001_000_00000_1110011);
}

[Test]
public void RiscV_dasm_hinval_gvma()
{
AssertCode("hinval.gvma\ts5,0(a7)", 0b0110011_10101_10001_000_00000_1110011);
}

[Test]
public void RiscV_dasm_hlv_b()
{
AssertCode("hlv.b\ts11,0(a7)", 0b0110000_00000_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hlv_bu()
{
AssertCode("hlv.bu\ts11,0(a7)", 0b0110000_00001_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hlv_h()
{
AssertCode("hlv.h\ts11,0(a7)", 0b0110010_00000_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hlv_hu()
{
AssertCode("hlv.hu\ts11,0(a7)", 0b0110010_00001_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hlvx_hu()
{
AssertCode("hlvx.hu\ts11,0(a7)", 0b0110010_00011_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hlv_w()
{
AssertCode("hlv.w\ts11,0(a7)", 0b0110100_00000_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hlvx_wu()
{
AssertCode("hlvx.wu\ts11,0(a7)", 0b0110100_00011_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hsv_b()
{
AssertCode("hsv.b\t0(a7),s5", 0b0110001_10101_10001_100_00000_1110011);
}

[Test]
public void RiscV_dasm_hsv_h()
{
AssertCode("hsv.h\t0(a7),s5", 0b0110011_10101_10001_100_00000_1110011);
}

[Test]
public void RiscV_dasm_hsv_w()
{
AssertCode("hsv.w\t0(a7),s5", 0b0110101_10101_10001_100_00000_1110011);
}

[Test]
public void RiscV_dasm_hlv_wu()
{
AssertCode("hlv.wu\ts11,0(a7)", 0b0110100_00001_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hlv_d()
{
AssertCode("hlv.d\ts11,0(a7)", 0b0110110_00000_10001_100_11011_1110011);
}

[Test]
public void RiscV_dasm_hsv_d()
{
AssertCode("hsv.d\t0(a7),s5", 0b0110111_10101_10001_100_00000_1110011);
}
}
}
}
Loading

0 comments on commit b2011c9

Please sign in to comment.