Set FS before reading F registers
[riscv-tests.git] / debug / gdbserver.py
1 #!/usr/bin/env python
2
3 import argparse
4 import binascii
5 import random
6 import sys
7 import tempfile
8 import time
9 import os
10
11 import targets
12 import testlib
13 from testlib import assertEqual, assertNotEqual, assertIn
14 from testlib import assertGreater, assertTrue, assertRegexpMatches, assertLess
15 from testlib import GdbTest
16
17 MSTATUS_UIE = 0x00000001
18 MSTATUS_SIE = 0x00000002
19 MSTATUS_HIE = 0x00000004
20 MSTATUS_MIE = 0x00000008
21 MSTATUS_UPIE = 0x00000010
22 MSTATUS_SPIE = 0x00000020
23 MSTATUS_HPIE = 0x00000040
24 MSTATUS_MPIE = 0x00000080
25 MSTATUS_SPP = 0x00000100
26 MSTATUS_HPP = 0x00000600
27 MSTATUS_MPP = 0x00001800
28 MSTATUS_FS = 0x00006000
29 MSTATUS_XS = 0x00018000
30 MSTATUS_MPRV = 0x00020000
31 MSTATUS_PUM = 0x00040000
32 MSTATUS_MXR = 0x00080000
33 MSTATUS_VM = 0x1F000000
34 MSTATUS32_SD = 0x80000000
35 MSTATUS64_SD = 0x8000000000000000
36
37 # pylint: disable=abstract-method
38
39 def ihex_line(address, record_type, data):
40 assert len(data) < 128
41 line = ":%02X%04X%02X" % (len(data), address, record_type)
42 check = len(data)
43 check += address % 256
44 check += address >> 8
45 check += record_type
46 for char in data:
47 value = ord(char)
48 check += value
49 line += "%02X" % value
50 line += "%02X\n" % ((256-check)%256)
51 return line
52
53 def ihex_parse(line):
54 assert line.startswith(":")
55 line = line[1:]
56 data_len = int(line[:2], 16)
57 address = int(line[2:6], 16)
58 record_type = int(line[6:8], 16)
59 data = ""
60 for i in range(data_len):
61 data += "%c" % int(line[8+2*i:10+2*i], 16)
62 return record_type, address, data
63
64 def readable_binary_string(s):
65 return "".join("%02x" % ord(c) for c in s)
66
67 class SimpleRegisterTest(GdbTest):
68 def check_reg(self, name):
69 a = random.randrange(1<<self.target.xlen)
70 b = random.randrange(1<<self.target.xlen)
71 self.gdb.p("$%s=0x%x" % (name, a))
72 self.gdb.stepi()
73 assertEqual(self.gdb.p("$%s" % name), a)
74 self.gdb.p("$%s=0x%x" % (name, b))
75 self.gdb.stepi()
76 assertEqual(self.gdb.p("$%s" % name), b)
77
78 def setup(self):
79 # 0x13 is nop
80 self.gdb.command("p *((int*) 0x%x)=0x13" % self.target.ram)
81 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 4))
82 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 8))
83 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 12))
84 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 16))
85 self.gdb.p("$pc=0x%x" % self.target.ram)
86
87 class SimpleS0Test(SimpleRegisterTest):
88 def test(self):
89 self.check_reg("s0")
90
91 class SimpleS1Test(SimpleRegisterTest):
92 def test(self):
93 self.check_reg("s1")
94
95 class SimpleT0Test(SimpleRegisterTest):
96 def test(self):
97 self.check_reg("t0")
98
99 class SimpleT1Test(SimpleRegisterTest):
100 def test(self):
101 self.check_reg("t1")
102
103 class SimpleF18Test(SimpleRegisterTest):
104 def check_reg(self, name):
105 self.gdb.p_raw("$mstatus=$mstatus | 0x00006000")
106 self.gdb.stepi()
107 a = random.random()
108 b = random.random()
109 self.gdb.p_raw("$%s=%f" % (name, a))
110 self.gdb.stepi()
111 assertLess(abs(float(self.gdb.p_raw("$%s" % name)) - a), .001)
112 self.gdb.p_raw("$%s=%f" % (name, b))
113 self.gdb.stepi()
114 assertLess(abs(float(self.gdb.p_raw("$%s" % name)) - b), .001)
115
116 def early_applicable(self):
117 return self.target.extensionSupported('F')
118
119 def test(self):
120 self.check_reg("f18")
121
122 class SimpleMemoryTest(GdbTest):
123 def access_test(self, size, data_type):
124 assertEqual(self.gdb.p("sizeof(%s)" % data_type), size)
125 a = 0x86753095555aaaa & ((1<<(size*8))-1)
126 b = 0xdeadbeef12345678 & ((1<<(size*8))-1)
127 self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, self.target.ram, a))
128 self.gdb.p("*((%s*)0x%x) = 0x%x" % (data_type, self.target.ram + size,
129 b))
130 assertEqual(self.gdb.p("*((%s*)0x%x)" % (data_type, self.target.ram)),
131 a)
132 assertEqual(self.gdb.p("*((%s*)0x%x)" % (
133 data_type, self.target.ram + size)), b)
134
135 class MemTest8(SimpleMemoryTest):
136 def test(self):
137 self.access_test(1, 'char')
138
139 class MemTest16(SimpleMemoryTest):
140 def test(self):
141 self.access_test(2, 'short')
142
143 class MemTest32(SimpleMemoryTest):
144 def test(self):
145 self.access_test(4, 'int')
146
147 class MemTest64(SimpleMemoryTest):
148 def test(self):
149 self.access_test(8, 'long long')
150
151 class MemTestReadInvalid(SimpleMemoryTest):
152 def test(self):
153 # This test relies on 'gdb_report_data_abort enable' being executed in
154 # the openocd.cfg file.
155 try:
156 self.gdb.p("*((int*)0xdeadbeef)")
157 assert False, "Read should have failed."
158 except testlib.CannotAccess as e:
159 assertEqual(e.address, 0xdeadbeef)
160 self.gdb.p("*((int*)0x%x)" % self.target.ram)
161
162 class MemTestWriteInvalid(SimpleMemoryTest):
163 def test(self):
164 # This test relies on 'gdb_report_data_abort enable' being executed in
165 # the openocd.cfg file.
166 try:
167 self.gdb.p("*((int*)0xdeadbeef)=8675309")
168 assert False, "Write should have failed."
169 except testlib.CannotAccess as e:
170 assertEqual(e.address, 0xdeadbeef)
171 self.gdb.p("*((int*)0x%x)=6874742" % self.target.ram)
172
173 class MemTestBlock(GdbTest):
174 def test(self):
175 length = 1024
176 line_length = 16
177 a = tempfile.NamedTemporaryFile(suffix=".ihex")
178 data = ""
179 for i in range(length / line_length):
180 line_data = "".join(["%c" % random.randrange(256)
181 for _ in range(line_length)])
182 data += line_data
183 a.write(ihex_line(i * line_length, 0, line_data))
184 a.flush()
185
186 self.gdb.command("restore %s 0x%x" % (a.name, self.target.ram))
187 for offset in range(0, length, 19*4) + [length-4]:
188 value = self.gdb.p("*((int*)0x%x)" % (self.target.ram + offset))
189 written = ord(data[offset]) | \
190 (ord(data[offset+1]) << 8) | \
191 (ord(data[offset+2]) << 16) | \
192 (ord(data[offset+3]) << 24)
193 assertEqual(value, written)
194
195 b = tempfile.NamedTemporaryFile(suffix=".ihex")
196 self.gdb.command("dump ihex memory %s 0x%x 0x%x" % (b.name,
197 self.target.ram, self.target.ram + length))
198 for line in b:
199 record_type, address, line_data = ihex_parse(line)
200 if record_type == 0:
201 assertEqual(readable_binary_string(line_data),
202 readable_binary_string(
203 data[address:address+len(line_data)]))
204
205 class InstantHaltTest(GdbTest):
206 def test(self):
207 assertEqual(self.target.reset_vector, self.gdb.p("$pc"))
208 # mcycle and minstret have no defined reset value.
209 mstatus = self.gdb.p("$mstatus")
210 assertEqual(mstatus & (MSTATUS_MIE | MSTATUS_MPRV |
211 MSTATUS_VM), 0)
212
213 class InstantChangePc(GdbTest):
214 def test(self):
215 """Change the PC right as we come out of reset."""
216 # 0x13 is nop
217 self.gdb.command("p *((int*) 0x%x)=0x13" % self.target.ram)
218 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 4))
219 self.gdb.command("p *((int*) 0x%x)=0x13" % (self.target.ram + 8))
220 self.gdb.p("$pc=0x%x" % self.target.ram)
221 self.gdb.stepi()
222 assertEqual((self.target.ram + 4), self.gdb.p("$pc"))
223 self.gdb.stepi()
224 assertEqual((self.target.ram + 8), self.gdb.p("$pc"))
225
226 class DebugTest(GdbTest):
227 # Include malloc so that gdb can make function calls. I suspect this malloc
228 # will silently blow through the memory set aside for it, so be careful.
229 compile_args = ("programs/debug.c", "programs/checksum.c",
230 "programs/tiny-malloc.c", "-DDEFINE_MALLOC", "-DDEFINE_FREE")
231
232 def setup(self):
233 self.gdb.load()
234 self.gdb.b("_exit")
235
236 def exit(self, expected_result=0xc86455d4):
237 output = self.gdb.c()
238 assertIn("Breakpoint", output)
239 assertIn("_exit", output)
240 assertEqual(self.gdb.p("status"), expected_result)
241
242 class DebugCompareSections(DebugTest):
243 def test(self):
244 output = self.gdb.command("compare-sections")
245 matched = 0
246 for line in output.splitlines():
247 if line.startswith("Section"):
248 assert line.endswith("matched.")
249 matched += 1
250 assertGreater(matched, 1)
251
252 class DebugFunctionCall(DebugTest):
253 def test(self):
254 self.gdb.b("main:start")
255 self.gdb.c()
256 assertEqual(self.gdb.p('fib(6)'), 8)
257 assertEqual(self.gdb.p('fib(7)'), 13)
258 self.exit()
259
260 class DebugChangeString(DebugTest):
261 def test(self):
262 text = "This little piggy went to the market."
263 self.gdb.b("main:start")
264 self.gdb.c()
265 self.gdb.p('fox = "%s"' % text)
266 self.exit(0x43b497b8)
267
268 class DebugTurbostep(DebugTest):
269 def test(self):
270 """Single step a bunch of times."""
271 self.gdb.b("main:start")
272 self.gdb.c()
273 self.gdb.command("p i=0")
274 last_pc = None
275 advances = 0
276 jumps = 0
277 for _ in range(100):
278 self.gdb.stepi()
279 pc = self.gdb.p("$pc")
280 assertNotEqual(last_pc, pc)
281 if last_pc and pc > last_pc and pc - last_pc <= 4:
282 advances += 1
283 else:
284 jumps += 1
285 last_pc = pc
286 # Some basic sanity that we're not running between breakpoints or
287 # something.
288 assertGreater(jumps, 10)
289 assertGreater(advances, 50)
290
291 class DebugExit(DebugTest):
292 def test(self):
293 self.exit()
294
295 class DebugSymbols(DebugTest):
296 def test(self):
297 self.gdb.b("main")
298 self.gdb.b("rot13")
299 output = self.gdb.c()
300 assertIn(", main ", output)
301 output = self.gdb.c()
302 assertIn(", rot13 ", output)
303
304 class DebugBreakpoint(DebugTest):
305 def test(self):
306 self.gdb.b("rot13")
307 # The breakpoint should be hit exactly 2 times.
308 for _ in range(2):
309 output = self.gdb.c()
310 self.gdb.p("$pc")
311 assertIn("Breakpoint ", output)
312 assertIn("rot13 ", output)
313 self.exit()
314
315 class Hwbp1(DebugTest):
316 def test(self):
317 if self.target.instruction_hardware_breakpoint_count < 1:
318 return 'not_applicable'
319
320 self.gdb.hbreak("rot13")
321 # The breakpoint should be hit exactly 2 times.
322 for _ in range(2):
323 output = self.gdb.c()
324 self.gdb.p("$pc")
325 assertRegexpMatches(output, r"[bB]reakpoint")
326 assertIn("rot13 ", output)
327 self.exit()
328
329 class Hwbp2(DebugTest):
330 def test(self):
331 if self.target.instruction_hardware_breakpoint_count < 2:
332 return 'not_applicable'
333
334 self.gdb.hbreak("main")
335 self.gdb.hbreak("rot13")
336 # We should hit 3 breakpoints.
337 for expected in ("main", "rot13", "rot13"):
338 output = self.gdb.c()
339 self.gdb.p("$pc")
340 assertRegexpMatches(output, r"[bB]reakpoint")
341 assertIn("%s " % expected, output)
342 self.exit()
343
344 class TooManyHwbp(DebugTest):
345 def run(self):
346 for i in range(30):
347 self.gdb.hbreak("*rot13 + %d" % (i * 4))
348
349 output = self.gdb.c()
350 assertIn("Cannot insert hardware breakpoint", output)
351 # Clean up, otherwise the hardware breakpoints stay set and future
352 # tests may fail.
353 self.gdb.command("D")
354
355 class Registers(DebugTest):
356 def test(self):
357 # Get to a point in the code where some registers have actually been
358 # used.
359 self.gdb.b("rot13")
360 self.gdb.c()
361 self.gdb.c()
362 # Try both forms to test gdb.
363 for cmd in ("info all-registers", "info registers all"):
364 output = self.gdb.command(cmd)
365 for reg in ('zero', 'ra', 'sp', 'gp', 'tp'):
366 assertIn(reg, output)
367
368 #TODO
369 # mcpuid is one of the few registers that should have the high bit set
370 # (for rv64).
371 # Leave this commented out until gdb and spike agree on the encoding of
372 # mcpuid (which is going to be renamed to misa in any case).
373 #assertRegexpMatches(output, ".*mcpuid *0x80")
374
375 #TODO:
376 # The instret register should always be changing.
377 #last_instret = None
378 #for _ in range(5):
379 # instret = self.gdb.p("$instret")
380 # assertNotEqual(instret, last_instret)
381 # last_instret = instret
382 # self.gdb.stepi()
383
384 self.exit()
385
386 class UserInterrupt(DebugTest):
387 def test(self):
388 """Sending gdb ^C while the program is running should cause it to
389 halt."""
390 self.gdb.b("main:start")
391 self.gdb.c()
392 self.gdb.p("i=123")
393 self.gdb.c(wait=False)
394 time.sleep(0.5)
395 output = self.gdb.interrupt()
396 assert "main" in output
397 assertGreater(self.gdb.p("j"), 10)
398 self.gdb.p("i=0")
399 self.exit()
400
401 class StepTest(GdbTest):
402 compile_args = ("programs/step.S", )
403
404 def setup(self):
405 self.gdb.load()
406 self.gdb.b("main")
407 self.gdb.c()
408
409 def test(self):
410 main_address = self.gdb.p("$pc")
411 if self.target.extensionSupported("c"):
412 sequence = (4, 8, 0xc, 0xe, 0x14, 0x18, 0x22, 0x1c, 0x24, 0x24)
413 else:
414 sequence = (4, 8, 0xc, 0x10, 0x18, 0x1c, 0x28, 0x20, 0x2c, 0x2c)
415 for expected in sequence:
416 self.gdb.stepi()
417 pc = self.gdb.p("$pc")
418 assertEqual("%x" % (pc - main_address), "%x" % expected)
419
420 class TriggerTest(GdbTest):
421 compile_args = ("programs/trigger.S", )
422 def setup(self):
423 self.gdb.load()
424 self.gdb.b("_exit")
425 self.gdb.b("main")
426 self.gdb.c()
427
428 def exit(self):
429 output = self.gdb.c()
430 assertIn("Breakpoint", output)
431 assertIn("_exit", output)
432
433 class TriggerExecuteInstant(TriggerTest):
434 """Test an execute breakpoint on the first instruction executed out of
435 debug mode."""
436 def test(self):
437 main_address = self.gdb.p("$pc")
438 self.gdb.command("hbreak *0x%x" % (main_address + 4))
439 self.gdb.c()
440 assertEqual(self.gdb.p("$pc"), main_address+4)
441
442 class TriggerLoadAddress(TriggerTest):
443 def test(self):
444 self.gdb.command("rwatch *((&data)+1)")
445 output = self.gdb.c()
446 assertIn("read_loop", output)
447 assertEqual(self.gdb.p("$a0"),
448 self.gdb.p("(&data)+1"))
449 self.exit()
450
451 class TriggerLoadAddressInstant(TriggerTest):
452 """Test a load address breakpoint on the first instruction executed out of
453 debug mode."""
454 def test(self):
455 self.gdb.command("b just_before_read_loop")
456 self.gdb.c()
457 read_loop = self.gdb.p("&read_loop")
458 self.gdb.command("rwatch data")
459 self.gdb.c()
460 # Accept hitting the breakpoint before or after the load instruction.
461 assertIn(self.gdb.p("$pc"), [read_loop, read_loop + 4])
462 assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
463
464 class TriggerStoreAddress(TriggerTest):
465 def test(self):
466 self.gdb.command("watch *((&data)+3)")
467 output = self.gdb.c()
468 assertIn("write_loop", output)
469 assertEqual(self.gdb.p("$a0"),
470 self.gdb.p("(&data)+3"))
471 self.exit()
472
473 class TriggerStoreAddressInstant(TriggerTest):
474 def test(self):
475 """Test a store address breakpoint on the first instruction executed out
476 of debug mode."""
477 self.gdb.command("b just_before_write_loop")
478 self.gdb.c()
479 write_loop = self.gdb.p("&write_loop")
480 self.gdb.command("watch data")
481 self.gdb.c()
482 # Accept hitting the breakpoint before or after the store instruction.
483 assertIn(self.gdb.p("$pc"), [write_loop, write_loop + 4])
484 assertEqual(self.gdb.p("$a0"), self.gdb.p("&data"))
485
486 class TriggerDmode(TriggerTest):
487 def check_triggers(self, tdata1_lsbs, tdata2):
488 dmode = 1 << (self.target.xlen-5)
489
490 triggers = []
491
492 if self.target.xlen == 32:
493 xlen_type = 'int'
494 elif self.target.xlen == 64:
495 xlen_type = 'long long'
496 else:
497 raise NotImplementedError
498
499 dmode_count = 0
500 i = 0
501 for i in range(16):
502 tdata1 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i))
503 if tdata1 == 0:
504 break
505 tdata2 = self.gdb.p("((%s *)&data)[%d]" % (xlen_type, 2*i+1))
506
507 if tdata1 & dmode:
508 dmode_count += 1
509 else:
510 assertEqual(tdata1 & 0xffff, tdata1_lsbs)
511 assertEqual(tdata2, tdata2)
512
513 assertGreater(i, 1)
514 assertEqual(dmode_count, 1)
515
516 return triggers
517
518 def test(self):
519 self.gdb.command("hbreak write_load_trigger")
520 self.gdb.b("clear_triggers")
521 self.gdb.p("$pc=write_store_trigger")
522 output = self.gdb.c()
523 assertIn("write_load_trigger", output)
524 self.check_triggers((1<<6) | (1<<1), 0xdeadbee0)
525 output = self.gdb.c()
526 assertIn("clear_triggers", output)
527 self.check_triggers((1<<6) | (1<<0), 0xfeedac00)
528
529 class RegsTest(GdbTest):
530 compile_args = ("programs/regs.S", )
531 def setup(self):
532 self.gdb.load()
533 self.gdb.b("main")
534 self.gdb.b("handle_trap")
535 self.gdb.c()
536
537 class WriteGprs(RegsTest):
538 def test(self):
539 regs = [("x%d" % n) for n in range(2, 32)]
540
541 self.gdb.p("$pc=write_regs")
542 for i, r in enumerate(regs):
543 self.gdb.p("$%s=%d" % (r, (0xdeadbeef<<i)+17))
544 self.gdb.p("$x1=data")
545 self.gdb.command("b all_done")
546 output = self.gdb.c()
547 assertIn("Breakpoint ", output)
548
549 # Just to get this data in the log.
550 self.gdb.command("x/30gx data")
551 self.gdb.command("info registers")
552 for n in range(len(regs)):
553 assertEqual(self.gdb.x("data+%d" % (8*n), 'g'),
554 ((0xdeadbeef<<n)+17) & ((1<<self.target.xlen)-1))
555
556 class WriteCsrs(RegsTest):
557 def test(self):
558 # As much a test of gdb as of the simulator.
559 self.gdb.p("$mscratch=0")
560 self.gdb.stepi()
561 assertEqual(self.gdb.p("$mscratch"), 0)
562 self.gdb.p("$mscratch=123")
563 self.gdb.stepi()
564 assertEqual(self.gdb.p("$mscratch"), 123)
565
566 self.gdb.p("$pc=write_regs")
567 self.gdb.p("$x1=data")
568 self.gdb.command("b all_done")
569 self.gdb.command("c")
570
571 assertEqual(123, self.gdb.p("$mscratch"))
572 assertEqual(123, self.gdb.p("$x1"))
573 assertEqual(123, self.gdb.p("$csr832"))
574
575 class DownloadTest(GdbTest):
576 def setup(self):
577 # pylint: disable=attribute-defined-outside-init
578 length = min(2**20, self.target.ram_size - 2048)
579 self.download_c = tempfile.NamedTemporaryFile(prefix="download_",
580 suffix=".c", delete=False)
581 self.download_c.write("#include <stdint.h>\n")
582 self.download_c.write(
583 "unsigned int crc32a(uint8_t *message, unsigned int size);\n")
584 self.download_c.write("uint32_t length = %d;\n" % length)
585 self.download_c.write("uint8_t d[%d] = {\n" % length)
586 self.crc = 0
587 assert length % 16 == 0
588 for i in range(length / 16):
589 self.download_c.write(" /* 0x%04x */ " % (i * 16))
590 for _ in range(16):
591 value = random.randrange(1<<8)
592 self.download_c.write("0x%02x, " % value)
593 self.crc = binascii.crc32("%c" % value, self.crc)
594 self.download_c.write("\n")
595 self.download_c.write("};\n")
596 self.download_c.write("uint8_t *data = &d[0];\n")
597 self.download_c.write(
598 "uint32_t main() { return crc32a(data, length); }\n")
599 self.download_c.flush()
600
601 if self.crc < 0:
602 self.crc += 2**32
603
604 self.binary = self.target.compile(self.download_c.name,
605 "programs/checksum.c")
606 self.gdb.command("file %s" % self.binary)
607
608 def test(self):
609 self.gdb.load()
610 self.gdb.command("b _exit")
611 self.gdb.c(timeout=60)
612 assertEqual(self.gdb.p("status"), self.crc)
613 os.unlink(self.download_c.name)
614
615 class MprvTest(GdbTest):
616 compile_args = ("programs/mprv.S", )
617 def setup(self):
618 self.gdb.load()
619
620 def test(self):
621 """Test that the debugger can access memory when MPRV is set."""
622 self.gdb.c(wait=False)
623 time.sleep(0.5)
624 self.gdb.interrupt()
625 output = self.gdb.command("p/x *(int*)(((char*)&data)-0x80000000)")
626 assertIn("0xbead", output)
627
628 class PrivTest(GdbTest):
629 compile_args = ("programs/priv.S", )
630 def setup(self):
631 # pylint: disable=attribute-defined-outside-init
632 self.gdb.load()
633
634 misa = self.target.misa
635 self.supported = set()
636 if misa & (1<<20):
637 self.supported.add(0)
638 if misa & (1<<18):
639 self.supported.add(1)
640 if misa & (1<<7):
641 self.supported.add(2)
642 self.supported.add(3)
643
644 class PrivRw(PrivTest):
645 def test(self):
646 """Test reading/writing priv."""
647 for privilege in range(4):
648 self.gdb.p("$priv=%d" % privilege)
649 self.gdb.stepi()
650 actual = self.gdb.p("$priv")
651 assertIn(actual, self.supported)
652 if privilege in self.supported:
653 assertEqual(actual, privilege)
654
655 class PrivChange(PrivTest):
656 def test(self):
657 """Test that the core's privilege level actually changes."""
658
659 if 0 not in self.supported:
660 return 'not_applicable'
661
662 self.gdb.b("main")
663 self.gdb.c()
664
665 # Machine mode
666 self.gdb.p("$priv=3")
667 main_address = self.gdb.p("$pc")
668 self.gdb.stepi()
669 assertEqual("%x" % self.gdb.p("$pc"), "%x" % (main_address+4))
670
671 # User mode
672 self.gdb.p("$priv=0")
673 self.gdb.stepi()
674 # Should have taken an exception, so be nowhere near main.
675 pc = self.gdb.p("$pc")
676 assertTrue(pc < main_address or pc > main_address + 0x100)
677
678 parsed = None
679 def main():
680 parser = argparse.ArgumentParser(
681 description="Test that gdb can talk to a RISC-V target.",
682 epilog="""
683 Example command line from the real world:
684 Run all RegsTest cases against a physical FPGA, with custom openocd command:
685 ./gdbserver.py --freedom-e300 --server_cmd "$HOME/SiFive/openocd/src/openocd -s $HOME/SiFive/openocd/tcl -d" Simple
686 """)
687 targets.add_target_options(parser)
688
689 testlib.add_test_run_options(parser)
690
691 # TODO: remove global
692 global parsed # pylint: disable=global-statement
693 parsed = parser.parse_args()
694
695 target = parsed.target(parsed.server_cmd, parsed.sim_cmd, parsed.isolate)
696 if parsed.xlen:
697 target.xlen = parsed.xlen
698
699 module = sys.modules[__name__]
700
701 return testlib.run_all_tests(module, target, parsed)
702
703 # TROUBLESHOOTING TIPS
704 # If a particular test fails, run just that one test, eg.:
705 # ./gdbserver.py MprvTest.test_mprv
706 # Then inspect gdb.log and spike.log to see what happened in more detail.
707
708 if __name__ == '__main__':
709 sys.exit(main())