/ analysis / emu / emu-timer-1ba8.py
emu-timer-1ba8.py
  1  #!/usr/bin/env python3
  2  
  3  from mcu import Operation, Microcontroller
  4  
  5  display = []
  6  #getc = [ord(c) for c in reversed("5\n23\nC\nasdf\nasdf\n")]
  7  getc = [ord(c) for c in reversed("5\n23\n42\n13\nY\n")]
  8  
  9  def flush_display(trace):
 10      global display
 11      if display == []: return
 12      if not trace:
 13          print("display:", repr(''.join(display)))
 14      display = []
 15  
 16  def putc(c):
 17      c = int(mcu.mem.a)
 18      if c & 0x80: # unescaping in case we come from putc_raw
 19          c = 0x40 | (c & 0x3f)
 20      print(f"putc({repr(chr(c))})")
 21  
 22  pois = {
 23      0x1bae,
 24  }
 25  
 26  mcu = Microcontroller()
 27  def run(mcu, end, trace):
 28      isns = 0
 29      while mcu.pc not in end:
 30          isns+=1
 31          op = Operation(mcu.rom[int(mcu.pc)])
 32          op.args = mcu.rom[int(mcu.pc + 1):int(mcu.pc + len(op))]
 33  
 34          if int(mcu.pc) in pois:
 35              print(f"{mcu.pc:04x} "
 36                    f"{int(mcu.mem.tl0):02x} "
 37                    , end='')
 38              #for i in range(3):
 39              #    if i>0 and i % 4==0: print(" ", end='')
 40              #    print(f"{mcu.mem._data[0x4a+i]:02x}", end='')
 41              print()
 42          if trace:
 43              flush_display(trace)
 44              print(f"{isns:5} {int(mcu.pc):04x}   {str(op):<30} | "
 45                    f"{int(mcu.mem.a):02x} "
 46                    f"{int(mcu.mem.r0):02x} "
 47                    f"{int(mcu.mem.r2):02x} "
 48                    f"{int(mcu.mem.r3):02x} "
 49                    f"{int(mcu.mem.r6):02x} "
 50                    f"{int(mcu.mem.dptr):04x} "
 51                    f"{int(mcu.mem[0xd0]) & 0xfe:02x} "
 52                    f"{int(mcu.mem[0xd1]):02x} ", end='')
 53              for i in range(3):
 54                  if i>0 and i % 4==0: print(" ", end='')
 55                  print(f"{mcu.mem._data[0x4a+i]:02x}", end='')
 56              print()
 57  
 58          if op.opcode == 0x12: # lcall
 59              if op.args == [0x03,0x7a]: # putc
 60                  if trace:
 61                      putc(mcu.mem.a)
 62                  mcu.pc += len(op)
 63                  #print(f"{chr(int(mcu.mem.a))}", end='')
 64                  display.append(chr(int(mcu.mem.a)))
 65                  continue
 66              elif op.args == [0x05,0x65]: # getc
 67                  if trace:
 68                      flush_display(trace)
 69                      print("getc()")
 70                  mcu.pc += len(op)
 71                  #mcu.mem.a = ord(input('')[0])
 72                  mcu.mem.a = getc.pop()
 73                  continue
 74              elif op.args == [0x1c,0xf5]: # call crypt_byte
 75                  if trace:
 76                      print(f"crypt_byte({int(mcu.mem.a):02x})")
 77                  print(f"crypt_byte({int(mcu.mem.a):02x})")
 78                  mcu.pc += len(op)
 79                  continue
 80              elif op.args == [0x1c,0x4f]: # call putc_maybe_print
 81                  # just skip it.
 82                  mcu.pc += len(op)
 83                  continue
 84          if op.opcode == 0x2: # jmp
 85              if op.args == [0x03,0x7a]: # putc
 86                  if trace:
 87                      putc(mcu.mem.a)
 88                  #print(f"{chr(int(mcu.mem.a))}", end='')
 89                  display.append(chr(int(mcu.mem.a)))
 90                  mcu._exec_34() # ret
 91                  continue
 92              elif op.args == [0x05,0x65]: # getc
 93                  if trace:
 94                      flush_display(trace)
 95                      print("getc()")
 96                  #mcu.mem.a = ord(input('')[0])
 97                  mcu.mem.a = getc.pop()
 98                  mcu._exec_34() # ret
 99                  continue
100  
101          # catch putc if not jmp/call
102          if int(mcu.pc)==0x37a:
103              if trace:
104                  putc(mcu.mem.a)
105              mcu._exec_34() # ret
106              continue
107  
108          mcu.next_cycle()
109      if trace:
110          flush_display(trace)
111          print("end, total insn", isns)
112      return isns
113  
114  # reset
115  mcu.reset_ram()
116  
117  # load rom image
118  with open('SBT.rom','rb') as fd:
119      code = fd.read()
120  for i, b in enumerate(code):
121     mcu.rom[i] = b
122  
123  # two timer config
124  # tmod th0  tl0 th1 th0 tcon
125  # 0x12 0x52             0x15
126  # 0x22 1    0   1   0   0x50
127  # tmod two nibbles, for t0 and t1
128  # lower two bits are mode
129  # mode 1: 16 bit timer
130  # mode 2: 8bit autoreload timer
131  
132  mcu.mem.tmod = 0x12
133  mcu.mem.th0 = 0x52
134  mcu.mem.tcon = 0x15
135  
136  mcu.pc = 0x1ba8 # we skip the query to print the output at 1aed
137  for i,c in enumerate("ABCDE"):
138     mcu.xmem[0x72d2+i]=ord(c)
139  
140  steps = run(mcu, [0x1bba], False)