You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
344 lines
8.8 KiB
344 lines
8.8 KiB
|
|
condition_table_true = ["lt", "gt", "eq"]
|
|
condition_table_false = ["ge", "le", "ne"]
|
|
trap_condition_table = {
|
|
1: "lgt",
|
|
2: "llt",
|
|
4: "eq",
|
|
5: "lge",
|
|
8: "gt",
|
|
12: "ge",
|
|
16: "lt",
|
|
20: "le",
|
|
31: "u"
|
|
}
|
|
|
|
spr_table = {
|
|
8: "lr",
|
|
9: "ctr"
|
|
}
|
|
|
|
def decodeI(value):
|
|
return (value >> 2) & 0xFFFFFF, (value >> 1) & 1, value & 1
|
|
|
|
def decodeB(value):
|
|
return (value >> 21) & 0x1F, (value >> 16) & 0x1F, (value >> 2) & 0x3FFF, (value >> 1) & 1, value & 1
|
|
|
|
def decodeD(value):
|
|
return (value >> 21) & 0x1F, (value >> 16) & 0x1F, value & 0xFFFF
|
|
|
|
def decodeX(value):
|
|
return (value >> 21) & 0x1F, (value >> 16) & 0x1F, (value >> 11) & 0x1F, (value >> 1) & 0x3FF, value & 1
|
|
|
|
def extend_sign(value, bits=16):
|
|
if value & 1 << (bits - 1):
|
|
value -= 1 << bits
|
|
return value
|
|
|
|
def ihex(value):
|
|
return "-" * (value < 0) + "0x" + hex(value).lstrip("-0x").rstrip("L").zfill(1).upper()
|
|
|
|
def decodeCond(BO, BI):
|
|
#TODO: Better condition code
|
|
if BO == 20: return ""
|
|
if BO & 1: return "?"
|
|
if BI > 2: return "?"
|
|
if BO == 4: return condition_table_false[BI]
|
|
if BO == 12: return condition_table_true[BI]
|
|
return "?"
|
|
|
|
def loadStore(value, regtype="r"):
|
|
D, A, d = decodeD(value)
|
|
d = extend_sign(d)
|
|
return "%s%i, %s(r%i)" %(regtype, D, ihex(d), A)
|
|
|
|
def loadStoreX(D, A, B, pad):
|
|
if pad: return "<invalid>"
|
|
return "r%i, %s, r%i" %(D, ("r%i" %A) if A else "0", B)
|
|
|
|
def add(D, A, B, Rc):
|
|
return "add%s" %("." * Rc), "r%i, r%i, r%i" %(D, A, B)
|
|
|
|
def addi(value, addr):
|
|
D, A, SIMM = decodeD(value)
|
|
SIMM = extend_sign(SIMM)
|
|
if A == 0:
|
|
return "li", "r%i, %s" %(D, ihex(SIMM))
|
|
return "addi", "r%i, r%i, %s" %(D, A, ihex(SIMM))
|
|
|
|
def addic(value, addr):
|
|
D, A, SIMM = decodeD(value)
|
|
SIMM = extend_sign(SIMM)
|
|
return "addic", "r%i, r%i, %s" %(D, A, ihex(SIMM))
|
|
|
|
def addic_(value, addr):
|
|
D, A, SIMM = decodeD(value)
|
|
SIMM = extend_sign(SIMM)
|
|
return "addic.", "r%i, r%i, %s" %(D, A, ihex(SIMM))
|
|
|
|
def addis(value, addr):
|
|
D, A, SIMM = decodeD(value)
|
|
SIMM = extend_sign(SIMM)
|
|
if A == 0:
|
|
return "lis", "r%i, %s" %(D, ihex(SIMM))
|
|
return "addis", "r%i, r%i, %s" %(D, A, ihex(SIMM))
|
|
|
|
def and_(S, A, B, Rc):
|
|
return "and%s" % ("." * Rc), "r%i, r%i, r%i" % (A, S, B)
|
|
|
|
def b(value, addr):
|
|
LI, AA, LK = decodeI(value)
|
|
LI = extend_sign(LI, 24) * 4
|
|
if AA:
|
|
dst = LI
|
|
else:
|
|
dst = addr + LI
|
|
return "b%s%s" %("l" * LK, "a" * AA), ihex(dst)
|
|
|
|
def bc(value, addr):
|
|
BO, BI, BD, AA, LK = decodeB(value)
|
|
LI = extend_sign(LK, 14) * 4
|
|
instr = "b" + decodeCond(BO, BI)
|
|
if LK: instr += "l"
|
|
if AA:
|
|
instr += "a"
|
|
dst = LI
|
|
else:
|
|
dst = addr + LI
|
|
return instr, ihex(dst)
|
|
|
|
def bcctr(BO, BI, pad, LK):
|
|
if pad: return "<invalid>"
|
|
instr = "b" + decodeCond(BO, BI) + "ctr"
|
|
if LK:
|
|
instr += "l"
|
|
return instr
|
|
|
|
def bclr(BO, BI, pad, LK):
|
|
if pad: return "<invalid>"
|
|
instr = "b" + decodeCond(BO, BI) + "lr"
|
|
if LK:
|
|
instr += "l"
|
|
return instr
|
|
|
|
def cmp(cr, A, B, pad):
|
|
if pad: return "<invalid>"
|
|
if cr & 3:
|
|
return "<invalid>"
|
|
return "cmp", "cr%i, r%i, r%i" %(cr >> 2, A, B)
|
|
|
|
def cmpi(value, addr):
|
|
cr, A, SIMM = decodeD(value)
|
|
SIMM = extend_sign(SIMM)
|
|
if cr & 3:
|
|
return "<invalid>"
|
|
return "cmpwi", "cr%i, r%i, %s" %(cr >> 2, A, ihex(SIMM))
|
|
|
|
def cmpl(cr, A, B, pad):
|
|
if pad: return "<invalid>"
|
|
if cr & 3:
|
|
return "<invalid>"
|
|
return "cmplw", "cr%i, r%i, r%i" %(cr >> 2, A, B)
|
|
|
|
def cmpli(value, addr):
|
|
cr, A, UIMM = decodeD(value)
|
|
if cr & 3:
|
|
return "<invalid>"
|
|
return "cmplwi", "cr%i, r%i, %s" %(cr >> 2, A, ihex(UIMM))
|
|
|
|
def cntlzw(S, A, pad, Rc):
|
|
if pad: return "<invalid>"
|
|
return "cntlzw%s" %("." * Rc), "r%i, r%i" %(A, S)
|
|
|
|
def dcbst(pad1, A, B, pad2):
|
|
if pad1 or pad2: return "<invalid>"
|
|
return "dcbst", "r%i, r%i" %(A, B)
|
|
|
|
def fmr(D, pad, B, Rc):
|
|
if pad: return "<invalid>"
|
|
return "fmr%s" %("." * Rc), "f%i, f%i" %(D, B)
|
|
|
|
def fneg(D, pad, B, Rc):
|
|
if pad: return "<invalid>"
|
|
return "fneg%s" %("." * Rc), "f%i, f%i" %(D, B)
|
|
|
|
def mfspr(D, sprLo, sprHi, pad):
|
|
if pad: return "<invalid>"
|
|
sprnum = (sprHi << 5) | sprLo
|
|
if sprnum not in spr_table:
|
|
spr = "?"
|
|
else:
|
|
spr = spr_table[sprnum]
|
|
return "mf%s" %spr, "r%i" %D
|
|
|
|
def mtspr(S, sprLo, sprHi, pad):
|
|
if pad: return "<invalid>"
|
|
sprnum = (sprHi << 5) | sprLo
|
|
if sprnum not in spr_table:
|
|
spr = ihex(sprnum)
|
|
else:
|
|
spr = spr_table[sprnum]
|
|
return "mt%s" %spr, "r%i" %S
|
|
|
|
def lbz(value, addr): return "lbz", loadStore(value)
|
|
def lfd(value, addr): return "lfd", loadStore(value, "f")
|
|
def lfs(value, addr): return "lfs", loadStore(value, "f")
|
|
def lmw(value, addr): return "lmw", loadStore(value)
|
|
def lwz(value, addr): return "lwz", loadStore(value)
|
|
def lwzu(value, addr): return "lwzu", loadStore(value)
|
|
def lwarx(D, A, B, pad): return "lwarx", loadStoreX(D, A, B, pad)
|
|
def lwzx(D, A, B, pad): return "lwzx", loadStoreX(D, A, B, pad)
|
|
|
|
def or_(S, A, B, Rc):
|
|
if S == B:
|
|
return "mr%s" %("." * Rc), "r%i, r%i" %(A, S)
|
|
return "or%s" %("." * Rc), "r%i, r%i, r%i" %(A, S, B)
|
|
|
|
def ori(value, addr):
|
|
S, A, UIMM = decodeD(value)
|
|
if UIMM == 0:
|
|
return "nop"
|
|
return "ori", "r%s, r%s, %s" %(A, S, ihex(UIMM))
|
|
|
|
def oris(value, addr):
|
|
S, A, UIMM = decodeD(value)
|
|
return "oris", "r%s, r%s, %s" %(A, S, ihex(UIMM))
|
|
|
|
def rlwinm(value, addr):
|
|
S, A, SH, M, Rc = decodeX(value)
|
|
MB = M >> 5
|
|
ME = M & 0x1F
|
|
dot = "." * Rc
|
|
if SH == 0 and MB == 0 and ME == 31:
|
|
return "nop"
|
|
if MB == 0 and ME == 31 - SH:
|
|
return "slwi%s" %dot, "r%i, r%i, %i" %(A, S, SH)
|
|
if ME == 31 and SH == 32 - MB:
|
|
return "srwi%s" %dot, "r%i, r%i, %i" %(A, S, MB)
|
|
if MB == 0 and ME < 31:
|
|
return "extlwi%s" %dot, "r%i, r%i, %i,%i" %(A, S, ME + 1, SH)
|
|
#extrwi
|
|
if MB == 0 and ME == 31:
|
|
if SH >= 16:
|
|
return "rotlwi%s" %dot, "r%i, r%i, %i" %(A, S, SH)
|
|
return "rotrwi%s" %dot, "r%i, r%i, %i" %(A, S, 32 - SH)
|
|
if SH == 0 and ME == 31:
|
|
return "clrlwi%s" %dot, "r%i, r%i, %i" %(A, S, MB)
|
|
if SH == 0 and MB == 0:
|
|
return "clrrwi%s" %dot, "r%i, r%i, %i" %(A, S, 31 - ME)
|
|
#clrlslwi
|
|
return "rlwinm%s" %dot, "r%i, r%i, %i,%i,%i" %(A, S, SH, MB, ME)
|
|
|
|
def sc(value, addr):
|
|
if value & 0x3FFFFFF != 2:
|
|
return "<invalid>"
|
|
return "sc"
|
|
|
|
def stb(value, addr): return "stb", loadStore(value)
|
|
def stfd(value, addr): return "stfd", loadStore(value, "f")
|
|
def stfs(value, addr): return "stfs", loadStore(value, "f")
|
|
def stfsu(value, addr): return "stfsu", loadStore(value, "f")
|
|
def stmw(value, addr): return "stmw", loadStore(value)
|
|
def stw(value, addr): return "stw", loadStore(value)
|
|
def stwu(value, addr): return "stwu", loadStore(value)
|
|
def stbx(S, A, B, pad): return "stbx", loadStoreX(S, A, B, pad)
|
|
def stwx(S, A, B, pad): return "stwx", loadStoreX(S, A, B, pad)
|
|
def stwcx(S, A, B, pad): return "stwcx", loadStoreX(S, A, B, pad ^ 1)
|
|
|
|
def tw(TO, A, B, pad):
|
|
if pad: return "<invalid>"
|
|
if TO == 31 and A == 0 and B == 0:
|
|
return "trap"
|
|
|
|
if TO not in trap_condition_table:
|
|
condition = "?"
|
|
else:
|
|
condition = trap_condition_table[TO]
|
|
return "tw%s" %condition, "r%i, r%i" %(A, B)
|
|
|
|
opcode_table_ext1 = {
|
|
16: bclr,
|
|
528: bcctr
|
|
}
|
|
|
|
opcode_table_ext2 = {
|
|
0: cmp,
|
|
4: tw,
|
|
20: lwarx,
|
|
23: lwzx,
|
|
26: cntlzw,
|
|
28: and_,
|
|
32: cmpl,
|
|
54: dcbst,
|
|
150: stwcx,
|
|
151: stwx,
|
|
215: stbx,
|
|
266: add,
|
|
339: mfspr,
|
|
444: or_,
|
|
467: mtspr
|
|
}
|
|
|
|
opcode_table_float_ext1 = {
|
|
40: fneg,
|
|
72: fmr
|
|
}
|
|
|
|
def ext1(value, addr):
|
|
DS, A, B, XO, Rc = decodeX(value)
|
|
if not XO in opcode_table_ext1:
|
|
return "ext1 - %s" %bin(XO)
|
|
return opcode_table_ext1[XO](DS, A, B, Rc)
|
|
|
|
def ext2(value, addr):
|
|
DS, A, B, XO, Rc = decodeX(value)
|
|
if not XO in opcode_table_ext2:
|
|
return "ext2 - %s" %bin(XO)
|
|
return opcode_table_ext2[XO](DS, A, B, Rc)
|
|
|
|
def float_ext1(value, addr):
|
|
D, A, B, XO, Rc = decodeX(value)
|
|
if not XO in opcode_table_float_ext1:
|
|
return "float_ext1 - %s" %bin(XO)
|
|
return opcode_table_float_ext1[XO](D, A, B, Rc)
|
|
|
|
opcode_table = {
|
|
10: cmpli,
|
|
11: cmpi,
|
|
12: addic,
|
|
13: addic_,
|
|
14: addi,
|
|
15: addis,
|
|
16: bc,
|
|
17: sc,
|
|
18: b,
|
|
19: ext1,
|
|
21: rlwinm,
|
|
24: ori,
|
|
25: oris,
|
|
31: ext2,
|
|
32: lwz,
|
|
33: lwzu,
|
|
34: lbz,
|
|
36: stw,
|
|
37: stwu,
|
|
38: stb,
|
|
46: lmw,
|
|
47: stmw,
|
|
48: lfs,
|
|
50: lfd,
|
|
52: stfs,
|
|
53: stfsu,
|
|
54: stfd,
|
|
63: float_ext1
|
|
}
|
|
|
|
def disassemble(value, address):
|
|
opcode = value >> 26
|
|
if opcode not in opcode_table:
|
|
return "???"
|
|
instr = opcode_table[opcode](value, address)
|
|
if type(instr) == str:
|
|
return instr
|
|
return instr[0] + " " * (10 - len(instr[0])) + instr[1]
|