def assy_skip(self): s = self['skip'] d = self['d'] if d: s = 0x20 - s self.dstadr = self.lo - s else: self.dstadr = self.lo + s self += code.Jump(cond="?s", to=self.hi) self += code.Jump(cond="?!s", to=self.dstadr) return assy.Arg_dst(self.lang.m, self.dstadr)
def flow_switch(asp, ins): if ins.dstadr != 0x2f38: return ins.flow_out.pop(0) ins += code.Flow(cond="?") asp.set_label(ins.hi, "break_%04x" % ins.lo) y = data.Const(asp, ins.lo - 2, ins.lo) ncase = asp.bu16(ins.lo - 2) y.typ = ".NCASE" y.fmt = "%d" % ncase cs = switches.get(ins.lo) if cs is None: cs = {} a = ins.lo - 2 for i in range(ncase): a -= 2 ct = cs.get(i) if ct is None: ct = "_%d" % i w = data.Const(asp, a, a + 2) z = asp.bs16(a) w.typ = ".CASE" w.fmt = "0x%x, %d" % (i, z) w.fmt += ", 0x%04x" % (ins.hi + z) ins += code.Jump(cond="0x%x" % i, to=ins.hi + z) if z < 0: asp.set_label(ins.hi + z, ".case_%04x_%s" % (ins.lo, ct))
def post_arg_func(asp, ins): post_arg_funcs = { 0xb80c: "WB", 0xb821: "WB", 0xb836: "W", 0xb846: "WWW", 0xb86c: "WWW", 0xb892: "WWW", 0xb989: "WWW", 0xbabc: "WW", 0xbb60: "WWW", 0xbca1: "WWW", 0xbdeb: "WW", } for f in ins.flow_out: i = post_arg_funcs.get(f.to) if i is None: continue ins.flow_out = [] ins += code.Call(to=f.to) a = ins.hi for j in i: if j == "W": d = asp.bu16(a) data.Dataptr(asp, a, a + 2, d) a += 2 if d >= 0x8000: d_q(asp, d) elif j == "B": cbyte(asp, a) # data.Data(asp, a, a + 1) a += 1 else: assert False ins += code.Jump(to=a)
def assy_sw(self): ''' Decode switch table ''' dreg = self['dreg1'] if dreg != self['dreg2']: raise assy.Invalid() if dreg != self['dreg3']: raise assy.Invalid() ptr = self.hi fin = self.lang.m.bu16(self.hi) + self.hi n = 0 while ptr < fin: i = self.lang.m.bs16(ptr) d = self.hi + i if i > 0: fin = min(fin, d) self += code.Jump(cond="0x%x" % n, to=d) data.Const(self.lang.m, ptr, ptr + 2, size=2, func=self.lang.m.bu16) self.lang.m.set_line_comment(ptr, "[0x%x] -> 0x%x" % (n, d)) self.lang.m.set_label(d, "switch@0x%x[0x%x]" % (self.lo, n)) ptr += 2 n += 1 return "D%d.W" % dreg
def flow_check(asp, ins): ''' Flow-check to capture inline strings ''' if ins.lo in ( 0x8000001c, 0x80002010, 0x80002028, ): return for f in ins.flow_out: if f.to in ( 0x80002010, 0x80002028, 0x80002aa8 ): y = data.Txt(asp, ins.hi, label=False, align=2, splitnl=True) ins.dstadr = y.hi ins.flow_out.pop(-1) ins += code.Jump(cond=True, to=ins.dstadr) elif f.to in ( 0x80000018, ): if asp.bu16(ins.lo - 6) == 0x41f9: a = asp.bu32(ins.lo - 4) y = data.Txt(asp, a, splitnl=True) elif f.to in ( 0x80002034, ): if asp.bu16(ins.lo - 6) == 0x47f9: a = asp.bu32(ins.lo - 4) y = data.Txt(asp, a, splitnl=True) elif f.to in ( 0x8000001c, 0x800000e2 ): y = data.Txt(asp, ins.hi, label=False, align=2, splitnl=True) ins.dstadr = y.hi ins.flow_out.pop(-1) ins += code.Jump(cond=True, to=ins.dstadr) elif f.to in ( 0x80002068, ): if asp.bu16(ins.lo - 4) == 0x303c: a = asp.bu16(ins.lo - 2) t = RESHA_PROGRAMS.get(a) if t: asp.set_line_comment(ins.lo - 4, t)
def flow_post_arg(asp, ins): z = post_arg.get(ins.dstadr) if z is None: return ins.flow_out.pop(-1) if len(z) <= 1: a = data.Pstruct(asp, ins.hi, ">h", "%d", ".INFIX").hi ins += code.Jump(to=a) return l = [] for i in z[1:]: if i[1:] == "A6rel": r = asp.bs16(ins.hi) ins.hi += 2 if r < 0: l.append("(A6-0x%x)" % -r) else: l.append("(A6+0x%x)" % r) elif i[1:] == "abs": r = asp.bu16(ins.hi) if r & 0x8000: r |= 0xffff0000 ins.hi += 2 l.append("0x%08x" % r) elif i == "drel": r = ins.hi + asp.bs16(ins.hi) ins.hi += 2 ins.lcmt += " @0x%x\n" % r y = data_double(asp, r) l.append("%g" % y.data[0]) elif i == "brel": r = ins.hi + asp.bs16(ins.hi) ins.hi += 2 ins.lcmt += " @0x%x\n" % r y = data_bcd(asp, r) l.append("%x" % y.data[0]) elif i == "lrel": r = ins.hi + asp.bs16(ins.hi) ins.hi += 2 ins.lcmt += " @0x%x\n" % r if not asp.occupied(r): data.Pstruct(asp, r, ">L", "%d", ".LONG") l.append("%d" % asp.bu32(r)) elif i == "frel": r = ins.hi + asp.bs16(ins.hi) ins.hi += 2 ins.lcmt += " @0x%x\n" % r y = data_float(asp, r) l.append("%g" % y.val) elif i == "bcd": r = asp.bu16(ins.hi) # y = data.Pstruct(asp, ins.hi, ">H", "%x", ".BCD") l.append("%04x" % r) ins.hi += 2 else: l.append(i) ins.oper.append(assy.Arg_verbatim("(" + ",".join(l) + ")")) ins += code.Flow()
def switch(self, adr, end): setup = self.cx.disass(adr) dispatch = self.cx.disass(setup.hi) dispatch.flow_out = [] tbl = setup.dstadr for off in range(0, end - tbl, 2): dispatch += code.Jump(cond="A=0x%02x" % off, to=tbl + off) item = self.cx.disass(tbl + off) yield off, item, tbl
def fc_case(asp, ins, _arg): ins.flow_out.pop(-1) a = ins.lo - 1 n = asp[a] data.Const(asp, a, a + 1) while n < 65535: a -= 1 y = data.Const(asp, a, a + 1) ins += code.Jump(cond="?", to=asp[a]) n += 1
def attempt(self): l,w = recognize(self.pj, self.top, recog0) if type(w) != int: return False self.tbl = l[0].dstadr self.top = l[0].lo l,w = recognize(self.pj, self.top, recog1) if type(w) != int: s = [] j = self.top for i in range(10): x = self.pj.t.find_hi(j) if len(x) != 1: break s.insert(0, x[0].mne) j = x[0].lo s = ",".join(s) return False if w == 2: lo = self.pj.m[l[0].lo + 1] hi = self.pj.m.[l[2].lo + 1] d = l[-1].dstadr elif w == 3: lo = self.pj.m.bu16(l[0].lo + 1) hi = self.pj.m.bu16(l[2].lo + 1) d = l[-2].dstadr elif w == 4: lo = self.pj.m.bu16(l[3].lo + 1) hi = self.pj.m.bu16(l[0].lo + 1) d = l[-1].dstadr else: print("S1?? %04x" % self.top, w) return False l[-1].lcmt += "SWITCH type=%d lo=%d hi=%d\n" % (w, lo, hi) # print("S1 %04x" % self.top, w, lo, hi, "D", d) self.pj.m.set_label(d, "default") a = self.i.hi for i in range(lo, hi + 1): self.pj.cc_locs.add(a) self.pj.cc_locs.add(a + 1) u = self.pj.m.bu16(a) if u != d: self.pj.m.set_label(u, "case_%d" % i) self.i += code.Jump(cond="%d" % i, to=u, lang=self.i.lang) self.i.lang.disass(self.pj, u) a += 2 return True
def inline_args(asp, ins): for f in ins.flow_out: i = i_args.get(f.to) if i is None: continue ins.flow_out = [] ins += code.Call(to=f.to) a = ins.hi for j in i: if j == "i": d = asp.bu16(a) data.Dataptr(asp, a, a + 2, d) a += 2 else: print("IARG:", j) assert False ins += code.Jump(to=a)
def jmp_table(lo, hi, span, txt="table", src=None): x = cx.m.add_range(lo, hi, txt="table") if src is None: ins = None else: ins = list(cx.m.find(src)) print("JMPTABLE %x" % src, ins) if len(ins) != 1: ins = None else: ins = ins[0] assert len(ins.flow_out) == 1 ins.flow_out = list() for a in range(lo, hi, span): if ins is not None: ins += code.Jump(to=a) cx.disass(a)
def assy_SW(self): assert self.lim[-1].assy[0] == "SWITCH" # All dr%d must match rset = set() for i in self.lim: for j in i.flds: if j[:2] == "dr": rset.add(i[j]) if len(rset) > 1: raise assy.Invalid("SWITCH dr# mismatch") self.mne = "SWITCH(D%d.%s)" % (rset.pop(), self.sz) if len(self.lim) < 3: raise assy.Invalid("SWITCH with insufficient limits") if self.lim[-2].assy[0] != "+DBL": raise assy.Invalid("SWITCH without +DBL") self.sz = set() for im in self.lim: def getfld(x): fl = im.get(x + 'l') if fl is not None: fh = im.get(x + 'h') if fh is not None: fl |= fh << 16 if fl & 0x80000000: fl -= 0x100000000 elif fl & 0x8000: fl -= 0x10000 return fl def getjmp(): j = im.get('j') if j is not None: if j & 0x80: j -= 0x100 return im.adr + j + int(im.assy[2]) j = im.get('jj') if j is not None: if j & 0x8000: j -= 0x10000 return im.adr + j + int(im.assy[2]) self.sz.add(im.assy[1]) if im.assy[0] == "+LOW": x = getfld('l') if x is not None: self.low = x x = getfld('s') if x is not None: self.sub = x x = getfld('a') if x is not None: self.add = x if im.assy[1] == 'L': m = (1 << 32) - 1 else: m = (1 << 16) - 1 assert self.sub == (self.low + self.add) & m self.go_lo = getjmp() elif im.assy[0] == "+HIGH": x = getfld('h') if x is not None: self.high = x self.go_hi = getjmp() if self.low is None and self.high is not None: self.low = 0 if self.low is None or self.high is None: print("XXX %x" % self.lo, self) for i in self.lim: print("--- %s" % str(i)) print("LOW", self.low, "HIGH", self.high) raise assy.Invalid() self.nm = "SWITCH_%x" % self.lo self.lang.m.set_label(self.lo, self.nm) self.wordtable() self.range() self += code.Jump()
def assy_skp(self): self += code.Jump(cond="?", to=self.hi) self += code.Jump(cond="?", to=self.hi + 1)
def example(): m0 = mem.Stackup(FILENAMES, nextto=__file__) cx = hp_nanoproc.hp_nanoproc_pg() # Slightly confusing mapping of memory for this one. Probably an # artifact of a change from smaller to bigger ROMS along the way. cx.m.map(m0, 0x0000, 0x1000) cx.m.map(m0, 0x2000, 0x3000, 0x1000) cx.m.map(m0, 0x1000, 0x2000, 0x2000) cx.m.map(m0, 0x3000, 0x4000, 0x3000) cx.disass(0) cx.disass(0xff) cuts = [] ####################################################################### if True: for a0 in range(4, 0x20, 4): cx.disass(a0) ix0 = list(cx.m.find(0x54)) assert len(ix0) == 1 ix0 = ix0[0] ix0.flow_out = list() for a0 in range(4, 0x20, 4): ix0 += code.Jump(to=a0) i = list(cx.m.find(a0)) assert len(i) == 1 i = i[0] assert len(i.flow_out) == 1 dpf = i.flow_out[0].to cuts.append((None, dpf)) ix1 = list(cx.m.find(dpf + 6)) assert len(ix1) == 1 ix1 = ix1[0] ix1.flow_out = list() pg = dpf & ~0x7ff print("DISP_%d %x" % (a0 >> 2, dpf)) cx.m.set_label(dpf, "DISP_%d" % (a0 >> 2)) for a1 in range(pg, dpf, 2): ix1 += code.Jump(to=a1) cx.disass(a1) v = a0 << 3 v |= (a1 - pg) >> 1 cx.m.set_label(a1, "PTR_%02x" % v) ####################################################################### def jmp_table(lo, hi, span, txt="table", src=None): x = cx.m.add_range(lo, hi, txt="table") if src is None: ins = None else: ins = list(cx.m.find(src)) print("JMPTABLE %x" % src, ins) if len(ins) != 1: ins = None else: ins = ins[0] assert len(ins.flow_out) == 1 ins.flow_out = list() for a in range(lo, hi, span): if ins is not None: ins += code.Jump(to=a) cx.disass(a) if True: jmp_table(0x07d0, 0x0800, 8, "table", 0x007f) jmp_table(0x0f80, 0x0fa8, 4, "LED segment table", 0xd0e) jmp_table(0x0fa8, 0x0fc0, 2, "table", 0x0aae) jmp_table(0x0fc0, 0x0fe0, 4, "table", 0x0b2e) jmp_table(0x0fe0, 0x1000, 4, "table", 0x0b49) jmp_table(0x1840, 0x1870, 8, "table", 0x1b2e) jmp_table(0x1fd0, 0x2000, 8, "table", 0x1d01) jmp_table(0x2fb8, 0x3000, 8, "table", 0x2f86) jmp_table(0x3fd8, 0x4000, 4, "table", 0x3d17) return NAME, (cx.m, )