def assy_inltxt(self): y = data.Txt(self.lang.m, self.lo + 2, label=False, splitnl=True, align=2) self.lang.disass(y.hi) raise assy.Invalid("Inline text hack")
def assy_MM(self, pj): mm = self.get('mm') if mm == 0: return self.assy_M2(pj, "Z") if mm == 6: return self.assy_M2(pj, "C") if mm == 7: return self.assy_M2(pj, "D") raise assy.Invalid()
def assy_subr(self): ''' ... ''' adr = self['x'] + 0x18 self.dstadr = self.lang.m[adr] if not self.dstadr: raise assy.Invalid() self.lang.codeptr(adr) self.lang.subrs.add(self.dstadr) return assy.Arg_dst(self.lang.m, self.dstadr)
def __init__(self, lim, lang): super().__init__(lim, lang) if self.lo & 1: raise assy.Invalid("Odd Address") self.ea = {} self.isz = "i32" self.icache = {} self.ea_fullext = lang.ea_fullext self.ea_scale = lang.ea_scale
def assy_Z(self, pj): if self['sz'] == 3: raise assy.Invalid('0x%x F_sz == 3' % self.lo) i, j = [ [1, ".B"], [2, ".W"], [4, ".L"], ] [self['sz']] self.sz = i self.mne += j
def assy_Ctl(self): n = { 0x2: "FCW", 0x3: "REFRESH", 0x4: "PSAPSEG", 0x5: "PSAPOFF", 0x6: "NSPSEG", 0x7: "NSPOFF", }.get(self['ctl']) if n: return n raise assy.Invalid("CTL REG 0x%x" % self['ctl'])
def assy_Z(self): if self['sz'] == 3: raise assy.Invalid('0x%x F_sz == 3' % self.lo, self.lim) i, j, m = [ [1, ".B", 0xff], [2, ".W", 0xffff], [4, ".L", 0xffffffff], ][self['sz']] self.sz = i self.isz = "i%d" % (i * 8) self.imsk = m self.mne += j
def __init__(self, lim, lang): super().__init__(lim, lang) if self.lo & 1: raise assy.Invalid("Odd Address") self.go_lo = None self.go_hi = None self.low = None self.high = None self.sub = 0 self.add = 0 self.reg = None self.nm = "SWITCH_%x" % self.lo self.sz = None
def assy_BARE(self): assert self.lim[-1].assy[0] == "SWITCH" if len(self.lim) != 1: raise assy.Invalid("BARE switch with prefix") a = self.hi top = 512 # XXX Safety, may be too small n = 0 while True: d = self.lang.m.bs16(self.hi + n * 2) if d < 0: raise assy.Invalid("BARE switch with (too) negative offset") top = min(d, top) a += 2 n += 1 if n * 2 >= top: break self.low = 0 self.high = n - 1 self.wordtable() raise assy.Invalid()
def assy_dst(self): x = self['disp8'] if x == 0x00: self.dstadr = self.hi + self.lang.m.bs16(self.hi) self.hi += 2 elif x == 0xff: self.dstadr = self.hi + self.lang.m.bs32(self.hi) self.hi += 4 elif x & 0x01: raise assy.Invalid("Odd numbered destination address") elif x & 0x80: self.dstadr = self.hi + x - 0x100 else: self.dstadr = self.hi + x return assy.Arg_dst(self.lang.m, self.dstadr)
def assy_a_rnrm(self): rn = REG[self['rn']] rm = REG[self['rm']] if not self['u']: rm = "-" + rm p = self.lim[-1].flds.get('p') w = self.lim[-1].flds.get('w') if not p: if not w: return "[%s]," % rn + rm raise assy.Invalid("a_imm4 mode wrong (!p,w)") if w: return "[%s," % rn + rm + "]!" return "[%s," % rn + rm + "]"
def assy_a_rn(self): ''' Addressing mode Rn/U/P/W ''' imm32 = self['imm12'] rn = REG[self['rn']] if self['u']: imm = "#0x%x" % imm32 else: imm = "#-0x%x" % imm32 p = self.lim[-1].flds.get('p') w = self.lim[-1].flds.get('w') if not p: if not w: #return [assy.Arg_verbatim("[%s]" % rn), assy.Arg_dst(self.lang.m, imm)] return "[%s]," % rn + imm raise assy.Invalid("a_rn mode wrong (!p,w)") if w: return "[%s," % rn + imm + "]!" if self['rn'] != 15 or OBJDUMP_COMPAT: if imm32: return "[%s," % rn + imm + "]" return "[%s]" % rn if self['u']: t = self.hi + 4 + imm32 else: t = self.hi + 4 - imm32 try: v = self.lang.m.lu32(t) if not self.lang.m.occupied(t): data.Const(self.lang.m, t, t + 4, func=self.lang.m.lu32, size=4) self.lcmt += "[%s,%s] = [#0x%x]\n" % (rn, imm, t) return assy.Arg_dst(self.lang.m, v, pfx="#") return "#0x%x" % v except: self.lcmt += "[%s,%s]\n" % (rn, imm) return "[#0x%x]" % t
def pilfunc_MOVEM_MR(self, arg): ll = [] eam = self['ea'] >> 3 if eam == 3: sr = "%%A%d" % (self['ea'] & 7) for r in self.subr_rlist(): if r == sr[1:]: ll += [ [sr, "=", "add", "i32", sr, ",", "%d" % self.sz], ] continue ll += [ ["%" + r, "=", "load", self.isz, ",", self.isz + "*", sr], [sr, "=", "add", "i32", sr, ",", "%d" % self.sz], ] if self.sz == 4: continue ll += [ ["%" + r, "=", "sext", self.isz, "%" + r, "to", "i32"], ] elif eam == 4: raise assy.Invalid("0x%x MOVEM m->r postincrement" % (self.lo)) else: x = self.pilmacro_PTR_EA() ll += [ ["%0", "=", self.isz + "*", x], ] for r in self.subr_rlist(): ll += [ [ "%" + r, "=", "load", self.isz, ",", self.isz + "*", "%0" ], ["%0", "=", "add", "i32", "%0", ",", "%d" % self.sz], ] if self.sz == 4: continue ll += [ ["%" + r, "=", "sext", self.isz, "%" + r, "to", "i32"], ] self.add_il(ll)
def assy_a_imm5(self): ''' Addressing mode Rn/U/P/W/imm5 ''' shf = self.assy_sh() if shf is None: shf = "" else: shf = "," + shf rn = REG[self['rn']] rm = REG[self['rm']] if not self['u']: rm = "-" + rm p = self.lim[-1].flds.get('p') w = self.lim[-1].flds.get('w') if p: if w: return "[%s,%s%s]!" % (rn, rm, shf) return "[%s,%s%s]" % (rn, rm, shf) else: if not w: return "[%s],%s%s" % (rn, rm, shf) raise assy.Invalid("a_imm5 mode wrong (!p,w)")
def assy_pushtxt(self): ''' XXX: Use PIL instead ? ''' if len(self.lim) == 5 and self.lim[0].assy[0] == "+PTA": sreg = self.lim[0]['sreg'] lim = self.lim[-4:] off = self.lo + 4 elif len(self.lim) == 4: sreg = 7 lim = self.lim off = self.lo + 2 else: raise assy.Invalid() for i, j in zip(lim, ("+PTB", "+PTC", "+PTD", "PUSH")): if i.assy[0][:4] != j: raise assy.Invalid() if lim[0]['areg'] != lim[2]['areg']: raise assy.Invalid() if lim[1]['dreg'] != self['dreg']: raise assy.Invalid() if lim[2]['sreg'] != sreg: raise assy.Invalid() adr = off + lim[0]['x'] - (1 << 16) length = lim[1]['y'] + 1 length *= { 'B': 1, 'W': 2, 'L': 4, }[lim[2].assy[0][4]] if lim[2].assy[0][-1] == '-': adr -= length elif lim[2].assy[0][-1] != '+': raise assy.Invalid() for i in range(adr, adr + length): j = self.lang.m[i] if 32 <= j <= 126: pass elif j in (9, 10, 13): pass else: print("BAD char 0x%02x" % j) raise assy.Invalid() y = data.Txt(self.lang.m, adr, adr + length, label=False) return '"' + y.txt + '"'
def assy_a_imm4(self): imm32 = (self['imm4h'] << 4) | self['imm4l'] if self['u']: imm = "#0x%x" % imm32 else: imm = "#-0x%x" % imm32 p = self.lim[-1].flds.get('p') w = self.lim[-1].flds.get('w') rn = REG[self['rn']] if not p: if not w: return "[%s]," % rn + imm raise assy.Invalid("a_imm4 mode wrong (!p,w)") if w: return "[%s," % rn + imm + "]!" if True or self['rn'] != 15 or OBJDUMP_COMPAT: if imm32: return "[%s," % rn + imm + "]" return "[%s]" % rn if self['u']: t = self.hi + 4 + imm32 else: t = self.hi + 4 - imm32 try: v = self.lang.m.lu32(t) if not self.lang.m.occupied(t): data.Const(self.lang.m, t, t + 4, func=self.lang.m.lu32, size=4) self.lcmt += "[%s,%s] = [#0x%x]\n" % (rn, imm, t) return "#0x%x" % v except: self.lcmt += "[%s,%s]\n" % (rn, imm) return "[#0x%x]" % t
def isubr_LEA(self, arg, which): if not which in self.ea: raise assy.Invalid("0x%x No '%s' in EA" % (self.lo, which)) il = self.ea[which] if len(il) == 1: self.add_il([ [il[0], "=", self.isz, arg[0]], ]) return assert len(il) == 2 j = self.icache.get("EA" + which) if j is None: self.icache["EA" + which] = il[0] ll = [] ll += il[1] ll.append( ["store", self.isz, arg[0], ",", self.isz + "*", il[0]], ) self.add_il(ll) else: self.add_il([ ["store", self.isz, arg[0], ",", self.isz + "*", j], ])
def assy_eaxt(self, pj, ref): ew = pj.m.bu16(self.hi) self.hi += 2 if ew & 0x8000: reg = "+A" else: reg = "+D" reg = reg + "%d" % ((ew >> 12) & 7) if ew & 0x800: wl = ".L" else: wl = ".W" sc = 1 << ((ew >> 9) & 3) if ew & 0x100: print("0x%x FULL EXT WORD" % self.lo, self) raise assy.Invalid("FULL EXT WORD") else: d = ew & 0xff if d & 0x80: d -= 0x100 s = "(" if ref == "PC": s += "#0x%x" % (d + self.hi - 2) elif d != 0: s += "#0x%x+" % d + ref else: s += ref s += reg + wl if sc > 1: s += "*%d" % sc s += ")" return s
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_rp(self): rp = self['rp'] if rp == 3: raise assy.Invalid('0x%x RP=3' % self.lo) return ('BC', 'DE', 'HL')[rp]
def assy_ea(self): try: j = self['ea'] except KeyError as e: raise assy.Invalid("0x%x no EA?" % self.lo, e, self.lim) return self.assy_eax("s", j >> 3, j & 7)
def assy_eax(self, id, eam, ear): il = [] self.ea[id] = il eax = 1 << eam if eax > 0x40: eax = 0x100 << ear eamask = int(self.im.assy[-1], 16) if not eax & eamask: raise assy.Invalid( "0x%x Wrong EA mode m=%d/r=%d" % (self.lo, eam, ear), self.im) if eax == 0x0001: il += ["%%D%d" % ear] return "D%d" % ear if eax == 0x0002: il += ["%%A%d" % ear] return "A%d" % ear if eax == 0x0004: il += ["%%A%d" % ear, []] return "(A%d)" % ear if eax == 0x0008: r = "A%d" % ear il += [ "%0", [ ["%0", "=", self.isz + "*", "%" + r], ["%" + r, "=", "add", "i32", "%" + r, ",", "%d" % self.sz], ] ] return "(A%d)+" % ear if eax == 0x0010: '''Address Register Indirect with Predecrement''' r = "A%d" % ear il += [ "%0", [ ["%" + r, "=", "sub", "i32", "%" + r, ",", "%d" % self.sz], ["%0", "=", "i32", "%" + r], ] ] return "-(%s)" % r if eax == 0x0020: '''Address Register Indirect with Displacement''' o = self.lang.m.bs16(self.hi) self.hi += 2 if o < 0: il += [ "%0", [ [ "%0", "=", "sub", self.isz + "*", "%%A%d" % ear, ",", "0x%x" % -o ], ] ] return "(A%d-0x%x)" % (ear, -o) else: il += [ "%0", [ [ "%0", "=", "add", self.isz + "*", "%%A%d" % ear, ",", "0x%x" % o ], ] ] return "(A%d+0x%x)" % (ear, o) if eax == 0x0040: return self.assy_eaxt(id, "A%d" % ear) if eax == 0x0100: o = self.lang.m.bu16(self.hi) self.hi += 2 if o & 0x8000: o |= 0xffff0000 self.dstadr = o il += ["0x%x" % o, []] return assy.Arg_dst(self.lang.m, o) if eax == 0x0200: o = self.lang.m.bu32(self.hi) self.hi += 4 self.dstadr = o il += ["0x%x" % o, []] return assy.Arg_dst(self.lang.m, o) if eax == 0x0400: o = self.hi + self.lang.m.bs16(self.hi) self.hi += 2 self.dstadr = o il += ["0x%x" % o, []] return assy.Arg_dst(self.lang.m, o) if eax == 0x0800: return self.assy_eaxt(id, "PC") if eax == 0x1000 and self.sz == 1: v = self.lang.m[self.hi + 1] self.hi += 2 il += ["0x%x" % v] return "#0x%02x" % v if eax == 0x1000 and self.sz == 2: v = self.lang.m.bu16(self.hi) self.hi += 2 il += ["0x%x" % v] return "#0x%04x" % v if eax == 0x1000 and self.sz == 4: v = self.lang.m.bu32(self.hi) self.hi += 4 il += ["0x%x" % v] return "#0x%08x" % v raise assy.Invalid("0x%x EA? 0x%04x m=%d/r=%d" % (self.lo, eax, eam, ear))
def __init__(self, lim, lang): super().__init__(lim, lang) if not isswitch(lim): raise assy.Invalid("NOT a switch construction (order)")
def fail(why): print("FAIL", why) raise assy.Invalid(why)
def assy_not(self): def fail(why): print("FAIL", why) raise assy.Invalid(why) ri = self.lim[0]['rn'] nswitch = self.lim[0]['imm12'] # XXX: default dst from lim[1] rd = self.lim[2]['rd'] if self.lim[-1].assy[0] != "ADD": fail("NOT A switch construction (!add)") if self.lim[-1]['rm'] != rd: fail("NOT A switch construction (rd/add/rm)") if self.lim[-1]['imm5'] != 2: fail("NOT A switch construction (add/imm5)") txt = '' if self.lim[3].assy[0] == "+LSL": # 16 bit if len(self.lim) != 6: fail("NOT A switch construction (16b/len)") if self.lim[2]['imm12'] != 8: fail("NOT A switch construction (16b/2imm12)") if self.lim[3].assy[0] != "+LSL": fail("NOT A switch construction (16b/!lsl)") if self.lim[4].assy[0] != "+LDRH": fail("NOT A switch construction (16b/!ldrh)") switchblock_16(self.hi, nswitch, self.lang) raise assy.Invalid("done 16bit switch") else: # 8 bit if len(self.lim) != 5: fail("NOT A switch construction (8b/len)") if self.lim[2]['imm12'] != 4: fail("NOT A switch construction (8b/2imm12)") if self.lim[3].assy[0] != "+LDRB": fail("NOT A switch construction (8b/!ldrb)") if self.lim[3]['rm'] != ri: fail("NOT A switch construction (ri/3rm)") if self.lim[3]['rn'] != rd: fail("NOT A switch construction (rd/3rn)") if self.lim[3]['rt'] != rd: fail("NOT A switch construction (rd/3rt)") switchblock_8(self.hi, nswitch, self.lang) raise assy.Invalid("done 8bit switch") fail("NOTYET")
def assy_eaxt(self, pj, id, ref): '''Extension Word Controlled Address Mode''' il = self.ea[id] iltyp = self.isz + "*" ll = [None] ew = pj.m.bu16(self.hi) if ew & 0x100: print("0x%x FULL EXT WORD" % self.lo, self) raise assy.Invalid("FULL EXT WORD") if ew & 0x600: print("0x%x Non-zero SCALE" % self.lo, self) raise assy.Invalid("BAD BRIEF EXT WORD") self.hi += 2 if ew & 0x8000: reg = "A" else: reg = "D" reg = reg + "%d" % ((ew >> 12) & 7) if ew & 0x800: wl = ".L" ll.append(["%2", "=", iltyp, "%" + reg]) else: ll.append(["%1", "=", "trunc", "i32", "%" + reg, "to", "i16"]) ll.append(["%2", "=", "sext", "i16", "%1", "to", iltyp]) wl = ".W" ll[0] = "%2" scl = (ew >> 9) & 3 sc = 1 << scl if scl != 0: ll.append(["%3", "=", "shl", iltyp, "%0", ",", "%d" % scl]) ll[0] = "%3" d = ew & 0xff if d & 0x80: d -= 0x100 if d > 0: ll.append(["%4", "=", "add", iltyp, ll[0], ",", "0x%x" % d]) ll[0] = "%4" if d < 0: ll.append(["%4", "=", "sub", iltyp, ll[0], ",", "0x%x" % -d]) ll[0] = "%4" ll.append(["%5", "=", "add", iltyp, ll[0], ",", "%" + ref]) ll[0] = "%5" s = "(" if ref == "PC": s += "#0x%x" % (d + self.hi - 2) elif d != 0: s += "#0x%x+" % d + ref else: s += ref s += "+" + reg + wl if sc > 1: s += "*%d" % sc s += ")" il += [ll[0], ll[1:]] return s
def __init__(self, lim, lang): super().__init__(lim, lang) if self['cid'] != 1: raise assy.Invalid("FP cid != 1")
def assy_d(self): ''' Select {DAT}d ''' d = self['d'] if d > 4: raise assy.Invalid("R4 is last register") self.mne = self.mne.replace('d', '%d' % self['d'])
def assy_eaxt_f(self, id, ref, ew): '''Full Extension Word Controlled Address Mode''' self.lcmt += " LEW=%04x" % ew nobase = 0 noidx = 0 pc = self.hi - 2 if ew & 0x47 in (0x04, 0x44, 0x45, 0x46, 0x47): raise assy.Invalid( "0x%x EA-FEW 0x%04x IS+I/IS reserved" % (self.lo, ew), self.im) if not (ew & 0x30): raise assy.Invalid("0x%x EA-FEW 0x%04x BD=0" % (self.lo, ew), self.im) if ref != "PC" and not (ew & 0x80): # Base Supress lan = [ref] else: lan = [] if ew & 0x8000: reg = "A" else: reg = "D" reg = reg + "%d" % ((ew >> 12) & 7) if ew & 0x800: wl = ".L" else: wl = ".W" xr = reg + wl scale = (ew >> 9) & 3 if scale: xr += "*%d" % (1 << scale) if not (ew & 0x40): # Index Supress lxr = [xr] else: lxr = [] bd = (ew >> 4) & 3 if bd == 2: basedisp = self.lang.m.bs16(self.hi) self.hi += 2 elif bd == 3: basedisp = self.lang.m.bu32(self.hi) self.hi += 4 else: basedisp = 0 if ref == "PC" and not (ew & 0x80): # Base Supress basedisp += pc if ew & 2: if ew & 1: outherdisp = self.lang.m.bu32(self.hi) self.hi += 4 else: outherdisp = self.lang.m.bs16(self.hi) self.hi += 2 else: outherdisp = 0 if not (ew & 7): # No index s = "(" + "+".join(lan + lxr) if basedisp < 0: s += "-#%x" % (-basedisp) elif basedisp and s == "(": s += "#%x" % basedisp elif basedisp: s += "+#%x" % basedisp s += ")" else: if ew & 4: # Post index s = "((" + lan[0] if basedisp < 0: s += "-#%x" % (-basedisp) elif basedisp and s == "((": s += "#%x" % basedisp elif basedisp: s += "+#%x" % basedisp s += ")" if lxr: s += "+" + lxr[0] else: # Pre index s = "((" + "+".join(lan + lxr) if basedisp < 0: s += "-#%x" % (-basedisp) elif basedisp and s == "((": s += "#%x" % basedisp elif basedisp: s += "+#%x" % basedisp s += ")" if outherdisp < 0: s += "-#%x" % (-outherdisp) elif outherdisp: s += "+#%x" % outherdisp s += ")" IS = (ew >> 6) & 1 IIS = (ew & 7) il = self.ea[id] iltyp = self.isz + "*" ll = [None] if ew & 0x800: wl = ".L" ll.append(["%2", "=", iltyp, "%" + reg]) else: ll.append(["%1", "=", "trunc", "i32", "%" + reg, "to", "i16"]) ll.append(["%2", "=", "sext", "i16", "%1", "to", iltyp]) wl = ".W" ll[0] = "%2" if scale != 0: ll.append(["%3", "=", "shl", iltyp, "%0", ",", "%d" % scale]) ll[0] = "%3" if basedisp > 0: ll.append(["%4", "=", "add", iltyp, ll[0], ",", "0x%x" % basedisp]) ll[0] = "%4" if basedisp < 0: ll.append( ["%4", "=", "sub", iltyp, ll[0], ",", "0x%x" % -basedisp]) ll[0] = "%4" ll.append(["%5", "=", "add", iltyp, ll[0], ",", "%" + ref]) ll[0] = "%5" il += [ll[0], ll[1:]] return s
def assy_L(self): if self.sz not in ('L', None): raise assy.Invalid("Inconsitent width in SWITCH") self.sz = 'L'