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)