Loading files
92595157eThis file is pinned to the selected release. Download the original to open it in your design tool.
# -*- coding: utf-8 -*-
import sys
import re
import pprint
class RISCV_Disassembler( object ):
""" 32bit RISCV disassembler """
def __init__( self ):
pass
def Disassemble( self, codeStr ):
try:
if( codeStr == "" or codeStr == "xxxxxxxx" ):
return "invalid:" + codeStr
code = int( codeStr, 16 )
common = self.InstructionCommon( code )
insn = common
if common.IsLoad():
insn = self.InstructionLoad( code )
elif common.IsStore():
insn = self.InstructionStore( code )
elif common.IsBranch():
insn = self.InstructionBranch( code )
elif common.IsJALR():
insn = self.InstructionJALR( code )
elif common.IsJAL():
insn = self.InstructionJAL( code )
elif common.IsOpImm():
insn = self.InstructionOpImm( code )
elif common.IsOp():
insn = self.InstructionOp( code )
elif common.IsAUIPC():
insn = self.InstructionAUIPC( code )
elif common.IsLUI():
insn = self.InstructionLUI( code )
elif common.IsMiscMem():
insn = self.InstructionMiscMem( code )
elif common.IsSystem():
insn = self.InstructionSystem( code )
elif common.IsFLoad():
insn = self.InstructionFLoad( code )
elif common.IsFStore():
insn = self.InstructionFStore( code )
elif common.IsFOp():
insn = self.InstructionFOp( code )
elif common.IsFMADD():
insn = self.InstructionFMADD( code )
elif common.IsFMSUB():
insn = self.InstructionFMSUB( code )
elif common.IsFNMSUB():
insn = self.InstructionFNMSUB( code )
elif common.IsFNMADD():
insn = self.InstructionFNMADD( code )
return insn.__str__()
except ValueError:
return "invalid: %s" % codeStr
class InstructionBase( object ):
""" RISCV distribution """
RV32I = True
RV64I = False
RV32M = True
RV64M = False
RV32A = False
RV64A = False
RV32F = True
RV64F = False
RV32D = False
RV64D = False
def __init__( self, code ):
self.code = code
def Bits( self, source, higherPosition, lowerPosition ):
""" Extract bits from source data. """
length = higherPosition - lowerPosition + 1
mask = (1 << length) - 1
return (source >> lowerPosition) & mask
def __str__( self ):
return "unknown %x" % self.code
class InstructionCommon( InstructionBase ):
""" Common instruction """
OC_LOAD = "0000011"
OC_STORE = "0100011"
OC_BRANCH = "1100011"
OC_JALR = "1100111"
OC_JAL = "1101111"
OC_OP_IMM = "0010011"
OC_OP = "0110011"
OC_AUIPC = "0010111"
OC_LUI = "0110111"
OC_MISC_MEM = "0001111"
OC_SYSTEM = "1110011"
OC_F_LOAD = "0000111"
OC_F_STORE = "0100111"
OC_F_OP = "1010011"
OC_F_FMADD = "1000011"
OC_F_FMSUB = "1000111"
OC_F_FNMSUB = "1001011"
OC_F_FNMADD = "1001111"
intRegName = ['zero', 'ra', 'sp', 'gp', 'tp', 't0', 't1', 't2',
's0/fp', 's1', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5',
'a6', 'a7', 's2', 's3', 's4', 's5', 's6', 's7',
's8', 's9', 's10', 's11', 't3', 't4', 't5', 't6']
floatRegName = ['ft0', 'ft1', 'ft2', 'ft3', 'ft4', 'ft5', 'ft6', 'ft7',
'fs0', 'fs1', 'fa0', 'fa1', 'fa2', 'fa3', 'fa4', 'fa5',
'fa6', 'fa7', 'fs2', 'fs3', 'fs4', 'fs5', 'fs6', 'fs7',
'fs8', 'fs9', 'fs10', 'fs11', 'ft8', 'ft9', 'ft10', 'ft11']
def __init__( self, code ):
RISCV_Disassembler.InstructionBase.__init__( self, code )
inst = "{0:032b}".format(self.Bits(code, 31, 0))
self.opCode = inst[-7:]
self.funct2 = inst[-27:-25]
self.funct3 = inst[-15:-12]
self.funct7 = inst[-32:-25]
self.funct6 = inst[-32:-26]
self.funct5 = inst[-25:-20]
self.funct12 = inst[-32:-20]
self.rd = self.intRegName[int(inst[-12:-7], 2)]
self.rs1 = self.intRegName[int(inst[-20:-15], 2)]
self.rs2 = self.intRegName[int(inst[-25:-20], 2)]
self.rd = self.intRegName[int(inst[-12:-7], 2)]
self.frs1 = self.floatRegName[int(inst[-20:-15], 2)]
self.frs2 = self.floatRegName[int(inst[-25:-20], 2)]
self.frs3 = self.floatRegName[int(inst[-32:-27], 2)]
self.frd = self.floatRegName[int(inst[-12:-7], 2)]
# Hex Style
self.shamt5 = str(hex(int(inst[-25:-20], 2)))
self.shamt6 = str(hex(int(inst[-26:-20], 2)))
self.I_Imm = str(hex(int(inst[-32] * 21 + inst[-31:-20], 2)))
self.S_Imm = str(hex(int(inst[-32] * 21 + inst[-31:-25] + inst[-12:-7], 2)))
self.B_Imm = str(hex(int(inst[-32] * 20 + inst[-8] + inst[-31:-25]
+ inst[-12:-8] + '0', 2)))
self.U_Imm = str(hex(int(inst[-32] + inst[-31:-20] + inst[-20:-12]
+ '0' * 12, 2)))
self.J_Imm = str(hex(int(inst[-32] * 12 + inst[-20:-12] + inst[-21]
+ inst[-31:-21] + '0', 2)))
def IsLoad( self ):
return self.opCode == self.OC_LOAD
def IsStore( self ):
return self.opCode == self.OC_STORE
def IsBranch( self ):
return self.opCode == self.OC_BRANCH
def IsJALR( self ):
return self.opCode == self.OC_JALR
def IsJAL( self ):
return self.opCode == self.OC_JAL
def IsOpImm( self ):
return self.opCode == self.OC_OP_IMM
def IsOp( self ):
return self.opCode == self.OC_OP
def IsAUIPC( self ):
return self.opCode == self.OC_AUIPC
def IsLUI( self ):
return self.opCode == self.OC_LUI
def IsMiscMem( self ):
return self.opCode == self.OC_MISC_MEM
def IsSystem( self ):
return self.opCode == self.OC_SYSTEM
def IsFLoad(self):
return self.opCode == self.OC_F_LOAD
def IsFStore(self):
return self.opCode == self.OC_F_STORE
def IsFOp(self):
return self.opCode == self.OC_F_OP
def IsFMADD(self):
return self.opCode == self.OC_F_FMADD
def IsFMSUB(self):
return self.opCode == self.OC_F_FMSUB
def IsFNMSUB(self):
return self.opCode == self.OC_F_FNMSUB
def IsFNMADD(self):
return self.opCode == self.OC_F_FNMADD
class InstructionLoad( InstructionCommon ):
""" Load instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct3 == '000' and self.RV32I:
opType = 'lb '
elif self.funct3 == '001' and self.RV32I:
opType = 'lh '
elif self.funct3 == '010' and self.RV32I:
opType = 'lw '
elif self.funct3 == '011' and self.RV64I:
opType = 'ld ' # self.RV64I
elif self.funct3 == '100' and self.RV32I:
opType = 'lbu '
elif self.funct3 == '101' and self.RV32I:
opType = 'lhu '
elif self.funct3 == '110' and self.RV32I:
opType = 'lwu '
else:
opType = 'Unknown'
asmStr = opType + self.rd + ', ' + self.I_Imm + '(' + self.rs1 + ')'
return asmStr
class InstructionStore( InstructionCommon ):
""" Store instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct3 == '000' and self.RV32I:
opType = 'sb '
elif self.funct3 == '001' and self.RV32I:
opType = 'sh '
elif self.funct3 == '010' and self.RV32I:
opType = 'sw '
elif self.funct3 == '011' and self.RV64I:
opType = 'sd '
else:
opType = 'Unknown'
asmStr = opType + self.rs2 + ', ' + self.S_Imm + '(' + self.rs1 + ')'
return asmStr
class InstructionBranch( InstructionCommon ):
""" Branch instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct3 == '000':
opType = 'beq '
elif self.funct3 == '001':
opType = 'bne '
elif self.funct3 == '100':
opType = 'blt '
elif self.funct3 == '101':
opType = 'bge '
elif self.funct3 == '110':
opType = 'bltu '
elif self.funct3 == '111':
opType = 'bgeu '
else:
opType = 'Unknown'
asmStr = opType + self.rs1 + ', ' + self.rs2 + ', ' + self.B_Imm
return asmStr
class InstructionJALR( InstructionCommon ):
""" JALR instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
opType = 'jalr '
asmStr = opType + self.rd + ', ' + self.I_Imm + '(' + self.rs1 + ')'
return asmStr
class InstructionJAL( InstructionCommon ):
""" JAL instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
opType = 'jal '
asmStr = opType + self.rd + ', ' + self.J_Imm
return asmStr
class InstructionOpImm( InstructionCommon ):
""" OpImm instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
imm = self.I_Imm
if self.funct3 == '000' and self.RV32I:
opType = 'addi '
elif self.funct3 == '001':
if self.funct6 == '000000' and self.RV64I:
opType = 'slli '
imm = self.shamt6
elif self.funct7 == '0000000' and self.RV32I:
opType = 'slli '
imm = self.shamt5
else:
opType = 'Unknown'
elif self.funct3 == '101':
if self.funct6 == '000000' and self.RV64I:
opType = 'srli '
imm = self.shamt6
elif self.funct6 == '010000' and self.RV64I:
opType = 'srai '
imm = self.shamt6
elif self.funct7 == '0000000' and self.RV32I:
opType = 'srli '
imm = self.shamt5
elif self.funct7 == '0100000' and self.RV32I:
opType = 'srai '
imm = self.shamt5
else:
opType = 'Unknown'
elif self.funct3 == '010' and self.RV32I:
opType = 'slti '
elif self.funct3 == '011' and self.RV32I:
opType = 'sltiu '
elif self.funct3 == '100' and self.RV32I:
opType = 'xori '
elif self.funct3 == '110' and self.RV32I:
opType = 'ori '
elif self.funct3 == '111' and self.RV32I:
opType = 'andi '
else:
opType = 'Unknown'
asmStr = opType + self.rd + ', ' + self.rs1 + ', ' + imm
return asmStr
class InstructionOp( InstructionCommon ):
""" Op instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct7 == '0000001' and self.RV32M:
if self.funct3 == '000':
opType = 'mul '
elif self.funct3 == '001':
opType = 'mulh '
elif self.funct3 == '010':
opType = 'mulhsu '
elif self.funct3 == '011':
opType = 'mulhu '
elif self.funct3 == '100':
opType = 'div '
elif self.funct3 == '101':
opType = 'divu '
elif self.funct3 == '110':
opType = 'rem '
elif self.funct3 == '111':
opType = 'remu '
else:
opType = 'Unknown'
elif self.RV32I:
if self.funct3 == '000' and self.funct7 == '0000000':
opType = 'add '
elif self.funct3 == '000' and self.funct7 == '0100000':
opType = 'sub '
elif self.funct3 == '001' and self.funct7 == '0000000':
opType = 'sll '
elif self.funct3 == '010' and self.funct7 == '0000000':
opType = 'slt '
elif self.funct3 == '011' and self.funct7 == '0000000':
opType = 'sltu '
elif self.funct3 == '100' and self.funct7 == '0000000':
opType = 'xor '
elif self.funct3 == '101' and self.funct7 == '0000000':
opType = 'srl '
elif self.funct3 == '101' and self.funct7 == '0100000':
opType = 'sra '
elif self.funct3 == '110' and self.funct7 == '0000000':
opType = 'or '
elif self.funct3 == '111' and self.funct7 == '0000000':
opType = 'and '
else:
opType = 'Unknown'
else:
opType = 'Unknown'
asmStr = opType + self.rd + ', ' + self.rs1 + ', ' + self.rs2
return asmStr
class InstructionAUIPC( InstructionCommon ):
""" AUIPC instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
opType = 'auipc '
asmStr = opType + self.rd + ', ' + self.U_Imm
return asmStr
class InstructionLUI( InstructionCommon ):
""" Load instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
opType = 'lui '
asmStr = opType + self.rd + ', ' + self.U_Imm
return asmStr
class InstructionMiscMem( InstructionCommon ):
""" Misc Memory instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct3 == "000":
opType = 'fence ' + "{0:08b}".format(self.Bits(self.code, 27, 20))
elif self.funct3 == "001":
opType = 'fence.i '
else:
opType = 'unknown misc mem'
asmStr = opType
return asmStr
class InstructionSystem( InstructionCommon ):
""" Misc Memory instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
csr = "0x{0:03x}".format(self.Bits(self.code, 31, 20))
zimm = "0x{0:03x}".format(self.Bits(self.code, 19, 15))
if self.funct3 == '000':
if self.funct12 == '000000000000':
opType = 'ecall'
elif self.funct12 == '000000000001':
opType = 'ebreak'
elif self.funct12 == '000000000010':
opType = 'uret'
elif self.funct12 == '000100000010':
opType = 'sret'
elif self.funct12 == '001100000010':
opType = 'mret'
elif self.funct12 == '000100000101':
opType = 'wfi'
elif self.funct12[0:7] == '0001001':
opType = 'sfence.vma ' + self.rs1 + ', ' + self.rs2
else:
opType = 'unknown system'
elif self.funct3 == "001":
opType = 'csrrw ' + self.rd + ', ' + csr + ', ' + self.rs1
elif self.funct3 == "010":
opType = 'csrrs ' + self.rd + ', ' + csr + ', ' + self.rs1
elif self.funct3 == "011":
opType = 'csrrc ' + self.rd + ', ' + csr + ', ' + self.rs1
elif self.funct3 == "101":
opType = 'csrrwi ' + self.rd + ', ' + csr + ', ' + zimm
elif self.funct3 == "110":
opType = 'csrrsi ' + self.rd + ', ' + csr + ', ' + zimm
elif self.funct3 == "111":
opType = 'csrrci ' + self.rd + ', ' + csr + ', ' + zimm
else:
opType = 'unknown system'
asmStr = opType
return asmStr
class InstructionFOp( InstructionCommon ):
""" FP Op instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct7 == '0000000' and self.RV32F:
opType = 'fadd.s '
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2
elif self.funct7 == '0000100' and self.RV32F:
opType = 'fsub.s '
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2
elif self.funct7 == '0001000' and self.RV32F:
opType = 'fmul.s '
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2
elif self.funct7 == '0001100' and self.RV32F:
opType = 'fdiv.s '
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2
elif self.funct7 == '0101100' and self.RV32F:
opType = 'fsqrt.s '
asmStr = opType + self.frd + ', ' + self.frs1
elif self.funct7 == '0010000' and self.RV32F:
if self.funct3 == '000':
opType = 'fsgnj.s '
elif self.funct3 == '001':
opType = 'fsgnjn.s '
elif self.funct3 == '010':
opType = 'fsgnjx.s '
else:
opType == 'unknown fop '
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2
elif self.funct7 == '0010100' and self.RV32F:
if self.funct3 == '000':
opType = 'fmin.s '
elif self.funct3 == '001':
opType = 'fmax.s '
else:
opType = 'unknown fop '
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2
elif self.funct7 == '1100000' and self.RV32F:
if self.funct5 == '00000':
opType = 'fcvt.w.s '
elif self.funct5 == '00001':
opType = 'fcvt.wu.s '
else:
opType = 'unknoen fop '
asmStr = opType + self.rd + ', ' + self.frs1
elif self.funct7 == '1110000' and self.RV32F:
if self.funct3 == '000':
opType = 'fmv.x.w '
elif self.funct3 == '001':
opType = 'fclass.s '
else:
opType = 'unknown fop '
asmStr = opType + self.rd + ', ' + self.frs1
elif self.funct7 == '1010000' and self.RV32F:
if self.funct3 == '010':
opType = 'feq.s '
elif self.funct3 == '001':
opType = 'flt.s '
elif self.funct3 == '000':
opType = 'fle.s '
else:
opType = 'unknown fop '
asmStr = opType + self.rd + ', ' + self.frs1 + ', ' + self.frs2
elif self.funct7 == '1101000' and self.RV32F:
if self.funct5 == '00000':
opType = 'fcvt.s.w '
elif self.funct5 == '00001':
opType = 'fcvt.s.wu '
else:
opType = 'unknown fop '
asmStr = opType + self.frd + ', ' + self.rs1
elif self.funct7 == '1111000' and self.RV32F:
opType = 'fmv.w.x '
asmStr = opType + self.frd + ', ' + self.rs1
else:
opType = 'unknown fop '
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2
return asmStr
class InstructionFLoad( InstructionCommon ):
""" FP Load instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct3 == '010' and self.RV32F:
opType = 'flw '
else:
opType = 'Unknown'
asmStr = opType + self.frd + ', ' + self.I_Imm + '(' + self.rs1 + ')'
return asmStr
class InstructionFStore( InstructionCommon ):
""" FP Store instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct3 == '010' and self.RV32F:
opType = 'fsw '
else:
opType = 'Unknown'
asmStr = opType + self.frs2 + ', ' + self.S_Imm + '(' + self.rs1 + ')'
return asmStr
class InstructionFMADD( InstructionCommon ):
""" FP FMADD instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct2 == '00' and self.RV32F:
opType = 'fmadd.s '
else:
opType = 'Unknown'
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2 + ', ' + self.frs3
return asmStr
class InstructionFMSUB( InstructionCommon ):
""" FP FMSUB instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct2 == '00' and self.RV32F:
opType = 'fmsub.s '
else:
opType = 'Unknown'
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2 + ', ' + self.frs3
return asmStr
class InstructionFNMSUB( InstructionCommon ):
""" FP FNMSUB instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct2 == '00' and self.RV32F:
opType = 'fnmsub.s '
else:
opType = 'Unknown'
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2 + ', ' + self.frs3
return asmStr
class InstructionFNMADD( InstructionCommon ):
""" FP FNMADD instruction """
def __init__( self, code ):
RISCV_Disassembler.InstructionCommon.__init__( self, code )
def __str__( self ):
if self.funct2 == '00' and self.RV32F:
opType = 'fnmadd.s '
else:
opType = 'Unknown'
asmStr = opType + self.frd + ', ' + self.frs1 + ', ' + self.frs2 + ', ' + self.frs3
return asmStr