[PATCH v4] [gdb] Add basic Z80 CPU support
Sergey Belyashov
sergey.belyashov@gmail.com
Tue Oct 6 10:17:02 GMT 2020
Hi,
There is instruction from Jakub Ladman on how to debug programs on the
Amstrad(Sinclair) ZX Spectrum +2B computer using GDB. Sources are
attached as an archive to the email.
howtouse.txt
Created on: 4. 10. 2020
Author: ladmanj
This is demonstration how to use Small Devices C Compiler, with
GNU AS assembler and GDB to debug Z80 code
Only assembler instructions stepping is possible at the time of
writing this text, because SDCC can't provide
the symbols (and maybe other information) in the way gdb needs.
The code being debugged is compiled and linked together with
GDB-STUB, which is relatively small piece of code
running on the target machine and provides interface between it
and the GDB itself.
This presentation is performed on the Amstrad(Sinclair) ZX
Spectrum +2B computer.
The tools used are:
z80-unknown-elf-as, z80-unknown-elf-ld z80-unknown-elf-objcopy
from the Sergey Belyashov's source tree from
https://github.com/b-s-a/binutils-gdb
bin2tap from https://sourceforge.net/projects/zxspectrumutils/
taptoser From Pavel Vymetálek's https://vym.cz/download/taptoser.tar.gz
to be used with Paul Farrow's modified 48k ROM-RS232
http://www.fruitcake.plus.com which redirects tape in&out to one
of the three possible (software emulated serial) ports.
The taptoser and the modified ROM isn't needed, the GDB-STUB and
the program to be debugged can also be loaded from
the physical tape if you are not equipped with some user
modifiable ROM cartridge, but because the serial connection
has to be used anyway for the stub/gdb communication it's a shame
not to use it also for the boot-up.
The z80-stub.c file which comes from the gdb source tree is
connected with the serial channel via
extern int getDebugChar (void) and extern void putDebugChar (int
ch) functions. These are in the thin wrapper file
io.c, and from this place assembly routines for the RS-232 serial
line are called.
The serial routines used here (rs232.s) are from this site:
https://cygnus.speccy.cz/download/zx128k_rs232/rs232_paul_farrow_57600_data_sequence_with_cts_flow_control.html
The binary file is built, converted to ZX Spectrum TAP file and
loaded to the target machine:
$ make upload
Reset ZX spectrum with Paul Farrow's RS232 ROM
Press any key to continue
Now run LOAD ""
taptoser gdbstub.tap -d /dev/ttyUSB0
Serial device: /dev/ttyUSB0, communication speed is: 57600 Bd
Filename: gdbstub
Flag: 0 Type: 0 => program
Program length: 93 bytes Runs from line 10 Length
without variables: 93 bytes
Proceed bytes: 95/ 95
[==================================================================================================]
100 %
Filename: gdbstub
Flag: 0 Type: 3 => bytes Start address: 32768 Length:
3056 bytes 3rd param: 32768
Proceed bytes: 3058/ 3058
[==================================================================================================]
100 %
The whole code is started by the code in mycrt0.s. The bin2tap
utility has appended a machine code loader
in basic to the tape file.
The basic loader places the code at the address 0x8000 and there
the machine code is run from,
the ROM cartridge (if present) is then switched off, the whole
code is copied from 0x8000
(bank 2 where we are running now) to 0xc000 (bank 0)
the ZX Spectrum +2 memory is switched to all-ram mode in such
way, the bank 0 is then at address 0x0000.
Then the program jumps to address 0x0000 and is initialized as
any other sdcc compiled program.
After initialization but before thi final jump to _main (to C
main function), the debug_exception function is called
and there the gdb-stub is finally waiting for the connection of the gdb.
When the z80-unknown-elf-gdb is run, the .gdbinit file is
examined and following commands are executed from it:
set remoteflow on
target remote /dev/ttyUSB0
Note: The software emulated serial port in the remote can't work
without hardware handshake enabled on the PC side.
The gdb prompt then looks like this:
$ z80-unknown-elf-gdb
GNU gdb (GDB) 10.0.50.20200317-git
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu
--target=z80-unknown-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x0000010d in ?? ()
(gdb)
Then the memory can be examined this way:
(gdb) x/20i 0x100
0x100: ld sp,0xff00
0x103: call 0x0146
0x106: ld hl,0x0005
0x109: push hl
0x10a: call 0x0210
=> 0x10d: call 0x0af2
0x110: jp 0x015a
0x113: nop
0x114: nop
0x115: nop
0x116: nop
0x117: nop
0x118: nop
0x119: nop
0x11a: nop
0x11b: nop
0x11c: nop
0x11d: nop
0x11e: nop
0x11f: nop
Displaying of the current instruction can be switched on:
(gdb) display/i $pc
1: x/i $pc
=> 0x10d: call 0x0af2
And then the instruction by instruction can be performed:
(gdb) si
warning: Unable to determine inferior's software breakpoint type:
couldn't find `_break_handler' function in the executable. Will be
used default software breakpoint instruction RST 0x08.
0x00000af2 in ?? ()
1: x/i $pc
=> 0xaf2: call 0x0af8
(gdb)
0x00000af8 in ?? ()
1: x/i $pc
=> 0xaf8: ld b,0x00
(gdb)
0x00000afa in ?? ()
1: x/i $pc
=> 0xafa: ld a,b
(gdb)
0x00000afb in ?? ()
1: x/i $pc
=> 0xafb: out (0xfe),a
(gdb)
0x00000afd in ?? ()
1: x/i $pc
=> 0xafd: inc b
(gdb)
0x00000afe in ?? ()
1: x/i $pc
=> 0xafe: xor a
(gdb)
0x00000aff in ?? ()
1: x/i $pc
=> 0xaff: in a,(0xfe)
(gdb)
0x00000b01 in ?? ()
1: x/i $pc
=> 0xb01: cpl
(gdb)
0x00000b02 in ?? ()
1: x/i $pc
=> 0xb02: and 0x1f
(gdb)
0x00000b04 in ?? ()
1: x/i $pc
=> 0xb04: jp z,0x0afa
(gdb)
0x00000afa in ?? ()
1: x/i $pc
=> 0xafa: ld a,b
(gdb)
You can load your binary to any free location of the RAM and do
the debugging.
If you lose control of the program (and it didn't overwrite
anything important), you can interrupt it
by the NMI button, if your machine or ROM cartridge is equipped with one.
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000aff in ?? ()
1: x/i $pc
=> 0xaff: in a,(0xfe)
That's all folks!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: z80_debug.tar.gz
Type: application/gzip
Size: 14789 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/gdb-patches/attachments/20201006/f669580c/attachment-0001.gz>
More information about the Gdb-patches
mailing list