experimenting with CR/LR/XER etc in qemu
[soc.git] / src / soc / simulator / qemu.py
1 from pygdbmi.gdbcontroller import GdbController
2 import subprocess
3
4 launch_args = ['qemu-system-ppc64',
5 '-machine', 'powernv9',
6 '-nographic',
7 '-s', '-S']
8
9
10 class QemuController:
11 def __init__(self, kernel):
12 args = launch_args + ['-kernel', kernel]
13 self.qemu_popen = subprocess.Popen(args,
14 stdout=subprocess.PIPE,
15 stdin=subprocess.PIPE)
16 self.gdb = GdbController(gdb_path='powerpc64-linux-gnu-gdb')
17
18 def __enter__(self):
19 return self
20
21 def __exit__(self, type, value, traceback):
22 self.exit()
23
24 def connect(self):
25 return self.gdb.write('-target-select remote localhost:1234')
26
27 def break_address(self, addr):
28 cmd = '-break-insert *0x{:x}'.format(addr)
29 return self.gdb.write(cmd)
30
31 def get_registers(self):
32 return self.gdb.write('-data-list-register-values x')
33
34 def _get_register(self, fmt):
35 res = self.gdb.write('-data-list-register-values '+fmt,
36 timeout_sec=1.0) # increase this timeout if needed
37 for x in res:
38 if(x["type"]=="result"):
39 assert 'register-values' in x['payload']
40 return int(x['payload']['register-values'][0]['value'], 0)
41 return None
42
43 # TODO: use -data-list-register-names instead of hardcoding the values
44 def get_pc(self): return self._get_register('x 64')
45 def get_msr(self): return self._get_register('x 65')
46 def get_cr(self): return self._get_register('x 66')
47 def get_lr(self): return self._get_register('x 67')
48 def get_ctr(self): return self._get_register('x 68') # probably
49 def get_xer(self): return self._get_register('x 69')
50 def get_fpscr(self): return self._get_register('x 70')
51 def get_mq(self): return self._get_register('x 71')
52
53 def get_register(self, num):
54 return self._get_register('x {}'.format(num))
55
56 def step(self):
57 return self.gdb.write('-exec-next-instruction')
58
59 def gdb_continue(self):
60 return self.gdb.write('-exec-continue')
61
62 def exit(self):
63 self.gdb.exit()
64 self.qemu_popen.kill()
65 outs, errs = self.qemu_popen.communicate()
66 self.qemu_popen.stdout.close()
67 self.qemu_popen.stdin.close()
68
69
70 def run_program(program):
71 q = QemuController(program.binfile.name)
72 q.connect()
73 q.break_address(0x20000000 + program.size())
74 q.gdb_continue()
75 return q
76
77
78 if __name__ == '__main__':
79 q = QemuController("qemu_test/kernel.bin")
80 q.connect()
81 q.break_address(0x20000000)
82 q.gdb_continue()
83 print(q.get_register(1))
84 print(q.step())
85 print(q.get_register(1))
86 q.exit()