Skip to content

Instantly share code, notes, and snippets.

@X547
Last active September 24, 2022 02:08
Show Gist options
  • Save X547/9da7300ae6414a53868f656f0d08fb2a to your computer and use it in GitHub Desktop.
Save X547/9da7300ae6414a53868f656f0d08fb2a to your computer and use it in GitHub Desktop.
RISC-V disassembler for Oberon (Component Pascal)
MODULE WorkDecRISCV;
IMPORT WorkDecoders;
TYPE
Decoder = POINTER TO RECORD (WorkDecoders.Decoder)
name: WorkDecoders.Name;
END;
VAR
dec-: WorkDecoders.Decoder;
pcRelReg: INTEGER;
pcRelRegVal: LONGINT;
PROCEDURE (dec: Decoder) Decode* (h: WorkDecoders.Handler);
VAR
newLine, keepPcRelReg: BOOLEAN;
i, opLen: INTEGER;
pc0: LONGINT;
op: ARRAY 12 OF SHORTINT;
op2: INTEGER;
rd, rs1, rs2, rs3, fn3, fn7, imm: INTEGER;
argSize: INTEGER;
PROCEDURE Next(): BYTE;
VAR b: BYTE;
BEGIN
b := h.Get(); INC(h.adr);
RETURN b
END Next;
PROCEDURE ReadSInt (VAR val: SHORTINT);
BEGIN
val := SHORT(Next() MOD 100H);
val := SHORT(val + 100H*Next());
END ReadSInt;
PROCEDURE WriteHex(x: LONGINT; n: INTEGER);
BEGIN
IF n > 1 THEN WriteHex(x DIV 16, n-1) END;
x := x MOD 16;
IF x <= 9 THEN h.Put(CHR(x + ORD("0")))
ELSE h.Put(CHR(x -10 + ORD("A")))
END
END WriteHex;
PROCEDURE WriteString (s: ARRAY OF CHAR);
VAR i: INTEGER;
BEGIN
i := 0; WHILE s[i] # 0X DO h.Put(s[i]); INC(i) END
END WriteString;
PROCEDURE WriteInt (x: INTEGER);
BEGIN
IF x = MIN(INTEGER) THEN WriteString("-2147483648")
ELSIF x < 0 THEN h.Put("-"); WriteInt(-x)
ELSE
IF x > 9 THEN WriteInt(x DIV 10) END;
h.Put(CHR(x MOD 10 + ORD("0")))
END
END WriteInt;
PROCEDURE WriteChar(ch: CHAR);
BEGIN
IF (ch >= " ") & (ch < 7FX) THEN h.Put(ch)
ELSE h.Put(".")
END
END WriteChar;
PROCEDURE WriteUndef;
BEGIN
WriteString("*****")
END WriteUndef;
PROCEDURE WriteAdr (adr: LONGINT);
BEGIN IF h.PutAdr(adr MOD ASH(1, 32), dec.name) THEN WriteString(dec.name) ELSE h.Put("$"); WriteHex(adr, 8) END;
END WriteAdr;
PROCEDURE WriteReg (r: INTEGER);
BEGIN
CASE r OF
| 0: WriteString("0")
| 1: WriteString("RA")
| 2: WriteString("SP")
| 3: WriteString("GP")
| 4: WriteString("TP")
| 5..7: WriteString("T"); WriteInt(r - 5)
| 8: WriteString("FP")
| 9: WriteString("S1")
| 10..17: WriteString("A"); WriteInt(r - 10)
| 18..27: WriteString("S"); WriteInt(r + 2 - 18)
| 28..31: WriteString("T"); WriteInt(r + 3 - 28)
END;
END WriteReg;
PROCEDURE WriteFloatReg (r: INTEGER);
BEGIN
CASE r OF
| 0..7: WriteString("FT"); WriteInt(r)
| 8..9: WriteString("FS"); WriteInt(r - 8)
| 10..17: WriteString("FA"); WriteInt(r - 10)
| 18..27: WriteString("FS"); WriteInt(r + 2 - 18)
| 28..31: WriteString("FT"); WriteInt(r + 8 - 28)
END;
END WriteFloatReg;
PROCEDURE WriteCsrReg (r: INTEGER);
BEGIN
CASE r OF
| 0: WriteString("USTATUS")
| 4: WriteString("UIE")
| 5: WriteString("UTVEC")
| 1: WriteString("FFLAGS")
| 2: WriteString("FRM")
| 3: WriteString("FCSR")
| 40H: WriteString("USCRATCH")
| 41H: WriteString("UEPC")
| 42H: WriteString("UCAUSE")
| 43H: WriteString("UTVAL")
| 44H: WriteString("UIP")
| 0C00H: WriteString("CYCLE")
| 0C01H: WriteString("TIME")
| 0C02H: WriteString("INSTRET")
| 0C03H .. 0C1FH: WriteString("HPMCOUNTER"); WriteInt(r - 0C00H)
| 0C80H: WriteString("CYCLEH")
| 0C81H: WriteString("TIMEH")
| 0C82H: WriteString("INSTRETH")
| 0C83H .. 0C9FH: WriteString("HPMCOUNTER"); WriteInt(r - 0C80H); WriteString("H")
| 100H: WriteString("SSTATUS")
| 102H: WriteString("SEDELEG")
| 103H: WriteString("SIDELEG")
| 104H: WriteString("SIE")
| 105H: WriteString("STVEC")
| 106H: WriteString("SCOUNTEREN")
| 140H: WriteString("SSCRATCH")
| 141H: WriteString("SEPC")
| 142H: WriteString("SCAUSE")
| 143H: WriteString("STVAL")
| 144H: WriteString("SIP")
| 180H: WriteString("SATP")
| 0F11H: WriteString("MVENDORID")
| 0F12H: WriteString("MARCHID")
| 0F13H: WriteString("MIMPID")
| 0F14H: WriteString("MHARTID")
| 0300H: WriteString("MSTATUS")
| 0301H: WriteString("MISA")
| 0302H: WriteString("MEDELEG")
| 0303H: WriteString("MIDELEG")
| 0304H: WriteString("MIE")
| 0305H: WriteString("MTVEC")
| 0306H: WriteString("MCOUNTEREN")
| 0340H: WriteString("MSCRATCH")
| 0341H: WriteString("MEPC")
| 0342H: WriteString("MCAUSE")
| 0343H: WriteString("MTVAL")
| 0344H: WriteString("MIP")
| 03A0H .. 03A3H: WriteString("PMPCFG"); WriteInt(r - 3A0H)
| 03B0H .. 03BFH: WriteString("PMPADDR"); WriteInt(r - 3B0H)
| 0B00H: WriteString("MCYCLE")
| 0B02H: WriteString("MINSTRET")
| 0B03H .. 0B1FH: WriteString("MHPMCOUNTER"); WriteInt(r - 0B00H)
| 0B80H: WriteString("MCYCLEH")
| 0B82H: WriteString("MINSTRETH")
| 0B83H .. 0B9FH: WriteString("MHPMCOUNTER"); WriteInt(r - 0B00H); WriteString("H")
| 0320H: WriteString("MCOUNTINHIBIT");
| 0323H .. 033FH: WriteString("MHPMEVENT"); WriteInt(r - 0320H)
| 07A0H: WriteString("TSELECT")
| 07A1H .. 07A3H: WriteString("TDATA"); WriteInt(r - 07A0H)
| 07B0H: WriteString("DCSR");
| 07B1H: WriteString("DPC");
| 07B2H .. 07B3H: WriteString("DSCRATCH"); WriteInt(r - 07B2H)
ELSE WriteString("CSR"); WriteInt(r) END;
END WriteCsrReg;
PROCEDURE SignExtend (val: INTEGER; bitCnt: INTEGER): INTEGER;
BEGIN
RETURN (val + ASH(1, bitCnt - 1)) MOD ASH(1, bitCnt) - ASH(1, bitCnt - 1);
END SignExtend;
PROCEDURE Write(s: ARRAY OF CHAR);
VAR ch: CHAR; i, a, c: INTEGER;
PROCEDURE WriteRegExpr (r: INTEGER);
BEGIN
CASE s[i+1] OF
| "f": INC(i); WriteFloatReg(r)
| "c": INC(i); WriteCsrReg(r)
| "i": INC(i); IF pcRelReg = r THEN WriteAdr(pcRelRegVal + imm) ELSE WriteInt(imm); h.Put("("); WriteReg(r); h.Put(")") END;
ELSE WriteReg(r) END;
END WriteRegExpr;
BEGIN
i := 0; ch := s[0];
WHILE ch # 0X DO
CASE ch OF
| "i": CASE s[i+1] OF "h": INC(i); h.Put("$"); WriteHex(imm, 8) ELSE WriteInt(imm) END
| "p": WriteAdr(pc0 + imm)
| "s": WriteRegExpr(rs1)
| "t": WriteRegExpr(rs2)
| "u": WriteRegExpr(rs3)
| "d": WriteRegExpr(rd)
| "a": (* argSize *)
CASE s[i+1] OF
| "f": INC(i); (* float *)
CASE argSize OF
| 0: h.Put("S") (* 32 bit *)
| 1: h.Put("D") (* 64 bit *)
| 2: h.Put("H") (* 16 bit *)
| 3: h.Put("Q") (* 128 bit *)
ELSE WriteString("?("); WriteInt(argSize); WriteString(")") END;
ELSE (* integer *)
CASE argSize OF
| -1: (* nothing *)
| 0: h.Put("B") (* 8 bit *)
| 1: h.Put("H") (* 16 bit *)
| 2: h.Put("W") (* 32 bit *)
| 3: h.Put("D") (* 64 bit *)
| 4: WriteString("BU") (* 8 bit unsigned *)
| 5: WriteString("HU") (* 16 bit unsigned *)
| 6: WriteString("WU") (* 32 bit unsigned *)
ELSE WriteString("?("); WriteInt(argSize); WriteString(")") END;
END;
ELSE h.Put(ch)
END;
INC(i); ch := s[i]
END
END Write;
PROCEDURE R;
BEGIN
rd := op2 DIV ASH(1, 7) MOD ASH(1, 12 - 7);
fn3 := op2 DIV ASH(1, 12) MOD ASH(1, 15 - 12);
rs1 := op2 DIV ASH(1, 15) MOD ASH(1, 20 - 15);
rs2 := op2 DIV ASH(1, 20) MOD ASH(1, 25 - 20);
fn7 := op2 DIV ASH(1, 25) MOD ASH(1, 32 - 25);
END R;
PROCEDURE R4;
BEGIN
R;
rs3 := fn7 DIV ASH(1, 2);
fn7 := fn7 MOD ASH(1, 2);
END R4;
PROCEDURE I;
BEGIN
rd := op2 DIV ASH(1, 7) MOD ASH(1, 12 - 7);
fn3 := op2 DIV ASH(1, 12) MOD ASH(1, 15 - 12);
rs1 := op2 DIV ASH(1, 15) MOD ASH(1, 20 - 15);
imm := SignExtend(op2 DIV ASH(1, 20) MOD ASH(1, 12), 12);
END I;
PROCEDURE S;
BEGIN
fn3 := op2 DIV ASH(1, 12) MOD ASH(1, 15 - 12);
rs1 := op2 DIV ASH(1, 15) MOD ASH(1, 20 - 15);
rs2 := op2 DIV ASH(1, 20) MOD ASH(1, 25 - 20);
imm := SignExtend(
op2 DIV ASH(1, 7) MOD ASH(1, 5) +
op2 DIV ASH(1, 25) MOD ASH(1, 7) * ASH(1, 5)
, 12);
END S;
PROCEDURE B;
BEGIN
fn3 := op2 DIV ASH(1, 12) MOD ASH(1, 15 - 12);
rs1 := op2 DIV ASH(1, 15) MOD ASH(1, 20 - 15);
rs2 := op2 DIV ASH(1, 20) MOD ASH(1, 25 - 20);
imm := SignExtend(SHORT(
op2 DIV ASH(1, 7) MOD ASH(1, 1) * ASH(1, 11) +
op2 DIV ASH(1, 8) MOD ASH(1, 4) * ASH(1, 1) +
op2 DIV ASH(1, 25) MOD ASH(1, 6) * ASH(1, 5) +
op2 DIV ASH(1, 31) MOD ASH(1, 1) * ASH(1, 12)
), 13);
END B;
PROCEDURE U;
BEGIN
rd := op2 DIV ASH(1, 7) MOD ASH(1, 12 - 7);
imm := op2 DIV ASH(1, 12) MOD ASH(1, 32 - 12) * ASH(1, 12);
END U;
PROCEDURE J;
BEGIN
rd := op2 DIV ASH(1, 7) MOD ASH(1, 12 - 7);
imm := SignExtend(SHORT(
op2 DIV ASH(1, 21) MOD ASH(1, 10) * ASH(1, 1) +
op2 DIV ASH(1, 20) MOD ASH(1, 1) * ASH(1, 11) +
op2 DIV ASH(1, 12) MOD ASH(1, 8) * ASH(1, 12) +
op2 DIV ASH(1, 31) MOD ASH(1, 1) * ASH(1, 20)
), 21)
END J;
PROCEDURE Op1;
BEGIN
CASE op[0] MOD ASH(1, 2) OF
| 0:
CASE op[0] DIV ASH(1, 13) MOD ASH(1, 3) OF
| 0:
rd := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
rs1 := 2; (* SP *)
imm :=
op[0] DIV ASH(1, 5) MOD ASH(1, 1) * ASH(1, 3) +
op[0] DIV ASH(1, 6) MOD ASH(1, 1) * ASH(1, 2) +
op[0] DIV ASH(1, 7) MOD ASH(1, 4) * ASH(1, 6) +
op[0] DIV ASH(1, 11) MOD ASH(1, 2) * ASH(1, 4);
IF pcRelReg = rs1 THEN Write("LI d, si") ELSIF op[0] = 0 THEN Write("ILLINSTR") ELSE Write("ADDI d, s, i") END;
| 1:
CASE h.mode OF
| 0, 1:
rd := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 6) +
op[0] DIV ASH(1, 10) MOD ASH(1, 3) * ASH(1, 3);
Write("FLD df, si")
| 2: Write("LQ ?")
END
| 2:
rd := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 5) MOD ASH(1, 1) * ASH(1, 2) +
op[0] DIV ASH(1, 6) MOD ASH(1, 1) * ASH(1, 6) +
op[0] DIV ASH(1, 10) MOD ASH(1, 3) * ASH(1, 3);
Write("LW d, si")
| 3:
CASE h.mode OF
| 0:
rd := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 5) MOD ASH(1, 1) * ASH(1, 2) +
op[0] DIV ASH(1, 6) MOD ASH(1, 1) * ASH(1, 6) +
op[0] DIV ASH(1, 10) MOD ASH(1, 3) * ASH(1, 3);
Write("FLW df, si")
| 1, 2:
rd := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 6) +
op[0] DIV ASH(1, 10) MOD ASH(1, 3) * ASH(1, 3);
Write("LD d, si")
END
| 5:
CASE h.mode OF
| 0, 1:
rs2 := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 6) +
op[0] DIV ASH(1, 10) MOD ASH(1, 3) * ASH(1, 3);
Write("FSD sf, ti")
| 2: Write("SQ ?")
END
| 6:
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
rs2 := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
imm := (
op[0] DIV ASH(1, 5) MOD ASH(1, 1) +
op[0] DIV ASH(1, 10) MOD ASH(1, 3) * ASH(1, 1) +
op[0] DIV ASH(1, 6) MOD ASH(1, 1) * ASH(1, 4)
)*4;
Write("SW t, si")
| 7:
CASE h.mode OF
| 0: Write("FSW ?")
| 1, 2:
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
rs2 := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 10) MOD ASH(1, 3) +
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 3);
Write("SD t, si")
END
ELSE WriteUndef END;
| 1:
CASE op[0] DIV ASH(1, 13) MOD ASH(1, 3) OF
| 0:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 5) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1)*ASH(1, 5), 6);
IF rd = 0 THEN
Write("NOP")
ELSE
IF rd = pcRelReg THEN Write("LI d, di") ELSE Write("ADDI d, d, i") END
END;
| 1:
CASE h.mode OF
| 0:
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 1)*ASH(1, 5) +
op[0] DIV ASH(1, 3) MOD ASH(1, 3)*ASH(1, 1) +
op[0] DIV ASH(1, 6) MOD ASH(1, 1)*ASH(1, 7) +
op[0] DIV ASH(1, 7) MOD ASH(1, 1)*ASH(1, 6) +
op[0] DIV ASH(1, 8) MOD ASH(1, 1)*ASH(1, 10) +
op[0] DIV ASH(1, 9) MOD ASH(1, 2)*ASH(1, 8) +
op[0] DIV ASH(1, 11) MOD ASH(1, 1)*ASH(1, 4) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1)*ASH(1, 11)
, 12);
Write("JAL p")
| 1, 2:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 5) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1)*ASH(1, 5)
, 6);
IF rd = pcRelReg THEN Write("LI d, di") ELSE Write("ADDIW d, d, i") END
END;
| 2:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 5) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5)
, 6);
Write("LI d, i")
| 3:
IF op[0] DIV ASH(1, 7) MOD ASH(1, 12 - 7) = 2 THEN
rd := 2; (* SP *)
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 1) * ASH(1, 5) +
op[0] DIV ASH(1, 3) MOD ASH(1, 2) * ASH(1, 7) +
op[0] DIV ASH(1, 5) MOD ASH(1, 1) * ASH(1, 6) +
op[0] DIV ASH(1, 6) MOD ASH(1, 1) * ASH(1, 4) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 9)
, 10);
IF pcRelReg = rd THEN Write("LI d, di") ELSE Write("ADDI d, d, i") END;
ELSE
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 5) * ASH(1, 12) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 17)
, 18);
Write("LUI d, ih"); keepPcRelReg := TRUE; pcRelReg := rd; pcRelRegVal := imm;
END;
| 4:
CASE op[0] DIV ASH(1, 10) MOD ASH(1, 2) OF
| 0:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 2) MOD ASH(1, 5) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5);
Write("SRLI d, d, i")
| 1:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm :=
op[0] DIV ASH(1, 2) MOD ASH(1, 5) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5);
Write("SRAI d, d, i")
| 2:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 5) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5)
, 6);
Write("ANDI d, d, i")
| 3:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
rs1 := op[0] DIV ASH(1, 2) MOD ASH(1, 3) + 8;
CASE op[0] DIV ASH(1, 5) MOD ASH(1, 2) + op[0] DIV ASH(1, 12) MOD 2 * ASH(1, 2) OF
| 0: Write("SUB d, d, s")
| 1: Write("XOR d, d, s")
| 2: Write("OR d, d, s")
| 3: Write("AND d, d, s")
| 4: Write("SUBW d, d, s")
| 5: Write("ADDW d, d, s")
ELSE WriteUndef END;
END;
| 5:
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 1) * ASH(1, 5) +
op[0] DIV ASH(1, 3) MOD ASH(1, 3) * ASH(1, 1) +
op[0] DIV ASH(1, 6) MOD ASH(1, 1) * ASH(1, 7) +
op[0] DIV ASH(1, 7) MOD ASH(1, 1) * ASH(1, 6) +
op[0] DIV ASH(1, 8) MOD ASH(1, 1) * ASH(1, 10) +
op[0] DIV ASH(1, 9) MOD ASH(1, 2) * ASH(1, 8) +
op[0] DIV ASH(1, 11) MOD ASH(1, 1) * ASH(1, 4) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 11)
, 12);
Write("J p")
| 6:
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 1) * ASH(1, 5) +
op[0] DIV ASH(1, 3) MOD ASH(1, 2) * ASH(1, 1) +
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 6) +
op[0] DIV ASH(1, 10) MOD ASH(1, 2) * ASH(1, 3) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 8)
, 9);
Write("BEQZ s, p")
| 7:
rs1 := op[0] DIV ASH(1, 7) MOD ASH(1, 3) + 8;
imm := SignExtend(
op[0] DIV ASH(1, 2) MOD ASH(1, 1) * ASH(1, 5) +
op[0] DIV ASH(1, 3) MOD ASH(1, 2) * ASH(1, 1) +
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 6) +
op[0] DIV ASH(1, 10) MOD ASH(1, 2) * ASH(1, 3) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 8)
, 9);
Write("BNEZ s, p")
END;
| 2:
CASE op[0] DIV ASH(1, 13) MOD ASH(1, 3) OF
| 0:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
imm :=
op[0] DIV ASH(1, 2) MOD ASH(1, 5) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5);
Write("SLLI d, d, i")
| 1:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
CASE h.mode OF
| 0, 1:
imm :=
op[0] DIV ASH(1, 2) MOD ASH(1, 3) * ASH(1, 6) +
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 3) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5);
Write("LD df, i(SP)")
| 2: Write("LQSP ?")
END
| 2:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
imm :=
op[0] DIV ASH(1, 2) MOD ASH(1, 2) * ASH(1, 6) +
op[0] DIV ASH(1, 4) MOD ASH(1, 2) * ASH(1, 2) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5);
Write("LW d, i(SP)")
| 3:
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
CASE h.mode OF
| 0: Write("FLWSP ?")
| 1, 2:
imm :=
op[0] DIV ASH(1, 2) MOD ASH(1, 3) * ASH(1, 6) +
op[0] DIV ASH(1, 5) MOD ASH(1, 2) * ASH(1, 3) +
op[0] DIV ASH(1, 12) MOD ASH(1, 1) * ASH(1, 5);
Write("LD d, i(SP)")
END
| 4:
rs1 := op[0] DIV ASH(1, 2) MOD ASH(1, 5);
rd := op[0] DIV ASH(1, 7) MOD ASH(1, 5);
CASE op[0] DIV ASH(1, 12) MOD 2 OF
| 0:
IF rs1 = 0 THEN
IF rd = 1 THEN Write("RET"); newLine := TRUE ELSE Write("JR d") END;
ELSE
Write("MV d, s")
END
| 1:
IF rs1 = 0 THEN
IF rd = 0 THEN
Write("EBREAK")
ELSE
h.SetBold; Write("JALR d"); h.SetNormal
END;
ELSE
Write("ADD d, s")
END;
END;
| 5:
rs1 := op[0] DIV ASH(1, 2) MOD ASH(1, 5);
CASE h.mode OF
| 0, 1:
imm := (
op[0] DIV ASH(1, 10) MOD ASH(1, 3) +
op[0] DIV ASH(1, 7) MOD ASH(1, 3)*ASH(1, 3)
)*8;
Write("SD sf, i(SP)")
| 2: Write("SQSP ?")
END
| 6:
rs1 := op[0] DIV ASH(1, 2) MOD ASH(1, 5);
imm :=
op[0] DIV ASH(1, 7) MOD ASH(1, 2) * ASH(1, 6) +
op[0] DIV ASH(1, 9) MOD ASH(1, 4) * ASH(1, 2);
Write("SW s, i(SP)")
| 7:
rs1 := op[0] DIV ASH(1, 2) MOD ASH(1, 5);
CASE h.mode OF
| 0:
Write("FSWSP ?")
| 1, 2:
imm := (
op[0] DIV ASH(1, 10) MOD ASH(1, 3) +
op[0] DIV ASH(1, 7) MOD ASH(1, 3)*ASH(1, 3)
)*8;
Write("SD s, i(SP)")
END
END;
END;
END Op1;
PROCEDURE Op2;
BEGIN
op2 := op[0] MOD ASH(1, 16) + op[1]*ASH(1, 16);
CASE op[0] DIV ASH(1, 2) MOD ASH(1, 5) OF
| 0: I; argSize := op[0] DIV ASH(1, 12) MOD ASH(1, 3); Write("La d, si");
| 1: I; Write("FLW df, si")
| 2: Write("?(2)") (* undefined *)
| 3: I;
CASE fn3 OF
| 0: Write("FENCE d, s, i")
| 1: Write("FENCE.I d, s, i")
ELSE WriteString("?(3, "); WriteInt(fn3); WriteString(")") END;
| 4:
I; CASE op[0] DIV ASH(1, 12) MOD ASH(1, 3) OF
| 0:
IF (rd = 0) & (rs1 = 0) & (imm = 0) THEN Write("NOP")
ELSIF rs1 = 0 THEN Write("LI d, i")
ELSIF rs1 = pcRelReg THEN Write("LI d, si")
ELSE Write("ADDI d, s, i") END
| 1: Write("SLLI d, s, i")
| 2: Write("SLTI d, s, i")
| 3: Write("SLTIU d, s, i")
| 4: Write("XORI d, s, i")
| 5: Write("SRLI d, s, i")
| 6: Write("ORI d, s, i")
| 7: Write("ANDI d, s, i")
ELSE WriteString("?("); WriteInt(op[0] DIV ASH(1, 12) MOD ASH(1, 3)); WriteString(")") END;
| 5: U; Write("AUIPC d, ih"); keepPcRelReg := TRUE; pcRelReg := rd; pcRelRegVal := imm + pc0;
| 6:
I; CASE op[0] DIV ASH(1, 12) MOD ASH(1, 3) OF
| 0: IF rs1 = pcRelReg THEN Write("LI d, si") ELSE Write("ADDIW d, s, i") END
| 1: Write("SLLIW d, s, i")
| 5: Write("SRLIW d, s, i")
ELSE WriteString("?("); WriteInt(op[0] DIV ASH(1, 12) MOD ASH(1, 3)); WriteString(")") END;
| 7: HALT(100); (* 48-bit opcode *)
| 8: S; argSize := op[0] DIV ASH(1, 12) MOD ASH(1, 3); Write("Sa t, si");
| 9: S; Write("FSW tf, si")
| 10: Write("?(10)") (* undefined *)
| 11: R;
argSize := fn3;
CASE fn7 DIV ASH(1, 2) OF
| 0: Write("AMOADD.a d, s, t")
| 1: Write("AMOSWAP.a d, s, t")
| 2: Write("LR.a d, s")
| 3: Write("SC.a d, s, t")
| 4: Write("AMOXOR.a d, s, t")
| 8: Write("AMOOR.a d, s, t")
| 12: Write("AMOAND.a d, s, t")
| 16: Write("AMOMIN.a d, s, t")
| 20: Write("AMOMAX.a d, s, t")
| 24: Write("AMOMINU.a d, s, t")
| 28: Write("AMOMAXU.a d, s, t")
ELSE WriteString("?(11, "); WriteInt(fn7 DIV ASH(1, 2)); WriteString(")") END;
| 12: R;
CASE fn7 OF
| 0:
CASE fn3 OF
| 0: Write("ADD d, s, t")
| 1: Write("SLL d, s, t")
| 2: Write("SLT d, s, t")
| 3: Write("SLTU d, s, t")
| 4: Write("XOR d, s, t")
| 5: Write("SRL d, s, t")
| 6: Write("OR d, s, t")
| 7: Write("AND d, s, t")
END;
| 1:
CASE fn3 OF
| 0: Write("MUL d, s, t")
| 1: Write("MULH d, s, t")
| 2: Write("MULHSU d, s, t")
| 3: Write("MULHU d, s, t")
| 4: Write("DIV d, s, t")
| 5: Write("DIVU d, s, t")
| 6: Write("REM d, s, t")
| 7: Write("REMU d, s, t")
END;
| 32:
CASE fn3 OF
| 0: Write("SUB d, s, t")
| 5: Write("SRA d, s, t")
ELSE WriteString("?(12, 32, "); WriteInt(fn3); WriteString(")") END;
ELSE WriteString("?(12, "); WriteInt(fn7); WriteString(")") END;
| 13: U; Write("LUI d, ih"); keepPcRelReg := TRUE; pcRelReg := rd; pcRelRegVal := imm;
| 14: R;
CASE fn7 OF
| 0:
CASE fn3 OF
| 0: Write("ADDW d, s, t")
| 1: Write("SLLW d, s, t")
| 5: Write("SRLW d, s, t")
ELSE WriteString("?(14, 0, "); WriteInt(fn3); WriteString(")") END;
| 1:
CASE fn3 OF
| 0: Write("MULW d, s, t")
| 4: Write("DIVW d, s, t")
| 5: Write("DIVUW d, s, t")
| 6: Write("REMW d, s, t")
| 7: Write("REMUW d, s, t")
ELSE WriteString("?(14, 1, "); WriteInt(fn3); WriteString(")") END;
| 32:
CASE fn3 OF
| 0: Write("SUBW d, s, t")
| 5: Write("SRAW d, s, t")
ELSE WriteString("?(14, 32, "); WriteInt(fn3); WriteString(")") END;
ELSE WriteString("?(14, "); WriteInt(fn7); WriteString(")") END;
| 15: HALT(100); (* 64-bit opcode *)
| 16: R4; argSize := fn7; Write("FMADD.af df, sf, tf, uf")
| 17: R4; argSize := fn7; Write("FMSUB.af df, sf, tf, uf")
| 18: R4; argSize := fn7; Write("FNMSUB.af df, sf, tf, uf")
| 19: R4; argSize := fn7; Write("FNMADD.af df, sf, tf, uf")
| 20: R;
argSize := fn7 MOD ASH(1, 2);
CASE fn7 DIV ASH(1, 2) OF
| 0: Write("FADD.af df, sf, tf")
| 1: Write("FSUB.af df, sf, tf")
| 2: Write("FMUL.af df, sf, tf")
| 3: Write("FDIV.af df, sf, tf")
| 4:
CASE fn3 OF
| 0: Write("FSGNJ.af df, sf, tf")
| 1: Write("FSGNJN.af df, sf, tf")
| 2: Write("FSGNJX.af df, sf, tf")
ELSE WriteString("?(20, 4, "); WriteInt(fn3); WriteString(")") END;
| 5:
CASE fn3 OF
| 0: Write("FMIN.af df, sf, tf")
| 1: Write("FMAX.af df, sf, tf")
ELSE WriteString("?(20, 5, "); WriteInt(fn3); WriteString(")") END;
| 8: Write("FCVT.af"); argSize := rs2; Write(".af df, sf, tf")
| 11: Write("FSQRT.af df, sf, tf")
| 20:
CASE fn3 OF
| 2: Write("FEQ.af df, sf, tf")
| 1: Write("FLT.af df, sf, tf")
| 0: Write("FLE.af df, sf, tf")
ELSE WriteString("?(20, 20, "); WriteInt(fn3); WriteString(")") END;
| 24:
CASE rs2 OF
| 0: Write("FCVT.W.af df, sf, tf")
| 1: Write("FCVT.WU.af df, sf, tf")
| 2: Write("FCVT.L.af df, sf, tf")
| 3: Write("FCVT.LU.af df, sf, tf")
ELSE WriteString("?(20, 24, "); WriteInt(rs2); WriteString(")") END;
| 26:
CASE rs2 OF
| 0: Write("FCVT.af.W df, sf, tf")
| 1: Write("FCVT.af.WU df, sf, tf")
| 2: Write("FCVT.af.L df, sf, tf")
| 3: Write("FCVT.af.LU df, sf, tf")
ELSE WriteString("?(20, 26, "); WriteInt(rs2); WriteString(")") END;
| 28:
CASE fn3 OF
| 0: INC(argSize, 2); Write("FMV.X.a df, sf, tf")
| 1: Write("FCLASS.S df, sf, tf")
ELSE WriteString("?(20, 28, "); WriteInt(fn3); WriteString(")") END;
| 30: INC(argSize, 2); Write("FMV.a.X df, sf, tf")
ELSE WriteString("?(20, "); WriteInt(fn7); WriteString(")") END;
| 21: Write("?(21)") (* undefined *)
| 22: Write("?(22)") (* undefined *)
| 23: Write("?(23)") (* undefined *)
| 24: B; Write("B");
CASE op[0] DIV ASH(1, 12) MOD ASH(1, 3) OF
| 0: Write("EQ")
| 1: Write("NE")
| 4: Write("LT")
| 5: Write("GE")
| 6: Write("LTU")
| 7: Write("BGEU")
ELSE WriteString("?("); WriteInt(op[0] DIV ASH(1, 12) MOD ASH(1, 3)); WriteString(")") END;
Write(" s, t, p")
| 25: I; h.SetBold; IF rd = 0 THEN Write("JR si") ELSIF rd = 1 (* RA *) THEN Write("JALR si") ELSE Write("JALR d, si") END; h.SetNormal
| 26: Write("?(26)") (* undefined *)
| 27: J; h.SetBold; IF rd = 0 THEN Write("J p") ELSIF rd = 1 (* RA *) THEN Write("JAL p") ELSE Write("JAL d, p") END; h.SetNormal
| 28: I;
CASE fn3 OF
| 0:
CASE imm OF
| 0: Write("ECALL")
| 1: Write("EBREAK")
| 258: Write("SRET")
| 261: Write("WFI")
| 770: Write("MRET")
| 288..319: R; Write("SFENCE.VMA s, t")
ELSE WriteString("?(28, 0, "); WriteInt(imm); WriteString(")") END;
| 1..3, 5..7:
rs2 := imm;
CASE fn3 OF
| 1, 5: Write("CSRRW")
| 2, 6: Write("CSRRS")
| 3, 7: Write("CSRRC")
END;
CASE fn3 OF 5..7: imm := rs1; Write("I d, tc, i") ELSE Write(" d, tc, s") END;
ELSE WriteString("?(28, "); WriteInt(fn3); WriteString(")") END;
| 29: Write("?(29)") (* undefined *)
| 30: Write("?(30)") (* undefined *)
| 31: HALT(100); (* variable length opcode *)
END;
END Op2;
BEGIN
newLine := FALSE;
keepPcRelReg := FALSE;
pc0 := h.adr;
ReadSInt(op[0]);
IF BITS(op[0] MOD 10000H) * {0..6} = {0..6} THEN
opLen := 5 + op[0] DIV ASH(1, 12) MOD ASH(1, 3);
ELSIF BITS(op[0] MOD 10000H) * {0..6} = {0..5} THEN
opLen := 4;
ELSIF BITS(op[0] MOD 10000H) * {0..5} = {0..4} THEN
opLen := 3;
ELSIF BITS(op[0] MOD 10000H) * {0..1} = {0..1} THEN
opLen := 2;
ELSE
opLen := 1;
END;
i := 1; WHILE i < opLen DO ReadSInt(op[i]); INC(i) END;
i := 0; WHILE i < MIN(opLen, 2) DO
WriteHex(op[i] MOD 10000H, 4); h.Put(" ");
INC(i) END;
h.Put(09X);
CASE opLen OF
| 1: Op1;
| 2: Op2;
ELSE WriteUndef END;
IF opLen > 2 THEN
h.Put(0DX); h.Put(09X);
i := 2; WHILE i < opLen DO
IF (i # 2) & (i MOD 2 = 0) THEN h.Put(09X); h.Put(0DX); h.Put(09X) END;
WriteHex(op[i] MOD 10000H, 4); h.Put(" ");
INC(i) END;
h.Put(09X);
END;
IF newLine THEN h.Put(0DX) END;
IF ~keepPcRelReg THEN pcRelReg := -1 END;
END Decode;
PROCEDURE Init;
VAR d: Decoder;
BEGIN
pcRelReg := -1;
NEW(d); dec := d;
END Init;
BEGIN Init;
END WorkDecRISCV.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment