#! /usr/bin/python # encoding: utf-8 # completely untested import sys, numpy from l3dis import l3dis class l3trigger: # 1 S N C S C cond = ( 1, 0, 1, 0, # 0 0 1, 0, 0, 1, # 0 1 1, 1, 1, 0, # 1 0 1, 1, 0, 1, # 1 1 ) verbose = 1 logtable = ( 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0010, 0b0010, 0b0010, 0b0010, 0b0010, 0b0010, 0b0011, 0b0011, 0b0011, 0b0011, 0b0011, 0b0011, 0b0100, #this should be 0011 0b0100, 0b0100, 0b0100, 0b0100, 0b0100, 0b0100, 0b0101, 0b0101, 0b0101, 0b0101, 0b0101, 0b0101, 0b0101, 0b0110, 0b0110, 0b0110, 0b0110, 0b0110, 0b0110, 0b0110, 0b0110, 0b0111, 0b0111, 0b0111, 0b0111, 0b0111, 0b0111, 0b0111, 0b0111, 0b1000, 0b1000, 0b1000, 0b1000, 0b1000, 0b1000, 0b1000, 0b1000, 0b1001, 0b1001, 0b1001, 0b1001, 0b1001, 0b1001, 0b1001, 0b1001, 0b1010, 0b1010, 0b1010, 0b1010, 0b1010, 0b1010, 0b1010, 0b1010, 0b1010, 0b1011, 0b1011, 0b1011, 0b1011, 0b1011, 0b1011, 0b1011, 0b1011, 0b1011, 0b1100, 0b1100, 0b1100, 0b1100, 0b1100, 0b1100, 0b1100, 0b1100, 0b1100, 0b1101, 0b1101, 0b1101, 0b1101, 0b1101, 0b1101, 0b1101, 0b1101, 0b1101, 0b1101, 0b1110, 0b1110, 0b1110, 0b1110, 0b1110, 0b1110, 0b1110, 0b1110, 0b1110, 0b1110, 0b1111, #this should be 1110 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, ) def __init__(self): self.code = numpy.zeros((1024,), "uint32") self.regs = numpy.zeros((256,), "uint32") self.flags = 0 self.last = 0 def load(self, f): for l in f: if l[0]=='@': ll = l[1:].split() a = int(ll[0],16) d = int(ll[1],16) self.code[a]=d def run(self, cls, pha): for i, p in enumerate(pha): self.regs[i+0xe0] = p if self.verbose>=3: sys.stderr.write("pha[%d]=0x%08x\n" % (i+0xe0, p)) a = cls<<8; while True: i = self.code[a] if self.verbose>=3: slast = self.last-0x20000000 if self.last & 0x10000000 else self.last sys.stderr.write("last=0x%08x=%-10d C=%d S=%d " % (self.last, slast, self.flags&1, self.flags>>1)) cc = (i>>30) | (self.flags<<2) if not self.cond[cc]: self.regs[a & 0xff] = self.last if self.verbose>=2: sys.stderr.write(l3dis(i, addr=a, form='skip @%(page)d:%(target)-03d %(cond)-3s %(mnem)-5s %(args)s\n')) a += 1 continue op = (i>>24) & 0b111111 if self.verbose>=2: sys.stderr.write(l3dis(i, addr=a, form=' @%(page)d:%(target)-03d %(cond)-3s %(mnem)-5s %(args)s\n')) if op & 0b100000 or op==0b000111: # ADDI/PHA Rx + c x = self.regs[i&0xff] c = (i>>8) & 0x1fffff if op & 0b100000: if c & 0x100000: c |= 0x3ff00000 else: c &= 0x000fffff else: c &= 0x0000ffff c += x if c & 0x10000000 and not c & 0x20000000: c = 0x0fffffff elif not c & 0x10000000 and c & 0x20000000: c = 0x30000000 else: c &= 0x3fffffff self.last = c self.regs[a & 0xff] = c if not op & 0b100000: self.pha(c) a += 1 continue if op & 0b010000: # CMP x <=> y x = self.regs[i&0xff] y = self.regs[(i>>16)&0xff] self.last = x self.regs[a & 0xff] = x c = (i>>8)&0xff if op & 0b001000: y += c else: x += c d = x - y ccc = 0 if d & 0x20000000: ccc |= 1 elif d==0: ccc |= 2 else: ccc |= 4 if ccc & op: self.flags |= 1 else: self.flags &= 2 a += 1 continue if (op & 0b1010) == 0b1000: # ADD/SUB/HIST Rx<>16)&0xff] sx = (i>>8) & 0xf sy = (i>>12) & 0xf if x & 0x10000000: x |= 0x1ffff0000000 if y & 0x10000000: y |= 0x1ffff0000000 if sx&8: x <<= 16-sx else: x >>= sx if sy&8: y <<= 16-sy else: y >>= sy if op & 1: c = x-y else: c = x+y if c & 0x2000000000 and not (c & 0x1ff0000000)==0x1ff0000000: c = 0x30000000 elif not c & 0x2000000000 and c & 0x1ff0000000: c = 0x0fffffff else: c &= 0x3fffffff self.last = c self.regs[a & 0xff] = c if op & 0b0100: self.hist(c) a += 1 continue if op == 0b000110: # MULI Rx*c >> s x = self.regs[i&0xff] & 0x1fffffff c = (i>>8) & 0xfff s = (i>>20) & 0xf if x & 0x10000000: x -= 0x20000000 c *= x c >>= s if c<0: c += 0x20000000 c &= 0x1fffffff self.last = c self.regs[a & 0xff] = c a += 1 continue if op == 0b000001: # LOG Rx x = ((self.regs[i&0xff] & 0x1fffffff)<<8) | 0b01111111 b = 0 while x >= 0x10000: b += 8; x >>= 8; while x >= 0x100: b += 1; x >>= 1; if b==29: c = 0 else: c = (b<<4) | self.logtable[x&0x7f] self.last = c self.regs[a & 0xff] = c a += 1 continue if op == 0b000101: # TRIM Rx, m, r x = self.regs[i&0xff] m = (i>>8) & 0xff r = (i>>16) & 0xff if x>8)&31 l = (i>>13)&31 if f <= l: c = x & ((1<<(l+1))-1) & ~((1<>20)&0xf if (cccc&3)==0: r = (i>>8)&0x1f c = (x>>r) & 1 elif (cccc&3)==1: c = self.flags&1 elif (cccc&3)==2: c = self.flags>>1 else: c = 0; if cccc&8: c = 1-c if cccc&4: self.flags = self.flags&1 | (c<<1) else: self.flags = self.flags&2 | c a += 1 continue # The simulation is not exact here. The hardware will use # this R[x] in the next two instructions via fastpath for # R[a], but later instructions will find the old value. # Do not use the POKE result register unless you know what # you are doing. if op == 0b000010: # POKE Rd = Rx x = self.regs[i&0xff] d = (i>>8)&0xff self.last = x self.regs[d] = x a += 1 continue if op == 0b000000: self.regs[a & 0xff] = self.last if not i & 0x800000: break if i & 0x400000: a = (i>>8)&0x3ff else: a += 1 continue raise ValueError("illegal opcode 0x%08x\n" % i) def hist(self, c): sys.stdout.write("HIST 0x%06x\n" % c) def pha(self, c): sys.stdout.write("PHA %2d 0x%02x\n" % (c&15, c>>4)) def l3sim_main(): from getopt import getopt import fileinput opts,files = getopt(sys.argv[1:], "f:e:vq") l3 = l3trigger() for o,v in opts: if o=='-f': f = open(v) l3.load(f) f.close() if o=='-e': tt = [int(ttt,0) for ttt in v.split()] l3.run(tt[0], tt[1:]) if o=='-v': l3.verbose = l3.verbose+1 if o=='-q': l3.verbose = l3.verbose-1 for t in fileinput.input(files): tt = [int(ttt,0) for ttt in t.split()] l3.run(tt[0], tt[1:]) if __name__ == '__main__': l3sim_main()