Last active
September 24, 2022 02:08
-
-
Save X547/9da7300ae6414a53868f656f0d08fb2a to your computer and use it in GitHub Desktop.
RISC-V disassembler for Oberon (Component Pascal)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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