jb302@29
|
1 #!/usr/bin/env python
|
jb302@29
|
2 # cli.py - a command line to control the emulator using
|
jb302@29
|
3 # the debug control class
|
jb302@29
|
4
|
jb302@29
|
5 import struct
|
jb302@40
|
6 import sys
|
jb302@29
|
7 from StringIO import StringIO
|
jb302@29
|
8 from io import BytesIO
|
jb302@29
|
9 from subprocess import Popen, PIPE, STDOUT
|
jb302@29
|
10
|
jb302@29
|
11 from asm import asm
|
jb302@29
|
12 from dbg import dbg
|
jb302@29
|
13
|
jb302@34
|
14 # start emu instance
|
jb302@34
|
15 emu = dbg.controller()
|
jb302@34
|
16 emu.Emu = Popen(['bin/emu'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
|
jb302@34
|
17
|
jb302@34
|
18 # symbol encodings
|
jb302@29
|
19 syms = {
|
jb302@29
|
20 'R0_0':0,
|
jb302@29
|
21 'R1_0':1,
|
jb302@29
|
22 'R2_0':2,
|
jb302@29
|
23 'R3_0':3,
|
jb302@29
|
24 'DPH':4,
|
jb302@29
|
25 'SPH':5,
|
jb302@29
|
26 'PCH':6,
|
jb302@29
|
27 'TMPH':7,
|
jb302@30
|
28 'R0_1':8,
|
jb302@29
|
29 'R1_1':9,
|
jb302@29
|
30 'R2_1':10,
|
jb302@29
|
31 'R3_1':11,
|
jb302@29
|
32 'DPL':12,
|
jb302@29
|
33 'SPL':13,
|
jb302@29
|
34 'PCL':14,
|
jb302@29
|
35 'TMPL':15,
|
jb302@29
|
36 'BS':0,
|
jb302@29
|
37 'IE':1,
|
jb302@29
|
38 'OV':2,
|
jb302@29
|
39 'S':3,
|
jb302@29
|
40 'P':4,
|
jb302@29
|
41 'AC':5,
|
jb302@29
|
42 'Z':6,
|
jb302@29
|
43 'C':7
|
jb302@29
|
44 }
|
jb302@29
|
45
|
jb302@34
|
46 # command line command strings
|
jb302@34
|
47 cmds = {
|
jb302@34
|
48 'step':emu.step,
|
jb302@40
|
49 'frun':emu.free_run,
|
jb302@34
|
50 'run':emu.run,
|
jb302@34
|
51 'runl':emu.run_len,
|
jb302@34
|
52 'gr':emu.get_reg,
|
jb302@34
|
53 'sr':emu.set_reg,
|
jb302@34
|
54 'gf':emu.get_flag,
|
jb302@34
|
55 'sf':emu.set_flag,
|
jb302@34
|
56 'gb':emu.get_block,
|
jb302@34
|
57 'sb':emu.set_block,
|
jb302@34
|
58 'ga':emu.get_a,
|
jb302@34
|
59 'gfs':emu.get_flags,
|
jb302@34
|
60 'gi':emu.get_ir,
|
jb302@34
|
61 'sbp':emu.set_bp
|
jb302@34
|
62 }
|
jb302@29
|
63
|
jb302@29
|
64 # assemble and execute inline asm.
|
jb302@29
|
65 # bytecode is copied to where ever the PC is and then executed
|
jb302@29
|
66 def exc():
|
jb302@29
|
67
|
jb302@29
|
68 while True:
|
jb302@29
|
69 # file like objects for source and byte code
|
jb302@29
|
70 code = StringIO()
|
jb302@29
|
71 bytecode = BytesIO()
|
jb302@29
|
72
|
jb302@29
|
73 # get the PC
|
jb302@29
|
74 pch = struct.unpack('>B', emu.get_reg(syms['PCH']))[0]
|
jb302@29
|
75 pcl = struct.unpack('>B', emu.get_reg(syms['PCL']))[0]
|
jb302@29
|
76
|
jb302@29
|
77 # get user input
|
jb302@34
|
78 c = raw_input('>> ')
|
jb302@34
|
79 if c == 'end':
|
jb302@29
|
80 break
|
jb302@29
|
81 code.write(c)
|
jb302@29
|
82
|
jb302@29
|
83 try:
|
jb302@29
|
84 # assemble and determine length bytes
|
jb302@29
|
85 a, l = asm.first_pass(code)
|
jb302@29
|
86 if l.keys() != []:
|
jb302@29
|
87 print 'labels not yet supported in interpreter mode'
|
jb302@29
|
88 continue
|
jb302@34
|
89 bytecode, d = asm.second_pass(bytecode, a, l)
|
jb302@29
|
90 bytecode.seek(0)
|
jb302@29
|
91 byte_array = bytearray(bytecode.read())
|
jb302@29
|
92 except:
|
jb302@29
|
93 print 'invalid instruction'
|
jb302@29
|
94 continue
|
jb302@29
|
95
|
jb302@34
|
96 print 'PC:', hex(pcl | (pch << 8)),'BC:', [hex(b) for b in byte_array]
|
jb302@29
|
97 # write to emu memory and execute
|
jb302@29
|
98 emu.set_block(pch, pcl, byte_array)
|
jb302@29
|
99 emu.step()
|
jb302@29
|
100
|
jb302@34
|
101
|
jb302@34
|
102 # request input and run command
|
jb302@34
|
103 def req_run():
|
jb302@34
|
104 inp = raw_input('> ').split()
|
jb302@34
|
105 if inp == []:
|
jb302@34
|
106 return
|
jb302@34
|
107 cmd = inp[0]
|
jb302@34
|
108 args = []
|
jb302@34
|
109
|
jb302@34
|
110 try:
|
jb302@34
|
111 if cmd == 'exit':
|
jb302@34
|
112 emu.Emu.kill()
|
jb302@34
|
113 exit()
|
jb302@34
|
114 # deal with inline execution independently
|
jb302@34
|
115 if cmd == 'exc':
|
jb302@34
|
116 exc()
|
jb302@34
|
117 return
|
jb302@34
|
118
|
jb302@34
|
119 # set block has unique argument syntax
|
jb302@34
|
120 if cmd == 'sb':
|
jb302@34
|
121 args.append(int(inp[1], 0))
|
jb302@34
|
122 args.append(int(inp[2], 0))
|
jb302@34
|
123 args.append([int(x, 0) for x in inp[3:]])
|
jb302@34
|
124 cmds[cmd](*args)
|
jb302@34
|
125 return
|
jb302@34
|
126
|
jb302@34
|
127 # decode args
|
jb302@34
|
128 i = 0
|
jb302@34
|
129 for word in inp[1:]:
|
jb302@34
|
130 if word in syms.keys():
|
jb302@34
|
131 args.append(syms[word])
|
jb302@34
|
132 # only arguments after 3 will be data for set block
|
jb302@34
|
133 # this needs to be in a list
|
jb302@34
|
134 else:
|
jb302@34
|
135 args.append(int(word, 0))
|
jb302@34
|
136 i = i + 1
|
jb302@34
|
137
|
jb302@34
|
138 resp = cmds[cmd](*args)
|
jb302@34
|
139 if resp == None:
|
jb302@34
|
140 return
|
jb302@34
|
141 else:
|
jb302@34
|
142 print [hex(struct.unpack('>B', x)[0]) for x in resp]
|
jb302@34
|
143
|
jb302@34
|
144 except Exception, e:
|
jb302@34
|
145 print e
|
jb302@34
|
146 print 'invalid command or argument syntax'
|
jb302@34
|
147 return
|
jb302@34
|
148
|
jb302@29
|
149
|
jb302@29
|
150 if __name__ == '__main__':
|
jb302@40
|
151 try:
|
jb302@40
|
152 with open(sys.argv[1], 'rb') as f:
|
jb302@40
|
153 prog = bytearray(f.read())
|
jb302@40
|
154 emu.set_block(0, 0, prog)
|
jb302@40
|
155 except IndexError:
|
jb302@40
|
156 pass
|
jb302@40
|
157
|
jb302@29
|
158 while True:
|
jb302@34
|
159 req_run()
|
jb302@29
|
160
|