From 01d6960d6d6d980e2ca3919c5b231705f3f3f6db Mon Sep 17 00:00:00 2001 From: Ian C Date: Thu, 7 Sep 2006 23:46:31 +0000 Subject: Added new Z80 core --- src/Makefile | 323 ++++--- src/expr.c | 735 ++++++++++++++++ src/expr.h | 59 ++ src/main.c | 8 +- src/memmenu.c | 14 +- src/z80.c | 366 ++++++++ src/z80.h | 245 ++++++ src/z80_decode.c | 2516 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/z80_dis.c | 2476 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/z80_private.h | 252 ++++++ src/zx81.c | 27 - src/zx81.h | 2 - 12 files changed, 6845 insertions(+), 178 deletions(-) create mode 100644 src/expr.c create mode 100644 src/expr.h create mode 100644 src/z80.c create mode 100644 src/z80.h create mode 100644 src/z80_decode.c create mode 100644 src/z80_dis.c create mode 100644 src/z80_private.h diff --git a/src/Makefile b/src/Makefile index 271fa37..7335868 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,7 @@ # # ------------------------------------------------------------------------- # -# $Id: Makefile,v 1.9 2004-01-23 20:05:54 ianc Exp $ +# $Id: Makefile,v 1.10 2006-09-07 23:46:31 ianc Exp $ # @@ -30,8 +30,6 @@ CFLAGS = -g -Wall -Werror -pedantic -ansi TARGET = ezx81 -Z80LIB = z80/z80.a - SOURCE = main.c \ zx81.c \ config.c \ @@ -39,7 +37,11 @@ SOURCE = main.c \ gui.c \ memmenu.c \ util.c \ - exit.c + exit.c \ + expr.c \ + z80.c \ + z80_decode.c \ + z80_dis.c OBJECTS = main.o \ zx81.o \ @@ -48,11 +50,15 @@ OBJECTS = main.o \ gui.o \ memmenu.o \ util.o \ - exit.o + exit.o \ + expr.o \ + z80.o \ + z80_decode.o \ + z80_dis.o -CFLAGS += -Iz80 `sdl-config --cflags` +CFLAGS += `sdl-config --cflags` -DENABLE_DISASSEM -LIBS = $(Z80LIB) `sdl-config --libs` +LIBS = `sdl-config --libs` $(TARGET): $(OBJECTS) $(Z80LIB) @@ -62,149 +68,194 @@ $(Z80LIB): z80/*.[ch] cd z80; make "EXTERNAL_CFLAGS=`sdl-config --cflags`" ; cd .. clean: - rm -f $(TARGET) $(OBJECTS) core - cd z80; make clean; cd .. + rm -f $(TARGET) $(TARGET).exe $(OBJECTS) core depend: makedepend -- $(CFLAGS) -- $(SOURCE) if test -e Makefile ; then rm -f Makefile.bak ; fi - cd z80; make depend ; cd .. # DO NOT DELETE THIS LINE -- make depend depends on it main.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h -main.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -main.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -main.o: /usr/local/include/SDL/SDL.h /usr/local/include/SDL/SDL_main.h -main.o: /usr/local/include/SDL/SDL_types.h -main.o: /usr/local/include/SDL/SDL_getenv.h -main.o: /usr/local/include/SDL/SDL_error.h -main.o: /usr/local/include/SDL/begin_code.h -main.o: /usr/local/include/SDL/close_code.h -main.o: /usr/local/include/SDL/SDL_rwops.h /usr/local/include/SDL/SDL_timer.h -main.o: /usr/local/include/SDL/SDL_audio.h -main.o: /usr/local/include/SDL/SDL_byteorder.h -main.o: /usr/local/include/SDL/SDL_cdrom.h -main.o: /usr/local/include/SDL/SDL_joystick.h -main.o: /usr/local/include/SDL/SDL_events.h -main.o: /usr/local/include/SDL/SDL_active.h -main.o: /usr/local/include/SDL/SDL_keyboard.h -main.o: /usr/local/include/SDL/SDL_keysym.h -main.o: /usr/local/include/SDL/SDL_mouse.h /usr/local/include/SDL/SDL_video.h -main.o: /usr/local/include/SDL/SDL_mutex.h /usr/local/include/SDL/SDL_quit.h -main.o: /usr/local/include/SDL/SDL_version.h z80/z80.h zx81.h gfx.h gui.h +main.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +main.o: /usr/include/machine/_types.h /usr/include/stdio.h +main.o: /usr/include/string.h /usr/include/strings.h +main.o: /usr/local/include/SDL11/SDL.h /usr/local/include/SDL11/SDL_main.h +main.o: /usr/local/include/SDL11/SDL_types.h +main.o: /usr/local/include/SDL11/SDL_getenv.h +main.o: /usr/local/include/SDL11/SDL_error.h +main.o: /usr/local/include/SDL11/begin_code.h +main.o: /usr/local/include/SDL11/close_code.h +main.o: /usr/local/include/SDL11/SDL_rwops.h +main.o: /usr/local/include/SDL11/SDL_timer.h +main.o: /usr/local/include/SDL11/SDL_audio.h +main.o: /usr/local/include/SDL11/SDL_byteorder.h +main.o: /usr/local/include/SDL11/SDL_cdrom.h +main.o: /usr/local/include/SDL11/SDL_joystick.h +main.o: /usr/local/include/SDL11/SDL_events.h +main.o: /usr/local/include/SDL11/SDL_active.h +main.o: /usr/local/include/SDL11/SDL_keyboard.h +main.o: /usr/local/include/SDL11/SDL_keysym.h +main.o: /usr/local/include/SDL11/SDL_mouse.h +main.o: /usr/local/include/SDL11/SDL_video.h +main.o: /usr/local/include/SDL11/SDL_mutex.h +main.o: /usr/local/include/SDL11/SDL_quit.h +main.o: /usr/local/include/SDL11/SDL_version.h z80.h zx81.h gfx.h gui.h main.o: memmenu.h config.h exit.h zx81.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h -zx81.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -zx81.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -zx81.o: zx81.h z80/z80.h /usr/local/include/SDL/SDL.h -zx81.o: /usr/local/include/SDL/SDL_main.h /usr/local/include/SDL/SDL_types.h -zx81.o: /usr/local/include/SDL/SDL_getenv.h -zx81.o: /usr/local/include/SDL/SDL_error.h -zx81.o: /usr/local/include/SDL/begin_code.h -zx81.o: /usr/local/include/SDL/close_code.h -zx81.o: /usr/local/include/SDL/SDL_rwops.h /usr/local/include/SDL/SDL_timer.h -zx81.o: /usr/local/include/SDL/SDL_audio.h -zx81.o: /usr/local/include/SDL/SDL_byteorder.h -zx81.o: /usr/local/include/SDL/SDL_cdrom.h -zx81.o: /usr/local/include/SDL/SDL_joystick.h -zx81.o: /usr/local/include/SDL/SDL_events.h -zx81.o: /usr/local/include/SDL/SDL_active.h -zx81.o: /usr/local/include/SDL/SDL_keyboard.h -zx81.o: /usr/local/include/SDL/SDL_keysym.h -zx81.o: /usr/local/include/SDL/SDL_mouse.h /usr/local/include/SDL/SDL_video.h -zx81.o: /usr/local/include/SDL/SDL_mutex.h /usr/local/include/SDL/SDL_quit.h -zx81.o: /usr/local/include/SDL/SDL_version.h gfx.h gui.h config.h util.h +zx81.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +zx81.o: /usr/include/machine/_types.h /usr/include/stdio.h +zx81.o: /usr/include/string.h /usr/include/strings.h zx81.h z80.h +zx81.o: /usr/local/include/SDL11/SDL.h /usr/local/include/SDL11/SDL_main.h +zx81.o: /usr/local/include/SDL11/SDL_types.h +zx81.o: /usr/local/include/SDL11/SDL_getenv.h +zx81.o: /usr/local/include/SDL11/SDL_error.h +zx81.o: /usr/local/include/SDL11/begin_code.h +zx81.o: /usr/local/include/SDL11/close_code.h +zx81.o: /usr/local/include/SDL11/SDL_rwops.h +zx81.o: /usr/local/include/SDL11/SDL_timer.h +zx81.o: /usr/local/include/SDL11/SDL_audio.h +zx81.o: /usr/local/include/SDL11/SDL_byteorder.h +zx81.o: /usr/local/include/SDL11/SDL_cdrom.h +zx81.o: /usr/local/include/SDL11/SDL_joystick.h +zx81.o: /usr/local/include/SDL11/SDL_events.h +zx81.o: /usr/local/include/SDL11/SDL_active.h +zx81.o: /usr/local/include/SDL11/SDL_keyboard.h +zx81.o: /usr/local/include/SDL11/SDL_keysym.h +zx81.o: /usr/local/include/SDL11/SDL_mouse.h +zx81.o: /usr/local/include/SDL11/SDL_video.h +zx81.o: /usr/local/include/SDL11/SDL_mutex.h +zx81.o: /usr/local/include/SDL11/SDL_quit.h +zx81.o: /usr/local/include/SDL11/SDL_version.h gfx.h gui.h config.h util.h zx81.o: exit.h config.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h -config.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -config.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -config.o: exit.h config.h +config.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +config.o: /usr/include/machine/_types.h /usr/include/stdio.h +config.o: /usr/include/string.h /usr/include/strings.h exit.h config.h gfx.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h -gfx.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -gfx.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -gfx.o: /usr/include/stdarg.h gfx.h /usr/local/include/SDL/SDL.h -gfx.o: /usr/local/include/SDL/SDL_main.h /usr/local/include/SDL/SDL_types.h -gfx.o: /usr/local/include/SDL/SDL_getenv.h /usr/local/include/SDL/SDL_error.h -gfx.o: /usr/local/include/SDL/begin_code.h -gfx.o: /usr/local/include/SDL/close_code.h /usr/local/include/SDL/SDL_rwops.h -gfx.o: /usr/local/include/SDL/SDL_timer.h /usr/local/include/SDL/SDL_audio.h -gfx.o: /usr/local/include/SDL/SDL_byteorder.h -gfx.o: /usr/local/include/SDL/SDL_cdrom.h -gfx.o: /usr/local/include/SDL/SDL_joystick.h -gfx.o: /usr/local/include/SDL/SDL_events.h -gfx.o: /usr/local/include/SDL/SDL_active.h -gfx.o: /usr/local/include/SDL/SDL_keyboard.h -gfx.o: /usr/local/include/SDL/SDL_keysym.h /usr/local/include/SDL/SDL_mouse.h -gfx.o: /usr/local/include/SDL/SDL_video.h /usr/local/include/SDL/SDL_mutex.h -gfx.o: /usr/local/include/SDL/SDL_quit.h /usr/local/include/SDL/SDL_version.h -gfx.o: exit.h config.h font.h +gfx.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +gfx.o: /usr/include/machine/_types.h /usr/include/stdio.h +gfx.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdarg.h +gfx.o: gfx.h /usr/local/include/SDL11/SDL.h +gfx.o: /usr/local/include/SDL11/SDL_main.h +gfx.o: /usr/local/include/SDL11/SDL_types.h +gfx.o: /usr/local/include/SDL11/SDL_getenv.h +gfx.o: /usr/local/include/SDL11/SDL_error.h +gfx.o: /usr/local/include/SDL11/begin_code.h +gfx.o: /usr/local/include/SDL11/close_code.h +gfx.o: /usr/local/include/SDL11/SDL_rwops.h +gfx.o: /usr/local/include/SDL11/SDL_timer.h +gfx.o: /usr/local/include/SDL11/SDL_audio.h +gfx.o: /usr/local/include/SDL11/SDL_byteorder.h +gfx.o: /usr/local/include/SDL11/SDL_cdrom.h +gfx.o: /usr/local/include/SDL11/SDL_joystick.h +gfx.o: /usr/local/include/SDL11/SDL_events.h +gfx.o: /usr/local/include/SDL11/SDL_active.h +gfx.o: /usr/local/include/SDL11/SDL_keyboard.h +gfx.o: /usr/local/include/SDL11/SDL_keysym.h +gfx.o: /usr/local/include/SDL11/SDL_mouse.h +gfx.o: /usr/local/include/SDL11/SDL_video.h +gfx.o: /usr/local/include/SDL11/SDL_mutex.h +gfx.o: /usr/local/include/SDL11/SDL_quit.h +gfx.o: /usr/local/include/SDL11/SDL_version.h exit.h config.h font.h gui.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h -gui.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -gui.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -gui.o: /usr/include/stdarg.h /usr/include/ctype.h /usr/include/runetype.h -gui.o: gui.h /usr/local/include/SDL/SDL.h /usr/local/include/SDL/SDL_main.h -gui.o: /usr/local/include/SDL/SDL_types.h /usr/local/include/SDL/SDL_getenv.h -gui.o: /usr/local/include/SDL/SDL_error.h /usr/local/include/SDL/begin_code.h -gui.o: /usr/local/include/SDL/close_code.h /usr/local/include/SDL/SDL_rwops.h -gui.o: /usr/local/include/SDL/SDL_timer.h /usr/local/include/SDL/SDL_audio.h -gui.o: /usr/local/include/SDL/SDL_byteorder.h -gui.o: /usr/local/include/SDL/SDL_cdrom.h -gui.o: /usr/local/include/SDL/SDL_joystick.h -gui.o: /usr/local/include/SDL/SDL_events.h -gui.o: /usr/local/include/SDL/SDL_active.h -gui.o: /usr/local/include/SDL/SDL_keyboard.h -gui.o: /usr/local/include/SDL/SDL_keysym.h /usr/local/include/SDL/SDL_mouse.h -gui.o: /usr/local/include/SDL/SDL_video.h /usr/local/include/SDL/SDL_mutex.h -gui.o: /usr/local/include/SDL/SDL_quit.h /usr/local/include/SDL/SDL_version.h -gui.o: gfx.h util.h exit.h +gui.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +gui.o: /usr/include/machine/_types.h /usr/include/stdio.h +gui.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdarg.h +gui.o: /usr/include/ctype.h /usr/include/_ctype.h /usr/include/runetype.h +gui.o: gui.h /usr/local/include/SDL11/SDL.h +gui.o: /usr/local/include/SDL11/SDL_main.h +gui.o: /usr/local/include/SDL11/SDL_types.h +gui.o: /usr/local/include/SDL11/SDL_getenv.h +gui.o: /usr/local/include/SDL11/SDL_error.h +gui.o: /usr/local/include/SDL11/begin_code.h +gui.o: /usr/local/include/SDL11/close_code.h +gui.o: /usr/local/include/SDL11/SDL_rwops.h +gui.o: /usr/local/include/SDL11/SDL_timer.h +gui.o: /usr/local/include/SDL11/SDL_audio.h +gui.o: /usr/local/include/SDL11/SDL_byteorder.h +gui.o: /usr/local/include/SDL11/SDL_cdrom.h +gui.o: /usr/local/include/SDL11/SDL_joystick.h +gui.o: /usr/local/include/SDL11/SDL_events.h +gui.o: /usr/local/include/SDL11/SDL_active.h +gui.o: /usr/local/include/SDL11/SDL_keyboard.h +gui.o: /usr/local/include/SDL11/SDL_keysym.h +gui.o: /usr/local/include/SDL11/SDL_mouse.h +gui.o: /usr/local/include/SDL11/SDL_video.h +gui.o: /usr/local/include/SDL11/SDL_mutex.h +gui.o: /usr/local/include/SDL11/SDL_quit.h +gui.o: /usr/local/include/SDL11/SDL_version.h gfx.h util.h exit.h memmenu.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h -memmenu.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -memmenu.o: /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -memmenu.o: /usr/include/ctype.h /usr/include/runetype.h memmenu.h z80/z80.h -memmenu.o: zx81.h /usr/local/include/SDL/SDL.h -memmenu.o: /usr/local/include/SDL/SDL_main.h -memmenu.o: /usr/local/include/SDL/SDL_types.h -memmenu.o: /usr/local/include/SDL/SDL_getenv.h -memmenu.o: /usr/local/include/SDL/SDL_error.h -memmenu.o: /usr/local/include/SDL/begin_code.h -memmenu.o: /usr/local/include/SDL/close_code.h -memmenu.o: /usr/local/include/SDL/SDL_rwops.h -memmenu.o: /usr/local/include/SDL/SDL_timer.h -memmenu.o: /usr/local/include/SDL/SDL_audio.h -memmenu.o: /usr/local/include/SDL/SDL_byteorder.h -memmenu.o: /usr/local/include/SDL/SDL_cdrom.h -memmenu.o: /usr/local/include/SDL/SDL_joystick.h -memmenu.o: /usr/local/include/SDL/SDL_events.h -memmenu.o: /usr/local/include/SDL/SDL_active.h -memmenu.o: /usr/local/include/SDL/SDL_keyboard.h -memmenu.o: /usr/local/include/SDL/SDL_keysym.h -memmenu.o: /usr/local/include/SDL/SDL_mouse.h -memmenu.o: /usr/local/include/SDL/SDL_video.h -memmenu.o: /usr/local/include/SDL/SDL_mutex.h -memmenu.o: /usr/local/include/SDL/SDL_quit.h -memmenu.o: /usr/local/include/SDL/SDL_version.h gfx.h gui.h util.h +memmenu.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +memmenu.o: /usr/include/machine/_types.h /usr/include/stdio.h +memmenu.o: /usr/include/string.h /usr/include/strings.h /usr/include/ctype.h +memmenu.o: /usr/include/_ctype.h /usr/include/runetype.h memmenu.h z80.h +memmenu.o: zx81.h /usr/local/include/SDL11/SDL.h +memmenu.o: /usr/local/include/SDL11/SDL_main.h +memmenu.o: /usr/local/include/SDL11/SDL_types.h +memmenu.o: /usr/local/include/SDL11/SDL_getenv.h +memmenu.o: /usr/local/include/SDL11/SDL_error.h +memmenu.o: /usr/local/include/SDL11/begin_code.h +memmenu.o: /usr/local/include/SDL11/close_code.h +memmenu.o: /usr/local/include/SDL11/SDL_rwops.h +memmenu.o: /usr/local/include/SDL11/SDL_timer.h +memmenu.o: /usr/local/include/SDL11/SDL_audio.h +memmenu.o: /usr/local/include/SDL11/SDL_byteorder.h +memmenu.o: /usr/local/include/SDL11/SDL_cdrom.h +memmenu.o: /usr/local/include/SDL11/SDL_joystick.h +memmenu.o: /usr/local/include/SDL11/SDL_events.h +memmenu.o: /usr/local/include/SDL11/SDL_active.h +memmenu.o: /usr/local/include/SDL11/SDL_keyboard.h +memmenu.o: /usr/local/include/SDL11/SDL_keysym.h +memmenu.o: /usr/local/include/SDL11/SDL_mouse.h +memmenu.o: /usr/local/include/SDL11/SDL_video.h +memmenu.o: /usr/local/include/SDL11/SDL_mutex.h +memmenu.o: /usr/local/include/SDL11/SDL_quit.h +memmenu.o: /usr/local/include/SDL11/SDL_version.h gfx.h gui.h util.h util.o: /usr/include/stdio.h /usr/include/sys/cdefs.h -util.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -util.o: /usr/include/string.h /usr/include/strings.h /usr/include/stdarg.h -util.o: util.h /usr/include/stdlib.h exit.h +util.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +util.o: /usr/include/machine/_types.h /usr/include/string.h +util.o: /usr/include/strings.h /usr/include/stdarg.h util.h +util.o: /usr/include/stdlib.h exit.h exit.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h -exit.o: /usr/include/sys/_types.h /usr/include/machine/_types.h -exit.o: /usr/include/stdarg.h exit.h /usr/local/include/SDL/SDL.h -exit.o: /usr/local/include/SDL/SDL_main.h /usr/local/include/SDL/SDL_types.h -exit.o: /usr/local/include/SDL/SDL_getenv.h -exit.o: /usr/local/include/SDL/SDL_error.h -exit.o: /usr/local/include/SDL/begin_code.h -exit.o: /usr/local/include/SDL/close_code.h -exit.o: /usr/local/include/SDL/SDL_rwops.h /usr/include/stdio.h -exit.o: /usr/local/include/SDL/SDL_timer.h /usr/local/include/SDL/SDL_audio.h -exit.o: /usr/local/include/SDL/SDL_byteorder.h -exit.o: /usr/local/include/SDL/SDL_cdrom.h -exit.o: /usr/local/include/SDL/SDL_joystick.h -exit.o: /usr/local/include/SDL/SDL_events.h -exit.o: /usr/local/include/SDL/SDL_active.h -exit.o: /usr/local/include/SDL/SDL_keyboard.h -exit.o: /usr/local/include/SDL/SDL_keysym.h -exit.o: /usr/local/include/SDL/SDL_mouse.h /usr/local/include/SDL/SDL_video.h -exit.o: /usr/local/include/SDL/SDL_mutex.h /usr/local/include/SDL/SDL_quit.h -exit.o: /usr/local/include/SDL/SDL_version.h +exit.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +exit.o: /usr/include/machine/_types.h /usr/include/stdarg.h exit.h +exit.o: /usr/local/include/SDL11/SDL.h /usr/local/include/SDL11/SDL_main.h +exit.o: /usr/local/include/SDL11/SDL_types.h +exit.o: /usr/local/include/SDL11/SDL_getenv.h +exit.o: /usr/local/include/SDL11/SDL_error.h +exit.o: /usr/local/include/SDL11/begin_code.h +exit.o: /usr/local/include/SDL11/close_code.h +exit.o: /usr/local/include/SDL11/SDL_rwops.h /usr/include/stdio.h +exit.o: /usr/local/include/SDL11/SDL_timer.h +exit.o: /usr/local/include/SDL11/SDL_audio.h +exit.o: /usr/local/include/SDL11/SDL_byteorder.h +exit.o: /usr/local/include/SDL11/SDL_cdrom.h +exit.o: /usr/local/include/SDL11/SDL_joystick.h +exit.o: /usr/local/include/SDL11/SDL_events.h +exit.o: /usr/local/include/SDL11/SDL_active.h +exit.o: /usr/local/include/SDL11/SDL_keyboard.h +exit.o: /usr/local/include/SDL11/SDL_keysym.h +exit.o: /usr/local/include/SDL11/SDL_mouse.h +exit.o: /usr/local/include/SDL11/SDL_video.h +exit.o: /usr/local/include/SDL11/SDL_mutex.h +exit.o: /usr/local/include/SDL11/SDL_quit.h +exit.o: /usr/local/include/SDL11/SDL_version.h +expr.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +expr.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +expr.o: /usr/include/machine/_types.h /usr/include/stdio.h +expr.o: /usr/include/string.h /usr/include/strings.h /usr/include/ctype.h +expr.o: /usr/include/_ctype.h /usr/include/runetype.h +z80.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +z80.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +z80.o: /usr/include/machine/_types.h /usr/include/string.h +z80.o: /usr/include/strings.h z80.h z80_private.h +z80_decode.o: /usr/include/stdlib.h /usr/include/sys/cdefs.h +z80_decode.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +z80_decode.o: /usr/include/machine/_types.h /usr/include/limits.h +z80_decode.o: /usr/include/sys/limits.h /usr/include/machine/_limits.h +z80_decode.o: /usr/include/sys/syslimits.h z80.h z80_private.h +z80_dis.o: /usr/include/stdio.h /usr/include/sys/cdefs.h +z80_dis.o: /usr/include/sys/_null.h /usr/include/sys/_types.h +z80_dis.o: /usr/include/machine/_types.h /usr/include/string.h +z80_dis.o: /usr/include/strings.h /usr/include/stdarg.h z80.h z80_private.h diff --git a/src/expr.c b/src/expr.c new file mode 100644 index 0000000..6cd8237 --- /dev/null +++ b/src/expr.c @@ -0,0 +1,735 @@ +/* + expr - Simple, expression evaluator + + Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.co.uk) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + Expands an expression. + +*/ +static const char id[]="$Id$"; + +#include +#include +#include +#include + +/* ---------------------------------------- MACROS +*/ +#define TRUE 1 +#define FALSE 0 + +#define TYPE_OPERAND 0 +#define TYPE_VARIABLE 1 +#define TYPE_OPERATOR 2 /* This acts as a base for operator tokens */ +#define TYPE_LPAREN 3 +#define TYPE_RPAREN 4 +#define TYPE_DIVIDE 5 +#define TYPE_MULTIPLY 6 +#define TYPE_ADD 7 +#define TYPE_SUBTRACT 8 +#define TYPE_NOT 9 +#define TYPE_AND 10 +#define TYPE_OR 11 +#define TYPE_XOR 12 +#define TYPE_UNARY_PLUS 13 +#define TYPE_UNARY_NEG 14 +#define TYPE_SHIFTL 15 +#define TYPE_SHIFTR 16 +#define TYPE_EQUALITY 17 +#define TYPE_BOOL_AND 18 +#define TYPE_BOOL_OR 19 +#define TYPE_MODULUS 20 +#define TYPE_LT 21 +#define TYPE_GT 22 +#define TYPE_LTEQ 23 +#define TYPE_GTEQ 24 +#define TYPE_NOTEQUAL 25 + +#define SYM_LPAREN "(" +#define SYM_RPAREN ")" +#define SYM_DIVIDE "/" +#define SYM_MULTIPLY "*" +#define SYM_ADD "+" +#define SYM_SUBTRACT "-" +#define SYM_NOT "~" +#define SYM_AND "&" +#define SYM_OR "|" +#define SYM_XOR "^" +#define SYM_UNARY_PLUS "+" +#define SYM_UNARY_NEG "-" +#define SYM_SHIFTL "<<" +#define SYM_SHIFTR ">>" +#define SYM_EQUALITY "==" +#define SYM_BOOL_AND "&&" +#define SYM_BOOL_OR "||" +#define SYM_MODULUS "%" +#define SYM_LT "<" +#define SYM_GT ">" +#define SYM_LTEQ "<=" +#define SYM_GTEQ ">=" +#define SYM_NOTEQUAL "!=" + +#define OPERATOR_CHARS "()/*+-~&|^<>!=%" + +#define IS_OPERATOR_TYPE(a) ((a)>=TYPE_OPERATOR) + +#define IS_PAREN(c) ((c)==SYM_LPAREN[0] || (c)==SYM_RPAREN[0]) + +#define IS_OPERATOR(c) (strchr(OPERATOR_CHARS,(c))) + +#define IS_OPERAND_END(c) ((c)==' ' || (c)=='\t' || IS_OPERATOR(c)) + +/* ---------------------------------------- TYPES +*/ + +typedef struct stk + { + int token; + int priority; + int is_unary; + char *text; + struct stk *next; + } Stack; + + +typedef enum {OpBinary, OpPretendUnary, OpUnary} OpType; + +typedef struct + { + const char *symbol; + int priority; + int token; + OpType type; + int allow_unary; + } Operator; + + +typedef enum {OpOk, OpSyntaxError, OpUnknown} OpError; + + +/* ---------------------------------------- GLOBALS +*/ +static char error[1024]; + +static int (*expand)(void *client_data, + const char *p, + long *value); + +static void *client=NULL; + +static const Operator op_info[]= + { + /* Unary ops - must be first in list. Note that LPAREN is treated + as a unary as it must be preceeded by another operator, rather + than an operand. + */ + {SYM_NOT, 9, TYPE_NOT, OpUnary, TRUE}, + {SYM_UNARY_PLUS,9, TYPE_UNARY_PLUS,OpUnary, TRUE}, + {SYM_UNARY_NEG, 9, TYPE_UNARY_NEG, OpUnary, TRUE}, + {SYM_LPAREN, 99, TYPE_LPAREN, OpPretendUnary, TRUE}, + + /* Binary ops and don't care ops + */ + {SYM_RPAREN, 99, TYPE_RPAREN, OpBinary, FALSE}, + {SYM_SHIFTL, 6, TYPE_SHIFTL, OpBinary, TRUE}, + {SYM_SHIFTR, 6, TYPE_SHIFTR, OpBinary, TRUE}, + {SYM_MULTIPLY, 5, TYPE_MULTIPLY, OpBinary, TRUE}, + {SYM_DIVIDE, 5, TYPE_DIVIDE, OpBinary, TRUE}, + {SYM_MODULUS, 5, TYPE_MODULUS, OpBinary, TRUE}, + {SYM_ADD, 4, TYPE_ADD, OpBinary, TRUE}, + {SYM_SUBTRACT, 4, TYPE_SUBTRACT, OpBinary, TRUE}, + {SYM_EQUALITY, 1, TYPE_EQUALITY, OpBinary, TRUE}, + {SYM_NOTEQUAL, 1, TYPE_NOTEQUAL, OpBinary, TRUE}, + {SYM_LTEQ, 1, TYPE_LTEQ, OpBinary, TRUE}, + {SYM_GTEQ, 1, TYPE_GTEQ, OpBinary, TRUE}, + {SYM_LT, 1, TYPE_LT, OpBinary, TRUE}, + {SYM_GT, 1, TYPE_GT, OpBinary, TRUE}, + {SYM_BOOL_AND, 0, TYPE_BOOL_AND, OpBinary, TRUE}, + {SYM_AND, 0, TYPE_AND, OpBinary, TRUE}, + {SYM_BOOL_OR, 0, TYPE_BOOL_OR, OpBinary, TRUE}, + {SYM_OR, 0, TYPE_OR, OpBinary, TRUE}, + {SYM_XOR, 0, TYPE_XOR, OpBinary, TRUE}, + + {0,0,0} + }; + + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ + +/* malloc wrapper +*/ +static void *Malloc(size_t size) +{ + void *p=malloc(size); + + if (!p) + { + fprintf(stderr,"malloc failed\n"); + exit(EXIT_FAILURE); + } + + return p; +} + + +/* Copy a string +*/ +static char *CopyStr(const char *p) +{ + char *new=Malloc(strlen(p)+1); + + return strcpy(new,p); +} + + +/* Empty a stack +*/ +static Stack *ClearStack(Stack *stack) +{ + while(stack) + { + Stack *tmp=stack; + + stack=stack->next; + free(tmp->text); + free(tmp); + } + + return stack; +} + + +/* Push onto the stack +*/ +static Stack *Push(Stack *stack, int token, int priority, + int is_unary, const char *text) +{ + Stack *e=Malloc(sizeof *e); + + e->text=CopyStr(text); + e->priority=priority; + e->token=token; + e->is_unary=is_unary; + e->next=stack; + stack=e; + + return stack; +} + + +/* Destroy the top element on the stack +*/ +static Stack *Pop(Stack *stack) +{ + if (stack) + { + Stack *tmp=stack; + + stack=stack->next; + + free(tmp->text); + free(tmp); + } + + return stack; +} + + +/* Debug to dump a stack non-destructively +static void Dump(const char *name, Stack *stack) +{ + while (stack) + { + printf("%-10s: Type: %-2d is_unary: %d text: %s\n", + name,stack->token,stack->is_unary,stack->text); + + stack=stack->next; + } +} +*/ + + +/* Find the symbol for an operator +*/ +static const char *ToString(int token) +{ + static char buff[32]; + int f; + + strcpy(buff,"UNKNOWN"); + + for(f=0;op_info[f].symbol;f++) + { + if (op_info[f].token==token) + { + strcpy(buff,op_info[f].symbol); + return buff; + } + } + + return "UNKNOWN"; +} + + +/* Search the operator info +*/ +static OpError FindOp(const char *p, int prev_was_op, const Operator **op) +{ + int f; + int found=FALSE; + + *op=NULL; + + for(f=0;op_info[f].symbol;f++) + { + if (strncmp(op_info[f].symbol,p,strlen(op_info[f].symbol))==0) + { + found=TRUE; + + if ((prev_was_op && op_info[f].type!=OpBinary) || + (!prev_was_op && op_info[f].type==OpBinary)) + + { + *op=op_info+f; + return OpOk; + } + } + } + + if (found) + return OpSyntaxError; + else + return OpUnknown; +} + + +static Stack *ToPostfix(const char *expr) +{ + Stack *stack=NULL; + Stack *output=NULL; + char buff[1024]; + char *p; + int prev_was_op=TRUE; + + /* Parse the infix expression into postfix + */ + while(*expr) + { + if (IS_OPERATOR(*expr)) + { + /* Found an operator - parse it + */ + const Operator *op; + OpError op_err; + + op_err=FindOp(expr,prev_was_op,&op); + + /* Unknown operator in expression + */ + if (!op) + { + if (op_err==OpSyntaxError) + sprintf(error,"Syntax error with operator %c",*expr); + else + sprintf(error,"Unknown operator %c",*expr); + + stack=ClearStack(stack); + output=ClearStack(output); + + return NULL; + } + + /* Special handling for closing parenthesis + */ + if (op->token==TYPE_RPAREN) + { + while(stack && stack->token!=TYPE_LPAREN) + { + output=Push(output, + stack->token, + stack->priority, + stack->is_unary, + stack->text); + stack=Pop(stack); + } + + /* Syntax error in expression + */ + if (!stack) + { + sprintf(error,"Missing %s",SYM_LPAREN); + + stack=ClearStack(stack); + output=ClearStack(output); + + return NULL; + } + + /* Remove the opening bracket and continue + */ + stack=Pop(stack); + } + else + { + /* Output the stack until an operator of lower precedence is + found + */ + if (op->type==OpUnary) + { + while(stack && !IS_PAREN(stack->text[0]) && + !stack->is_unary && + (stack->priority >= op->priority)) + { + output=Push(output, + stack->token, + stack->priority, + stack->is_unary, + stack->text); + + stack=Pop(stack); + } + } + else + { + while(stack && !IS_PAREN(stack->text[0]) && + (stack->priority >= op->priority)) + { + output=Push(output, + stack->token, + stack->priority, + stack->is_unary, + stack->text); + + stack=Pop(stack); + } + } + + stack=Push(stack, + op->token, + op->priority, + op->type==OpUnary, + op->symbol); + } + + /* Move past token + */ + expr+=strlen(op->symbol); + + prev_was_op=op->allow_unary; + } + else + { + if (!isspace(*expr)) + { + /* Found an operand - parse and store the operand + */ + p=buff; + + while(*expr && !IS_OPERAND_END(*expr)) + { + *p++=*expr++; + } + + *p=0; + + /* Note that operands are marked as unary just to chose one over + the other branch in EvalPostfix() - no other reason + */ + output=Push(output,TYPE_OPERAND,0,TRUE,buff); + + prev_was_op=FALSE; + } + else + { + expr++; + } + } + } + + while(stack) + { + output=Push(output, + stack->token, + stack->priority, + stack->is_unary, + stack->text); + + stack=Pop(stack); + } + + /* Return the stack + */ + return output; +} + + +static int EvalPostfix(Stack **stack, long *result) +{ + Stack *expr; + int token; + + expr=*stack; + + if (!expr) + { + sprintf(error,"Called with empty postfix stack"); + return FALSE; + } + + token=expr->token; + + if (expr->is_unary) + { + if (token==TYPE_OPERAND) + { + char *endp; + + *result=strtol(expr->text,&endp,0); + + if (!(expr->text[0] && *endp==0)) + { + int ok=FALSE; + + if (expand) + ok=expand(client,expr->text,result); + + if (!ok) + { + sprintf(error,"Undefined variable '%s'",expr->text); + return FALSE; + } + } + + expr=Pop(expr); + } + else if (token==TYPE_VARIABLE) + { + int ok=FALSE; + + if (expand) + ok=expand(client,expr->text,result); + + if (!ok) + { + sprintf(error,"Undefined variable '%s'",expr->text); + return FALSE; + } + + expr=Pop(expr); + } + else + { + long val; + + expr=Pop(expr); + + if (!expr || !EvalPostfix(&expr,&val)) + { + sprintf(error,"Operator '%s' expects an argument", + ToString(token)); + *stack=expr; + return FALSE; + } + + switch(token) + { + case TYPE_NOT: + *result=~val; + break; + + case TYPE_UNARY_PLUS: + *result=+val; + break; + + case TYPE_UNARY_NEG: + *result=-val; + break; + + default: + sprintf(error,"Execpected unary token '%s' processed", + ToString(token)); + *stack=expr; + return FALSE; + break; + } + } + } + else + { + long left,right; + + expr=Pop(expr); + + if (!expr || !EvalPostfix(&expr,&right)) + { + sprintf(error,"Operator '%s' expects two arguments", + ToString(token)); + *stack=expr; + return FALSE; + } + + if (!expr || !EvalPostfix(&expr,&left)) + { + sprintf(error,"Operator '%s' expects two arguments", + ToString(token)); + *stack=expr; + return FALSE; + } + + switch(token) + { + case TYPE_DIVIDE: + *result=left/right; + break; + + case TYPE_MULTIPLY: + *result=left*right; + break; + + case TYPE_MODULUS: + *result=left%right; + break; + + case TYPE_ADD: + *result=left+right; + break; + + case TYPE_SUBTRACT: + *result=left-right; + break; + + case TYPE_AND: + *result=left&right; + break; + + case TYPE_OR: + *result=left|right; + break; + + case TYPE_BOOL_AND: + *result=left&&right; + break; + + case TYPE_BOOL_OR: + *result=left||right; + break; + + case TYPE_XOR: + *result=left^right; + break; + + case TYPE_SHIFTL: + if (right<0) + { + sprintf(error,"Cannot shift left by a " + "negative number (%ld)",right); + *stack=expr; + return FALSE; + } + + *result=left<>right; + break; + + case TYPE_EQUALITY: + *result=left==right; + break; + + case TYPE_NOTEQUAL: + *result=left!=right; + break; + + case TYPE_LT: + *result=leftright; + break; + + case TYPE_LTEQ: + *result=left<=right; + break; + + case TYPE_GTEQ: + *result=left>=right; + break; + + default: + sprintf(error,"Unexpected binary token '%s' processed", + ToString(token)); + *stack=expr; + return FALSE; + break; + } + } + + *stack=expr; + + return TRUE; +} + + +/* ---------------------------------------- INTERFACES +*/ + +int ExprEval(const char *expr, long *result, + int (*expand_var)(void *client_data, const char *p, long *value), + void *client_data) +{ + Stack *output; + int ret; + + expand=expand_var; + client=client_data; + + output=ToPostfix(expr); + + if (!output) + return FALSE; + + ret=EvalPostfix(&output,result); + + ClearStack(output); + + return ret; +} + + +/* Gets a readable reason for an error from ExprEval() or ExprParse. +*/ +const char *ExprError(void) +{ + return error; +} + + +/* END OF FILE */ diff --git a/src/expr.h b/src/expr.h new file mode 100644 index 0000000..2c77897 --- /dev/null +++ b/src/expr.h @@ -0,0 +1,59 @@ +/* + expr - Simple, expression evaluator + + Copyright (C) 2003 Ian Cowburn (ianc@noddybox.demon.co.uk) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + This is a simple expression evaluator, supporting user supplied variables. + + It works on longs, but a floating point version would be easy enough to + generate from this. + + NB: THIS CODE IS NOT THREAD SAFE +*/ + +#ifndef EXPR_H +#define EXPR_H "$Id$" + +/* ---------------------------------------- INTERFACES +*/ + +/* Returns the result of expr and stores the answer in result. + Returns FALSE on error. + + If expand_var is not NULL then unrecognised strings of characters + (basically anything that gives strtol() problems) are passed to that + to expand the value. The return of this routine should be TRUE if the + value was expanded into value. The client_data pointer is passed to + expand_var(). +*/ +int ExprEval(const char *expr, long *result, + int (*expand_var)(void *client_data, + const char *p, + long *value), + void *client_data); + + +/* Gets a readable reason for an error from ExprEval() or ExprParse. +*/ +const char *ExprError(void); + + +#endif + +/* END OF FILE */ diff --git a/src/main.c b/src/main.c index f6c5e6e..4aae0b3 100644 --- a/src/main.c +++ b/src/main.c @@ -73,12 +73,10 @@ int main(int argc, char *argv[]) trace=IConfig(CONF_TRACE); - z80=Z80Init(ZX81WriteMem, - ZX81ReadMem, - ZX81WriteWord, - ZX81ReadWord, - ZX81WritePort, + z80=Z80Init(ZX81ReadMem, + ZX81WriteMem, ZX81ReadPort, + ZX81WritePort, ZX81ReadForDisassem); GFXInit(); diff --git a/src/memmenu.c b/src/memmenu.c index 95429f9..81a8646 100644 --- a/src/memmenu.c +++ b/src/memmenu.c @@ -229,19 +229,19 @@ int DisplayZ80State(Z80State *s, int y, Uint32 col) static int EnterAddress(const char *prompt, Z80 *z80, Z80Word *w) { const char *p; - char *error; + char *error="NOT YET IMPLEMENTED"; long l; p=GUIInputString(prompt ? prompt : "Address?",""); if (*p) { - if (!Z80Expression(z80,p,&l,&error)) + if (1) /*(!Z80Expression(z80,p,&l,&error))*/ { GUIMessage(eMessageBox, "ERROR","%s",error ? error:"Invalid expression"); - free(error); + /* free(error); */ } else { @@ -486,7 +486,7 @@ static int Instruction(Z80 *z80, Z80Val data) { long l; - if (Z80Expression(z80,bpoint.expr[f],&l,NULL)) + if (0) /*(Z80Expression(z80,bpoint.expr[f],&l,NULL))*/ { if (l) brk=bpoint.expr[f]; @@ -731,15 +731,14 @@ static void PlaybackTrace(Z80 *z80) static void DoAddBreakpoint(Z80 *z80) { const char *expr; - char *error; - long l; + char *error=NULL; expr=GUIInputString("Expression?",""); if (!*expr) return; - if (!Z80Expression(z80,expr,&l,&error)) + if (0) /*(!Z80Expression(z80,expr,&l,&error))*/ { if (error) { @@ -749,7 +748,6 @@ static void DoAddBreakpoint(Z80 *z80) else { GUIMessage(eMessageBox,"ERROR","Expression is invalid"); - free(error); } } else diff --git a/src/z80.c b/src/z80.c new file mode 100644 index 0000000..60dbca4 --- /dev/null +++ b/src/z80.c @@ -0,0 +1,366 @@ +/* + + z80 - Z80 Emulator + + Copyright (C) 2006 Ian Cowburn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + + Z80 + +*/ +#include +#include + +#include "z80.h" +#include "z80_private.h" + +static const char ident[]="$Id$"; +static const char ident_z80_header[]=Z80_H; +static const char ident_z80_private_header[]=Z80_PRIVATE_H; + +Z80Label *z80_labels=NULL; + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static void InitTables() +{ + static int init=FALSE; + + if (init) + return; + + init=TRUE; + + Z80_InitialiseInternals(); +} + +static void Z80_CheckInterrupt(Z80 *cpu) +{ + /* Check interrupts + */ + if (cpu->raise) + { + if (cpu->nmi) + { + if (cpu->halt) + { + cpu->halt=FALSE; + CALLBACK(eZ80_Halt,0); + cpu->PC++; + } + + TSTATE(2); + cpu->IFF1=0; + cpu->nmi=FALSE; + PUSH(cpu->PC); + cpu->PC=0x66; + } + else if (cpu->IFF1) + { + if (cpu->halt) + { + cpu->halt=FALSE; + CALLBACK(eZ80_Halt,0); + cpu->PC++; + } + + TSTATE(2); + + switch(cpu->IM) + { + default: + case 0: + INC_R; + Z80_Decode(cpu,cpu->devbyte); + return; + break; + + case 1: + PUSH(cpu->PC); + cpu->PC=0x38; + break; + + case 2: + PUSH(cpu->PC); + cpu->PC=(Z80Word)cpu->I*256+cpu->devbyte; + break; + } + } + + cpu->raise=FALSE; + } +} + + +/* ---------------------------------------- INTERFACES +*/ + +Z80 *Z80Init(Z80ReadMemory read_memory, + Z80WriteMemory write_memory, + Z80ReadPort read_port, + Z80WritePort write_port, + Z80ReadMemory read_disassem) +{ + Z80 *cpu; + int f; + int r; + + InitTables(); + + if (!read_memory || !write_memory) + return NULL; + + cpu=malloc(sizeof *cpu); + + if (cpu) + { + cpu->mread=read_memory; + cpu->mwrite=write_memory; + cpu->pread=read_port; + cpu->pwrite=write_port; + cpu->disread=read_disassem; + + for(f=0;fcallback[f][r]=NULL; + + Z80Reset(cpu); + } + + return cpu; +} + + +void Z80Reset(Z80 *cpu) +{ + cpu->cycle=0; + cpu->PC=0; + + cpu->AF.w=0xffff; + cpu->BC.w=0xffff; + cpu->DE.w=0xffff; + cpu->HL.w=0xffff; + cpu->AF_=0xffff; + cpu->BC_=0xffff; + cpu->DE_=0xffff; + cpu->HL_=0xffff; + + cpu->IX.w=0xffff; + cpu->IY.w=0xffff; + + cpu->SP=0xffff; + cpu->IFF1=0; + cpu->IFF2=0; + cpu->IM=0; + cpu->I=0; + cpu->R=0; + cpu->halt=0; + + cpu->raise=FALSE; + cpu->nmi=FALSE; +} + + +void Z80SetPC(Z80 *cpu,Z80Word PC) +{ + cpu->PC=PC; +} + + +Z80Word Z80GetPC(Z80 *cpu) +{ + return cpu->PC; +} + + +void Z80ResetCycles(Z80 *cpu, Z80Val cycles) +{ + cpu->cycle=cycles; +} + + +int Z80LodgeCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback) +{ + int f; + + for(f=0;fcallback[reason][f]) + { + cpu->callback[reason][f]=callback; + return TRUE; + } + } + + return FALSE; +} + + +void Z80RemoveCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback) +{ + int f; + + for(f=0;fcallback[reason][f]==callback) + cpu->callback[reason][f]=NULL; +} + + +void Z80Interrupt(Z80 *cpu, Z80Byte devbyte) +{ + cpu->raise=TRUE; + cpu->devbyte=devbyte; + cpu->nmi=FALSE; +} + + +void Z80NMI(Z80 *cpu) +{ + cpu->raise=TRUE; + cpu->nmi=TRUE; +} + + +int Z80SingleStep(Z80 *cpu) +{ + Z80Byte opcode; + + cpu->last_cb=TRUE; + cpu->shift=0; + + Z80_CheckInterrupt(cpu); + + CALLBACK(eZ80_Instruction,cpu->cycle); + + INC_R; + + opcode=FETCH_BYTE; + + Z80_Decode(cpu,opcode); + + return cpu->last_cb; +} + + +void Z80Exec(Z80 *cpu) +{ + while (Z80SingleStep(cpu)); +} + + +void Z80GetState(Z80 *cpu, Z80State *state) +{ + state->cycle= cpu->cycle; + + state->AF = cpu->AF.w; + state->BC = cpu->BC.w; + state->DE = cpu->DE.w; + state->HL = cpu->HL.w; + + state->AF_ = cpu->AF_; + state->BC_ = cpu->BC_; + state->DE_ = cpu->DE_; + state->HL_ = cpu->HL_; + + state->IX = cpu->IX.w; + state->IY = cpu->IY.w; + + state->SP = cpu->SP; + state->PC = cpu->PC; + + state->IFF1 = cpu->IFF1; + state->IFF2 = cpu->IFF2; + state->IM = cpu->IM; + state->I = cpu->I; + state->R = cpu->R; +} + + +void Z80SetState(Z80 *cpu, const Z80State *state) +{ + cpu->cycle = state->cycle; + + cpu->AF.w = state->AF; + cpu->BC.w = state->BC; + cpu->DE.w = state->DE; + cpu->HL.w = state->HL; + + cpu->AF_ = state->AF_; + cpu->BC_ = state->BC_; + cpu->DE_ = state->DE_; + cpu->HL_ = state->HL_; + + cpu->IX.w = state->IX; + cpu->IY.w = state->IY; + + cpu->SP = state->SP; + cpu->PC = state->PC; + + cpu->IFF1 = state->IFF1; + cpu->IFF2 = state->IFF2; + cpu->IM = state->IM; + cpu->I = state->I; + cpu->R = state->R; +} + + +Z80Val Z80Cycles(Z80 *cpu) +{ + return cpu->cycle; +} + + +void Z80SetLabels(Z80Label labels[]) +{ + z80_labels=labels; +} + + +const char *Z80Disassemble(Z80 *cpu, Z80Word *pc) +{ +#ifdef ENABLE_DISASSEM + static char s[80]; + Z80Word opc,npc; + Z80Byte op; + int f; + + opc=*pc; + op=Z80_Dis_FetchByte(cpu,pc); + dis_opcode_z80[op](cpu,op,pc); + npc=*pc; + + strcpy(s,Z80_Dis_Printf("%-5s",Z80_Dis_GetOp())); + strcat(s,Z80_Dis_Printf("%-40s ;",Z80_Dis_GetArg())); + + for(f=0;f<5 && opc!=npc;f++) + strcat(s,Z80_Dis_Printf(" %.2x",(int)cpu->disread(cpu,opc++))); + + if (opc!=npc) + for(f=1;f<3;f++) + s[strlen(s)-f]='.'; + + return s; +#else + (*pc)+=4; + return "NO DISASSEMBLER"; +#endif +} + +/* END OF FILE */ diff --git a/src/z80.h b/src/z80.h new file mode 100644 index 0000000..0b7424b --- /dev/null +++ b/src/z80.h @@ -0,0 +1,245 @@ +/* + + z80 - Z80 emulation + + Copyright (C) 2006 Ian Cowburn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + +*/ + +#ifndef Z80_H +#define Z80_H "$Id$" + +/* ---------------------------------------- TYPES +*/ + +/* The processor +*/ +struct Z80; +typedef struct Z80 Z80; + + +/* Large unsigned type +*/ +typedef unsigned long Z80Val; + + +/* 8-bit type. The emulation will exit with code 2 if this isn't 8 bits. +*/ +typedef unsigned char Z80Byte; + + +/* 8-bit signed type. The emulation will exit with code 2 if this isn't 8 bits. +*/ +typedef signed char Z80Relative; + + +/* 16-bit type. The emulation will exit with code 2 if this isn't 16 bits. +*/ +typedef unsigned short Z80Word; + + +/* Interfaces used to handle memory +*/ +typedef Z80Byte (*Z80ReadMemory)(Z80 *cpu, Z80Word address); +typedef void (*Z80WriteMemory)(Z80 *cpu, Z80Word address, Z80Byte value); + + +/* Interfaces needed to handle ports (IN/OUT commands) +*/ +typedef Z80Byte (*Z80ReadPort)(Z80 *cpu, Z80Word address); +typedef void (*Z80WritePort)(Z80 *cpu, Z80Word address, Z80Byte value); + + +/* Callback. Callback should return TRUE for processing to continue. +*/ +typedef int (*Z80Callback)(Z80 *cpu, Z80Val data); + + +/* Callback reasons + + eZ80_Instruction Called before the initial fetch for an instruction + (called just to once no matter how many bytes the + instruction is made up of). + + eZ80_EDHook Called when an undefined ED opcode is executed. + + eZ80_Halt Called when the HALT instruction is hit and released. + + eZ80_RETI Called when the RETI instruction is executed +*/ +typedef enum +{ + eZ80_Instruction, /* data = no cycles since reset */ + eZ80_EDHook, /* data = byte after ED opcode (only for NOP opcodes) */ + eZ80_Halt, /* data = 1 halt raised, 0 halt cleared by int */ + eZ80_RETI, /* data = ignored */ + eZ80_NO_CALLBACK /* leave at end */ +} Z80CallbackReason; + + +/* Get/settable state of the Z80 +*/ +typedef struct +{ + Z80Word PC; + Z80Word SP; + + Z80Val cycle; + + Z80Word AF; + Z80Word BC; + Z80Word DE; + Z80Word HL; + + Z80Word AF_; /* Alternate registers */ + Z80Word BC_; + Z80Word DE_; + Z80Word HL_; + + Z80Word IX; + Z80Word IY; + + Z80Byte IFF1; + Z80Byte IFF2; + Z80Byte IM; + Z80Byte I; + Z80Byte R; +} Z80State; + + +/* Flags in the F register +*/ +typedef enum +{ + eZ80_Carry =0x01, + eZ80_Neg =0x02, + eZ80_PV =0x04, + eZ80_Hidden3 =0x08, + eZ80_HalfCarry =0x10, + eZ80_Hidden5 =0x20, + eZ80_Zero =0x40, + eZ80_Sign =0x80 +} Z80FlagRegister; + + +/* Disassembly label -- only useful if ENABLE_DISASSEMBLER is set. + Labels are stored as an array, where a NULL in the label field marks + the end of the list. +*/ +typedef struct +{ + Z80Word address; + const char *label; +} Z80Label; + + +/* ---------------------------------------- INTERFACES +*/ + + +/* Initialises the processor. +*/ +Z80 *Z80Init(Z80ReadMemory read_memory, + Z80WriteMemory write_memory, + Z80ReadPort read_port, + Z80WritePort write_port, + Z80ReadMemory read_for_disassem); + + +/* Resets the processor. +*/ +void Z80Reset(Z80 *cpu); + + +/* Sets the PC +*/ +void Z80SetPC(Z80 *cpu, Z80Word PC); + + +/* Gets the PC +*/ +Z80Word Z80GetPC(Z80 *cpu); + + +/* Sets the cycle count to the specified count +*/ +void Z80ResetCycles(Z80 *cpu, Z80Val cycles); + + +/* Lodge a callback to be invoked after special events. Returns FALSE + if the callback couldn't be lodged (there is a max of 10 callbacks per + reason). +*/ +int Z80LodgeCallback(Z80 *cpu, + Z80CallbackReason reason, + Z80Callback callback); + + +/* Remove a callback. Does nothing if reason was not lodged with + Z80LodgeCallback() +*/ +void Z80RemoveCallback(Z80 *cpu, + Z80CallbackReason reason, + Z80Callback callback); + + +/* Cause an interrupt before the next opcode. + devbyte is the byte generated by the device (if any). +*/ +void Z80Interrupt(Z80 *cpu, Z80Byte devbyte); + + +/* Cause an NMI +*/ +void Z80NMI(Z80 *cpu); + + +/* Execute a single instruction. Returns FALSE if any callback returned + FALSE. +*/ +int Z80SingleStep(Z80 *cpu); + + +/* Executes until a callback returns FALSE (never returns otherwise) +*/ +void Z80Exec(Z80 *cpu); + + +/* Interrogate the state of the Z80 +*/ +Z80Val Z80Cycles(Z80 *cpu); +void Z80GetState(Z80 *cpu, Z80State *state); +void Z80SetState(Z80 *cpu, const Z80State *state); + + +/* Set address to label mappings for the disassembler +*/ +void Z80SetLabels(Z80Label labels[]); + + +/* Simple disassembly of memory accessed through read_for_disassem. + addr is updated on exit. +*/ +const char *Z80Disassemble(Z80 *cpu, Z80Word *addr); + +#endif + +/* END OF FILE */ diff --git a/src/z80_decode.c b/src/z80_decode.c new file mode 100644 index 0000000..e78206c --- /dev/null +++ b/src/z80_decode.c @@ -0,0 +1,2516 @@ +/* + + z80 - Z80 Emulator + + Copyright (C) 2006 Ian Cowburn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + +*/ +#include +#include + +#include "z80.h" +#include "z80_private.h" + +static const char ident[]="$Id$"; + +/* ---------------------------------------- TABLES AND INIT +*/ +static Z80Byte PSZtable[512]; +static Z80Byte SZtable[512]; +static Z80Byte Ptable[512]; +static Z80Byte Stable[512]; +static Z80Byte Ztable[512]; + + +static int HI; +static int LO; + +/* ---------------------------------------- MISC FUNCTIONS +*/ +void Z80_InitialiseInternals(void) +{ + Z80Word f; + Z80Reg r; + + /* Check endianness + */ + r.w=0x1234; + + if (r.b[0] == 0x12) + { + HI=0; + LO=1; + } + else if (r.b[1] == 0x12) + { + HI=1; + LO=0; + } + else + { + exit(1); + } + + /* Check variable sizes + */ + if (CHAR_BIT!=8 || sizeof(Z80Word)!=2) + { + exit(2); + } + + /* Initialise flag tables + */ + for(f=0;f<256;f++) + { + Z80Byte p,z,s; + int b; + + p=0; + + for(b=0;b<8;b++) + if (f&(1<mwrite(cpu,addr,val); + cpu->mwrite(cpu,addr+1,val>>8); +} + + +/* ---------------------------------------- GENERAL MACROS +*/ +#define SWAP(A,B) \ +do { \ + unsigned swap_tmp; \ + swap_tmp=A; \ + A=B; \ + B=swap_tmp; \ +} while(0) + + +/* ---------------------------------------- ARITHMETIC OPS +*/ +#define ADD8(ONCE) \ +do { \ + Z80Byte VAL=ONCE; \ + unsigned w; \ + w=cpu->AF.b[HI]+(unsigned)VAL; \ + cpu->AF.b[LO]=SZtable[w]; \ + if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \ + if ((VAL^cpu->AF.b[HI]^0x80)&(VAL^w)&0x80) cpu->AF.b[LO]|=P_Z80; \ + SETHIDDEN(w); \ + cpu->AF.b[HI]=w; \ +} while(0) + + +#define ADC8(ONCE) \ +do { \ + Z80Byte VAL=ONCE; \ + unsigned w; \ + w=(cpu->AF.b[HI]+(unsigned)VAL+CARRY)&0x1ff; \ + cpu->AF.b[LO]=SZtable[w]; \ + if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \ + if ((VAL^cpu->AF.b[HI]^0x80)&(VAL^w)&0x80) cpu->AF.b[LO]|=P_Z80; \ + SETHIDDEN(w); \ + cpu->AF.b[HI]=w; \ +} while(0) + + +#define SUB8(ONCE) \ +do { \ + Z80Byte VAL=ONCE; \ + unsigned w; \ + w=(cpu->AF.b[HI]-(unsigned)VAL)&0x1ff; \ + cpu->AF.b[LO]=SZtable[w]|N_Z80; \ + if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \ + if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \ + SETHIDDEN(w); \ + cpu->AF.b[HI]=w; \ +} while(0) + + +#define CMP8(ONCE) \ +do { \ + Z80Byte VAL=ONCE; \ + unsigned w; \ + w=(cpu->AF.b[HI]-(unsigned)VAL)&0x1ff; \ + cpu->AF.b[LO]=SZtable[w]|N_Z80; \ + if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \ + if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \ + SETHIDDEN(VAL); \ +} while(0) + + +#define SBC8(ONCE) \ +do { \ + Z80Byte VAL=ONCE; \ + unsigned w; \ + w=(cpu->AF.b[HI]-(unsigned)VAL-CARRY)&0x1ff; \ + cpu->AF.b[LO]=SZtable[w]|N_Z80; \ + if ((cpu->AF.b[HI]^w^VAL)&H_Z80) cpu->AF.b[LO]|=H_Z80; \ + if ((VAL^cpu->AF.b[HI])&(cpu->AF.b[HI]^w)&0x80) cpu->AF.b[LO]|=P_Z80; \ + SETHIDDEN(w); \ + cpu->AF.b[HI]=w; \ +} while(0) + + +#define ADD16(REG,ONCE) \ +do { \ + Z80Word VAL=ONCE; \ + Z80Val w; \ + w=(REG)+(Z80Val)VAL; \ + cpu->AF.b[LO]&=(S_Z80|Z_Z80|V_Z80); \ + if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \ + if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \ + SETHIDDEN(w>>8); \ + (REG)=w; \ +} while(0) + + +#define ADC16(REG, ONCE) \ +do { \ + Z80Word VAL=ONCE; \ + Z80Val w; \ + w=(REG)+(Z80Val)VAL+CARRY; \ + cpu->AF.b[LO]=0; \ + if ((w&0xffff)==0) cpu->AF.b[LO]=Z_Z80; \ + if (w&0x8000) cpu->AF.b[LO]|=S_Z80; \ + if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \ + if ((VAL^(REG)^0x8000)&((REG)^w)&0x8000) cpu->AF.b[LO]|=P_Z80; \ + if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \ + SETHIDDEN(w>>8); \ + (REG)=w; \ +} while(0) + + +#define SBC16(REG, ONCE) \ +do { \ + Z80Word VAL=ONCE; \ + Z80Val w; \ + w=(REG)-(Z80Val)VAL-CARRY; \ + cpu->AF.b[LO]=N_Z80; \ + if (w&0x8000) cpu->AF.b[LO]|=S_Z80; \ + if ((w&0xffff)==0) cpu->AF.b[LO]|=Z_Z80; \ + if (w>0xffff) cpu->AF.b[LO]|=C_Z80; \ + if ((VAL^(REG))&((REG)^w)&0x8000) cpu->AF.b[LO]|=P_Z80; \ + if (((REG)^w^VAL)&0x1000) cpu->AF.b[LO]|=H_Z80; \ + SETHIDDEN(w>>8); \ + (REG)=w; \ +} while(0) + + +#define INC8(REG) \ +do { \ + (REG)++; \ + cpu->AF.b[LO]=CARRY|SZtable[(REG)]; \ + if ((REG)==0x80) cpu->AF.b[LO]|=P_Z80; \ + if (((REG)&0x0f)==0) cpu->AF.b[LO]|=H_Z80; \ +} while(0) + + +#define DEC8(REG) \ +do { \ + (REG)--; \ + cpu->AF.b[LO]=N_Z80|CARRY; \ + if ((REG)==0x7f) cpu->AF.b[LO]|=P_Z80; \ + if (((REG)&0x0f)==0x0f) cpu->AF.b[LO]|=H_Z80; \ + cpu->AF.b[LO]|=SZtable[(REG)]; \ +} while(0) + + +#define OP_ON_MEM(OP,addr) \ +do { \ + Z80Byte memop=cpu->mread(cpu,addr); \ + OP(memop); \ + cpu->mwrite(cpu,addr,memop); \ +} while(0) + + +#define OP_ON_MEM_WITH_ARG(OP,addr,arg) \ +do { \ + Z80Byte memop=cpu->mread(cpu,addr); \ + OP(memop,arg); \ + cpu->mwrite(cpu,addr,memop); \ +} while(0) + + +#define OP_ON_MEM_WITH_COPY(OP,addr,copy) \ +do { \ + Z80Byte memop=cpu->mread(cpu,addr); \ + OP(memop); \ + copy=memop; \ + cpu->mwrite(cpu,addr,memop); \ +} while(0) + + +#define OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,arg,copy) \ +do { \ + Z80Byte memop=cpu->mread(cpu,addr); \ + OP(memop,arg); \ + copy=memop; \ + cpu->mwrite(cpu,addr,memop); \ +} while(0) + + +/* ---------------------------------------- ROTATE AND SHIFT OPS +*/ +#define RRCA \ +do { \ + cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]&C_Z80); \ + cpu->AF.b[HI]=(cpu->AF.b[HI]>>1)|(cpu->AF.b[HI]<<7); \ + SETHIDDEN(cpu->AF.b[HI]); \ +} while(0) + + +#define RRA \ +do { \ + Z80Byte c; \ + c=CARRY; \ + cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]&C_Z80); \ + cpu->AF.b[HI]=(cpu->AF.b[HI]>>1)|(c<<7); \ + SETHIDDEN(cpu->AF.b[HI]); \ +} while(0) + + +#define RRC(REG) \ +do { \ + Z80Byte c; \ + c=(REG)&C_Z80; \ + (REG)=((REG)>>1)|((REG)<<7); \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +#define RR(REG) \ +do { \ + Z80Byte c; \ + c=(REG)&C_Z80; \ + (REG)=((REG)>>1)|(CARRY<<7); \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +#define RLCA \ +do { \ + cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]>>7); \ + cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|(cpu->AF.b[HI]>>7); \ + SETHIDDEN(cpu->AF.b[HI]); \ +} while(0) + + +#define RLA \ +do { \ + Z80Byte c; \ + c=CARRY; \ + cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80))|(cpu->AF.b[HI]>>7); \ + cpu->AF.b[HI]=(cpu->AF.b[HI]<<1)|c; \ + SETHIDDEN(cpu->AF.b[HI]); \ +} while(0) + + +#define RLC(REG) \ +do { \ + Z80Byte c; \ + c=(REG)>>7; \ + (REG)=((REG)<<1)|c; \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +#define RL(REG) \ +do { \ + Z80Byte c; \ + c=(REG)>>7; \ + (REG)=((REG)<<1)|CARRY; \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +#define SRL(REG) \ +do { \ + Z80Byte c; \ + c=(REG)&C_Z80; \ + (REG)>>=1; \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +#define SRA(REG) \ +do { \ + Z80Byte c; \ + c=(REG)&C_Z80; \ + (REG)=((REG)>>1)|((REG)&0x80); \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +#define SLL(REG) \ +do { \ + Z80Byte c; \ + c=(REG)>>7; \ + (REG)=((REG)<<1)|1; \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +#define SLA(REG) \ +do { \ + Z80Byte c; \ + c=(REG)>>7; \ + (REG)=(REG)<<1; \ + cpu->AF.b[LO]=PSZtable[(REG)]|c; \ + SETHIDDEN(REG); \ +} while(0) + + +/* ---------------------------------------- BOOLEAN OPS +*/ +#define AND(VAL) \ +do { \ + cpu->AF.b[HI]&=VAL; \ + cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]|H_Z80; \ + SETHIDDEN(cpu->AF.b[HI]); \ +} while(0) + + +#define OR(VAL) \ +do { \ + cpu->AF.b[HI]|=VAL; \ + cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]; \ + SETHIDDEN(cpu->AF.b[HI]); \ +} while(0) + + +#define XOR(VAL) \ +do { \ + cpu->AF.b[HI]^=VAL; \ + cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]]; \ + SETHIDDEN(cpu->AF.b[HI]); \ +} while(0) + + +#define BIT(REG,B) \ +do { \ + cpu->AF.b[LO]=CARRY|H_Z80; \ + if ((REG)&(1<AF.b[LO]|=S_Z80; \ + if (B==5 && (REG&B5_Z80)) cpu->AF.b[LO]|=B5_Z80; \ + if (B==3 && (REG&B3_Z80)) cpu->AF.b[LO]|=B3_Z80; \ + } \ + else \ + { \ + cpu->AF.b[LO]|=Z_Z80; \ + cpu->AF.b[LO]|=P_Z80; \ + } \ +} while(0) + +#define BIT_SET(REG,B) (REG)|=(1<PC); \ + } \ + else \ + { \ + TSTATE(5); \ + } \ +} while(0) + + +#define RST(ADDR) \ + TSTATE(11); \ + PUSH(cpu->PC); \ + cpu->PC=ADDR + +/* ---------------------------------------- BLOCK OPERATIONS +*/ +#define LDI \ +do { \ + Z80Byte b; \ + \ + b=PEEK(cpu->HL.w); \ + POKE(cpu->DE.w,b); \ + cpu->DE.w++; \ + cpu->HL.w++; \ + cpu->BC.w--; \ + \ + CLRFLAG(H_Z80); \ + CLRFLAG(N_Z80); \ + \ + if (cpu->BC.w) \ + SETFLAG(P_Z80); \ + else \ + CLRFLAG(P_Z80); \ + \ + SETHIDDEN(cpu->AF.b[HI]+b); \ +} while(0) + +#define LDD \ +do { \ + Z80Byte b; \ + \ + b=PEEK(cpu->HL.w); \ + POKE(cpu->DE.w,b); \ + cpu->DE.w--; \ + cpu->HL.w--; \ + cpu->BC.w--; \ + \ + CLRFLAG(H_Z80); \ + CLRFLAG(N_Z80); \ + \ + if (cpu->BC.w) \ + SETFLAG(P_Z80); \ + else \ + CLRFLAG(P_Z80); \ + \ + SETHIDDEN(cpu->AF.b[HI]+b); \ +} while(0) + +#define CPI \ +do { \ + Z80Byte c,b; \ + \ + c=CARRY; \ + b=PEEK(cpu->HL.w); \ + \ + CMP8(b); \ + \ + if (c) \ + SETFLAG(C_Z80); \ + else \ + CLRFLAG(C_Z80); \ + \ + cpu->HL.w++; \ + cpu->BC.w--; \ + \ + if (cpu->BC.w) \ + SETFLAG(P_Z80); \ + else \ + CLRFLAG(P_Z80); \ +} while(0) + +#define CPD \ +do { \ + Z80Byte c,b; \ + \ + c=CARRY; \ + b=PEEK(cpu->HL.w); \ + \ + CMP8(b); \ + \ + if (c) \ + SETFLAG(C_Z80); \ + else \ + CLRFLAG(C_Z80); \ + \ + cpu->HL.w--; \ + cpu->BC.w--; \ + \ + if (cpu->BC.w) \ + SETFLAG(P_Z80); \ + else \ + CLRFLAG(P_Z80); \ +} while(0) + +#define INI \ +do { \ + Z80Word w; \ + Z80Byte b; \ + \ + b=IN(cpu->BC.w); \ + POKE(cpu->HL.w,b); \ + \ + cpu->BC.b[HI]--; \ + cpu->HL.w++; \ + \ + cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \ + SETHIDDEN(cpu->BC.b[HI]); \ + \ + w=(((Z80Word)cpu->BC.b[LO])&0xff)+b; \ + \ + if (b&0x80) \ + SETFLAG(N_Z80); \ + \ + if (w&0x100) \ + { \ + SETFLAG(C_Z80); \ + SETFLAG(H_Z80); \ + } \ + else \ + { \ + CLRFLAG(C_Z80); \ + CLRFLAG(H_Z80); \ + } \ +} while(0) + +#define IND \ +do { \ + Z80Word w; \ + Z80Byte b; \ + \ + b=IN(cpu->BC.w); \ + POKE(cpu->HL.w,b); \ + \ + cpu->BC.b[HI]--; \ + cpu->HL.w--; \ + \ + cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \ + SETHIDDEN(cpu->BC.b[HI]); \ + \ + w=(((Z80Word)cpu->BC.b[LO])&0xff)+b; \ + \ + if (b&0x80) \ + SETFLAG(N_Z80); \ + \ + if (w&0x100) \ + { \ + SETFLAG(C_Z80); \ + SETFLAG(H_Z80); \ + } \ + else \ + { \ + CLRFLAG(C_Z80); \ + CLRFLAG(H_Z80); \ + } \ +} while(0) \ + +#define OUTI \ +do { \ + OUT(cpu->BC.w,PEEK(cpu->HL.w)); \ + \ + cpu->HL.w++; \ + cpu->BC.b[HI]--; \ + \ + cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \ + SETHIDDEN(cpu->BC.b[HI]); \ +} while(0) + +#define OUTD \ +do { \ + OUT(cpu->BC.w,PEEK(cpu->HL.w)); \ + \ + cpu->HL.w--; \ + cpu->BC.b[HI]--; \ + \ + cpu->AF.b[LO]=SZtable[cpu->BC.b[HI]]; \ + SETFLAG(N_Z80); \ + SETHIDDEN(cpu->BC.b[HI]); \ +} while(0) + + +/* ---------------------------------------- BASE OPCODE SHORT-HAND BLOCKS +*/ + +#define LD_BLOCK(BASE,DEST,DEST2) \ + case BASE: /* LD DEST,B */ \ + TSTATE(4); \ + DEST=cpu->BC.b[HI]; \ + break; \ + \ + case BASE+1: /* LD DEST,C */ \ + TSTATE(4); \ + DEST=cpu->BC.b[LO]; \ + break; \ + \ + case BASE+2: /* LD DEST,D */ \ + TSTATE(4); \ + DEST=cpu->DE.b[HI]; \ + break; \ + \ + case BASE+3: /* LD DEST,E */ \ + TSTATE(4); \ + DEST=cpu->DE.b[LO]; \ + break; \ + \ + case BASE+4: /* LD DEST,H */ \ + TSTATE(4); \ + DEST=*H; \ + break; \ + \ + case BASE+5: /* LD DEST,L */ \ + TSTATE(4); \ + DEST=*L; \ + break; \ + \ + case BASE+6: /* LD DEST,(HL) */ \ + TSTATE(7); \ + OFFSET(off); \ + DEST2=cpu->mread(cpu,*HL+off); \ + break; \ + \ + case BASE+7: /* LD DEST,A */ \ + TSTATE(4); \ + DEST=cpu->AF.b[HI]; \ + break; + +#define ALU_BLOCK(BASE,OP) \ + case BASE: /* OP A,B */ \ + TSTATE(4); \ + OP(cpu->BC.b[HI]); \ + break; \ + \ + case BASE+1: /* OP A,C */ \ + TSTATE(4); \ + OP(cpu->BC.b[LO]); \ + break; \ + \ + case BASE+2: /* OP A,D */ \ + TSTATE(4); \ + OP(cpu->DE.b[HI]); \ + break; \ + \ + case BASE+3: /* OP A,E */ \ + TSTATE(4); \ + OP(cpu->DE.b[LO]); \ + break; \ + \ + case BASE+4: /* OP A,H */ \ + TSTATE(4); \ + OP(*H); \ + break; \ + \ + case BASE+5: /* OP A,L */ \ + TSTATE(4); \ + OP(*L); \ + break; \ + \ + case BASE+6: /* OP A,(HL) */ \ + TSTATE(7); \ + OFFSET(off); \ + OP_ON_MEM(OP,*HL+off); \ + break; \ + \ + case BASE+7: /* OP A,A */ \ + TSTATE(4); \ + OP(cpu->AF.b[HI]); \ + break; + + +/* ---------------------------------------- CB OPCODE SHORT-HAND BLOCKS +*/ + +#define CB_ALU_BLOCK(BASE,OP) \ + case BASE: /* OP B */ \ + TSTATE(8); \ + OP(cpu->BC.b[HI]); \ + break; \ + \ + case BASE+1: /* OP C */ \ + TSTATE(8); \ + OP(cpu->BC.b[LO]); \ + break; \ + \ + case BASE+2: /* OP D */ \ + TSTATE(8); \ + OP(cpu->DE.b[HI]); \ + break; \ + \ + case BASE+3: /* OP E */ \ + TSTATE(8); \ + OP(cpu->DE.b[LO]); \ + break; \ + \ + case BASE+4: /* OP H */ \ + TSTATE(8); \ + OP(cpu->HL.b[HI]); \ + break; \ + \ + case BASE+5: /* OP L */ \ + TSTATE(8); \ + OP(cpu->HL.b[LO]); \ + break; \ + \ + case BASE+6: /* OP (HL) */ \ + TSTATE(15); \ + OP_ON_MEM(OP,cpu->HL.w); \ + break; \ + \ + case BASE+7: /* OP A */ \ + TSTATE(8); \ + OP(cpu->AF.b[HI]); \ + break; + +#define CB_BITMANIP_BLOCK(BASE,OP,BIT_NO) \ + case BASE: /* OP B */ \ + TSTATE(8); \ + OP(cpu->BC.b[HI],BIT_NO); \ + break; \ + \ + case BASE+1: /* OP C */ \ + TSTATE(8); \ + OP(cpu->BC.b[LO],BIT_NO); \ + break; \ + \ + case BASE+2: /* OP D */ \ + TSTATE(8); \ + OP(cpu->DE.b[HI],BIT_NO); \ + break; \ + \ + case BASE+3: /* OP E */ \ + TSTATE(8); \ + OP(cpu->DE.b[LO],BIT_NO); \ + break; \ + \ + case BASE+4: /* OP H */ \ + TSTATE(8); \ + OP(cpu->HL.b[HI],BIT_NO); \ + break; \ + \ + case BASE+5: /* OP L */ \ + TSTATE(8); \ + OP(cpu->HL.b[LO],BIT_NO); \ + break; \ + \ + case BASE+6: /* OP (HL) */ \ + TSTATE(12); \ + OP_ON_MEM_WITH_ARG(OP,cpu->HL.w,BIT_NO); \ + break; \ + \ + case BASE+7: /* OP A */ \ + TSTATE(8); \ + OP(cpu->AF.b[HI],BIT_NO); \ + break; + +/* ---------------------------------------- SHIFTED CB OPCODE SHORT-HAND BLOCKS +*/ + +#define SHIFTED_CB_ALU_BLOCK(BASE,OP) \ + case BASE: /* OP B */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_COPY(OP,addr,cpu->BC.b[HI]); \ + break; \ + \ + case BASE+1: /* OP C */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_COPY(OP,addr,cpu->BC.b[LO]); \ + break; \ + \ + case BASE+2: /* OP D */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_COPY(OP,addr,cpu->DE.b[HI]); \ + break; \ + \ + case BASE+3: /* OP E */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_COPY(OP,addr,cpu->DE.b[LO]); \ + break; \ + \ + case BASE+4: /* OP H */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_COPY(OP,addr,cpu->HL.b[HI]); \ + break; \ + \ + case BASE+5: /* OP L */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_COPY(OP,addr,cpu->HL.b[LO]); \ + break; \ + \ + case BASE+6: /* OP (HL) */ \ + TSTATE(15); \ + OP_ON_MEM(OP,addr); \ + break; \ + \ + case BASE+7: /* OP A */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_COPY(OP,addr,cpu->AF.b[HI]); \ + break; + +#define SHIFTED_CB_BITMANIP_BLOCK(BASE,OP,BIT_NO) \ + case BASE: /* OP B */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->BC.b[HI]); \ + break; \ + \ + case BASE+1: /* OP C */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->BC.b[LO]); \ + break; \ + \ + case BASE+2: /* OP D */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->DE.b[HI]); \ + break; \ + \ + case BASE+3: /* OP E */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->DE.b[LO]); \ + break; \ + \ + case BASE+4: /* OP H */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->HL.b[HI]); \ + break; \ + \ + case BASE+5: /* OP L */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->HL.b[LO]); \ + break; \ + \ + case BASE+6: /* OP (HL) */ \ + TSTATE(12); \ + OP_ON_MEM_WITH_ARG(OP,addr,BIT_NO); \ + break; \ + \ + case BASE+7: /* OP A */ \ + TSTATE(8); \ + OP_ON_MEM_WITH_ARG_AND_COPY(OP,addr,BIT_NO,cpu->AF.b[HI]); \ + break; + +/* ---------------------------------------- DAA +*/ + +/* This alogrithm is based on info from + http://www.worldofspectrum.org/faq/reference/z80reference.htm +*/ +static void DAA (Z80 *cpu) +{ + Z80Byte add=0; + Z80Byte carry=0; + Z80Byte nf=cpu->AF.b[LO]&N_Z80; + Z80Byte acc=cpu->AF.b[HI]; + + if (acc>0x99 || IS_C) + { + add|=0x60; + carry=C_Z80; + } + + if ((acc&0xf)>0x9 || IS_H) + { + add|=0x06; + } + + if (nf) + { + cpu->AF.b[HI]-=add; + } + else + { + cpu->AF.b[HI]+=add; + } + + cpu->AF.b[LO]=PSZtable[cpu->AF.b[HI]] + | carry + | nf + | ((acc^cpu->AF.b[HI])&H_Z80) + | (cpu->AF.b[HI]&(B3_Z80|B5_Z80)); +} + +/* ---------------------------------------- HANDLERS FOR ED OPCODES +*/ +static void DecodeED(Z80 *cpu, Z80Byte opcode) +{ + switch(opcode) + { + case 0x40: /* IN B,(C) */ + TSTATE(12); + + if (cpu->pread) + { + cpu->BC.b[HI]=cpu->pread(cpu,cpu->BC.w); + } + else + { + cpu->BC.b[HI]=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[HI]]; + SETHIDDEN(cpu->BC.b[HI]); + break; + + case 0x41: /* OUT (C),B */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->BC.b[HI]); + break; + + case 0x42: /* SBC HL,BC */ + TSTATE(15); + SBC16(cpu->HL.w,cpu->BC.w); + break; + + case 0x43: /* LD (nnnn),BC */ + TSTATE(20); + POKEW(FETCH_WORD,cpu->BC.w); + break; + + case 0x44: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x45: /* RETN */ + TSTATE(14); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x46: /* IM 0 */ + TSTATE(8); + cpu->IM=0; + break; + + case 0x47: /* LD I,A */ + TSTATE(9); + cpu->I=cpu->AF.b[HI]; + break; + + case 0x48: /* IN C,(C) */ + TSTATE(12); + + if (cpu->pread) + { + cpu->BC.b[LO]=cpu->pread(cpu,cpu->BC.w); + } + else + { + cpu->BC.b[LO]=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->BC.b[LO]]; + SETHIDDEN(cpu->BC.b[LO]); + break; + + case 0x49: /* OUT (C),C */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->BC.b[LO]); + break; + + case 0x4a: /* ADC HL,BC */ + TSTATE(15); + ADC16(cpu->HL.w,cpu->BC.w); + break; + + case 0x4b: /* LD BC,(nnnn) */ + TSTATE(20); + cpu->BC.w=PEEKW(FETCH_WORD); + break; + + case 0x4c: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x4d: /* RETI */ + TSTATE(14); + CALLBACK(eZ80_RETI,0); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x4e: /* IM 0/1 */ + TSTATE(8); + cpu->IM=0; + break; + + case 0x4f: /* LD R,A */ + TSTATE(9); + cpu->R=cpu->AF.b[HI]; + break; + + case 0x50: /* IN D,(C) */ + TSTATE(12); + + if (cpu->pread) + { + cpu->DE.b[HI]=cpu->pread(cpu,cpu->BC.w); + } + else + { + cpu->DE.b[HI]=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[HI]]; + SETHIDDEN(cpu->BC.b[HI]); + break; + + case 0x51: /* OUT (C),D */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->DE.b[HI]); + break; + + case 0x52: /* SBC HL,DE */ + TSTATE(15); + SBC16(cpu->HL.w,cpu->DE.w); + break; + + case 0x53: /* LD (nnnn),DE */ + TSTATE(20); + POKEW(FETCH_WORD,cpu->DE.w); + break; + + case 0x54: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x55: /* RETN */ + TSTATE(14); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x56: /* IM 1 */ + TSTATE(8); + cpu->IM=1; + break; + + case 0x57: /* LD A,I */ + TSTATE(9); + cpu->AF.b[HI]=cpu->I; + break; + + case 0x58: /* IN E,(C) */ + TSTATE(12); + + if (cpu->pread) + { + cpu->DE.b[LO]=cpu->pread(cpu,cpu->BC.w); + } + else + { + cpu->BC.b[LO]=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->DE.b[LO]]; + SETHIDDEN(cpu->DE.b[LO]); + break; + + case 0x59: /* OUT (C),E */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->DE.b[LO]); + break; + + case 0x5a: /* ADC HL,DE */ + TSTATE(15); + ADC16(cpu->HL.w,cpu->DE.w); + break; + + case 0x5b: /* LD DE,(nnnn) */ + TSTATE(20); + cpu->DE.w=PEEKW(FETCH_WORD); + break; + + case 0x5c: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x5d: /* RETN */ + TSTATE(14); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x5e: /* IM 2 */ + TSTATE(8); + cpu->IM=2; + break; + + case 0x5f: /* LD A,R */ + TSTATE(9); + cpu->AF.b[HI]=cpu->R; + break; + + case 0x60: /* IN H,(C) */ + TSTATE(12); + + if (cpu->pread) + { + cpu->HL.b[HI]=cpu->pread(cpu,cpu->BC.w); + } + else + { + cpu->HL.b[HI]=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->HL.b[HI]]; + SETHIDDEN(cpu->HL.b[HI]); + break; + + case 0x61: /* OUT (C),H */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->HL.b[HI]); + break; + + case 0x62: /* SBC HL,HL */ + TSTATE(15); + SBC16(cpu->HL.w,cpu->HL.w); + break; + + case 0x63: /* LD (nnnn),HL */ + TSTATE(20); + POKEW(FETCH_WORD,cpu->HL.w); + break; + + case 0x64: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x65: /* RETN */ + TSTATE(14); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x66: /* IM 0 */ + TSTATE(8); + cpu->IM=0; + break; + + case 0x67: /* RRD */ + { + Z80Byte b; + + TSTATE(18); + + b=PEEK(cpu->HL.w); + + POKE(cpu->HL.w,(b>>4)|(cpu->AF.b[HI]<<4)); + cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b&0x0f); + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]]; + SETHIDDEN(cpu->AF.b[HI]); + break; + } + + case 0x68: /* IN L,(C) */ + TSTATE(12); + + if (cpu->pread) + { + cpu->HL.b[LO]=cpu->pread(cpu,cpu->BC.w); + } + else + { + cpu->HL.b[LO]=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->HL.b[LO]]; + SETHIDDEN(cpu->HL.b[LO]); + break; + + case 0x69: /* OUT (C),L */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->HL.b[LO]); + break; + + case 0x6a: /* ADC HL,HL */ + TSTATE(15); + ADC16(cpu->HL.w,cpu->HL.w); + break; + + case 0x6b: /* LD HL,(nnnn) */ + TSTATE(20); + cpu->HL.w=PEEKW(FETCH_WORD); + break; + + case 0x6c: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x6d: /* RETN */ + TSTATE(14); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x6e: /* IM 0/1 */ + TSTATE(8); + cpu->IM=0; + break; + + case 0x6f: /* RLD */ + { + Z80Byte b; + + TSTATE(18); + + b=PEEK(cpu->HL.w); + + POKE(cpu->HL.w,(b<<4)|(cpu->AF.b[HI]&0x0f)); + cpu->AF.b[HI]=(cpu->AF.b[HI]&0xf0)|(b>>4); + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]]; + SETHIDDEN(cpu->AF.b[HI]); + break; + } + + case 0x70: /* IN (C) */ + { + Z80Byte b; + + TSTATE(12); + + if (cpu->pread) + { + b=cpu->pread(cpu,cpu->BC.w); + } + else + { + b=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[b]; + SETHIDDEN(b); + break; + } + + case 0x71: /* OUT (C) */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,0); + break; + + case 0x72: /* SBC HL,SP */ + TSTATE(15); + SBC16(cpu->HL.w,cpu->SP); + break; + + case 0x73: /* LD (nnnn),SP */ + TSTATE(20); + POKEW(FETCH_WORD,cpu->SP); + break; + + case 0x74: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x75: /* RETN */ + TSTATE(14); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x76: /* IM 1 */ + TSTATE(8); + cpu->IM=1; + break; + + case 0x77: /* NOP */ + TSTATE(8); + CALLBACK(eZ80_EDHook,opcode); + break; + + case 0x78: /* IN A,(C) */ + TSTATE(12); + + if (cpu->pread) + { + cpu->AF.b[HI]=cpu->pread(cpu,cpu->BC.w); + } + else + { + cpu->AF.b[HI]=0; + } + + cpu->AF.b[LO]=CARRY|PSZtable[cpu->AF.b[HI]]; + SETHIDDEN(cpu->AF.b[HI]); + break; + + case 0x79: /* OUT (C),A */ + TSTATE(12); + if (cpu->pwrite) cpu->pwrite(cpu,cpu->BC.w,cpu->AF.b[HI]); + break; + + case 0x7a: /* ADC HL,SP */ + TSTATE(15); + ADC16(cpu->HL.w,cpu->SP); + break; + + case 0x7b: /* LD SP,(nnnn) */ + TSTATE(20); + cpu->SP=PEEKW(FETCH_WORD); + break; + + case 0x7c: /* NEG */ + { + Z80Byte b; + + TSTATE(8); + + b=cpu->AF.b[HI]; + cpu->AF.b[HI]=0; + SUB8(b); + break; + } + + case 0x7d: /* RETN */ + TSTATE(14); + cpu->IFF1=cpu->IFF2; + POP(cpu->PC); + break; + + case 0x7e: /* IM 2 */ + TSTATE(8); + cpu->IM=2; + break; + + case 0x7f: /* NOP */ + TSTATE(8); + CALLBACK(eZ80_EDHook,opcode); + break; + + case 0xa0: /* LDI */ + TSTATE(16); + LDI; + break; + + case 0xa1: /* CPI */ + TSTATE(16); + CPI; + break; + + case 0xa2: /* INI */ + TSTATE(16); + INI; + break; + + case 0xa3: /* OUTI */ + TSTATE(16); + OUTI; + break; + + case 0xa8: /* LDD */ + TSTATE(16); + LDD; + break; + + case 0xa9: /* CPD */ + TSTATE(16); + CPD; + break; + + case 0xaa: /* IND */ + TSTATE(16); + IND; + break; + + case 0xab: /* OUTD */ + TSTATE(16); + OUTD; + break; + + case 0xb0: /* LDIR */ + TSTATE(16); + LDI; + if (cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + case 0xb1: /* CPIR */ + TSTATE(16); + CPI; + if (cpu->BC.w && !IS_Z) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + case 0xb2: /* INIR */ + TSTATE(16); + INI; + if (cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + case 0xb3: /* OTIR */ + TSTATE(16); + OUTI; + if (cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + case 0xb8: /* LDDR */ + TSTATE(16); + LDD; + if (cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + case 0xb9: /* CPDR */ + TSTATE(16); + CPD; + if (cpu->BC.w && !IS_Z) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + case 0xba: /* INDR */ + TSTATE(16); + IND; + if (cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + case 0xbb: /* OTDR */ + TSTATE(16); + OUTD; + if (cpu->BC.w) + { + TSTATE(5); + cpu->PC-=2; + } + break; + + /* All the rest are NOP/invalid + */ + default: + TSTATE(8); + CALLBACK(eZ80_EDHook,opcode); + break; + } +} + + +/* ---------------------------------------- HANDLERS FOR CB OPCODES +*/ +static void DecodeCB(Z80 *cpu, Z80Byte opcode) +{ + switch(opcode) + { + CB_ALU_BLOCK(0x00,RLC) + CB_ALU_BLOCK(0x08,RRC) + CB_ALU_BLOCK(0x10,RL) + CB_ALU_BLOCK(0x18,RR) + CB_ALU_BLOCK(0x20,SLA) + CB_ALU_BLOCK(0x28,SRA) + CB_ALU_BLOCK(0x30,SLL) + CB_ALU_BLOCK(0x38,SRL) + + CB_BITMANIP_BLOCK(0x40,BIT,0) + CB_BITMANIP_BLOCK(0x48,BIT,1) + CB_BITMANIP_BLOCK(0x50,BIT,2) + CB_BITMANIP_BLOCK(0x58,BIT,3) + CB_BITMANIP_BLOCK(0x60,BIT,4) + CB_BITMANIP_BLOCK(0x68,BIT,5) + CB_BITMANIP_BLOCK(0x70,BIT,6) + CB_BITMANIP_BLOCK(0x78,BIT,7) + + CB_BITMANIP_BLOCK(0x80,BIT_RES,0) + CB_BITMANIP_BLOCK(0x88,BIT_RES,1) + CB_BITMANIP_BLOCK(0x90,BIT_RES,2) + CB_BITMANIP_BLOCK(0x98,BIT_RES,3) + CB_BITMANIP_BLOCK(0xa0,BIT_RES,4) + CB_BITMANIP_BLOCK(0xa8,BIT_RES,5) + CB_BITMANIP_BLOCK(0xb0,BIT_RES,6) + CB_BITMANIP_BLOCK(0xb8,BIT_RES,7) + + CB_BITMANIP_BLOCK(0xc0,BIT_SET,0) + CB_BITMANIP_BLOCK(0xc8,BIT_SET,1) + CB_BITMANIP_BLOCK(0xd0,BIT_SET,2) + CB_BITMANIP_BLOCK(0xd8,BIT_SET,3) + CB_BITMANIP_BLOCK(0xe0,BIT_SET,4) + CB_BITMANIP_BLOCK(0xe8,BIT_SET,5) + CB_BITMANIP_BLOCK(0xf0,BIT_SET,6) + CB_BITMANIP_BLOCK(0xf8,BIT_SET,7) + } +} + + +static void ShiftedDecodeCB(Z80 *cpu, Z80Byte opcode, Z80Relative offset) +{ + Z80Word addr; + + /* See if we've come here from a IX/IY shift. + */ + switch (cpu->shift) + { + case 0xdd: + addr=cpu->IX.w+offset; + break; + case 0xfd: + addr=cpu->IY.w+offset; + break; + default: + addr=cpu->HL.w; /* Play safe... */ + break; + } + + switch(opcode) + { + SHIFTED_CB_ALU_BLOCK(0x00,RLC) + SHIFTED_CB_ALU_BLOCK(0x08,RRC) + SHIFTED_CB_ALU_BLOCK(0x10,RL) + SHIFTED_CB_ALU_BLOCK(0x18,RR) + SHIFTED_CB_ALU_BLOCK(0x20,SLA) + SHIFTED_CB_ALU_BLOCK(0x28,SRA) + SHIFTED_CB_ALU_BLOCK(0x30,SLL) + SHIFTED_CB_ALU_BLOCK(0x38,SRL) + + SHIFTED_CB_BITMANIP_BLOCK(0x40,BIT,0) + SHIFTED_CB_BITMANIP_BLOCK(0x48,BIT,1) + SHIFTED_CB_BITMANIP_BLOCK(0x50,BIT,2) + SHIFTED_CB_BITMANIP_BLOCK(0x58,BIT,3) + SHIFTED_CB_BITMANIP_BLOCK(0x60,BIT,4) + SHIFTED_CB_BITMANIP_BLOCK(0x68,BIT,5) + SHIFTED_CB_BITMANIP_BLOCK(0x70,BIT,6) + SHIFTED_CB_BITMANIP_BLOCK(0x78,BIT,7) + + SHIFTED_CB_BITMANIP_BLOCK(0x80,BIT_RES,0) + SHIFTED_CB_BITMANIP_BLOCK(0x88,BIT_RES,1) + SHIFTED_CB_BITMANIP_BLOCK(0x90,BIT_RES,2) + SHIFTED_CB_BITMANIP_BLOCK(0x98,BIT_RES,3) + SHIFTED_CB_BITMANIP_BLOCK(0xa0,BIT_RES,4) + SHIFTED_CB_BITMANIP_BLOCK(0xa8,BIT_RES,5) + SHIFTED_CB_BITMANIP_BLOCK(0xb0,BIT_RES,6) + SHIFTED_CB_BITMANIP_BLOCK(0xb8,BIT_RES,7) + + SHIFTED_CB_BITMANIP_BLOCK(0xc0,BIT_SET,0) + SHIFTED_CB_BITMANIP_BLOCK(0xc8,BIT_SET,1) + SHIFTED_CB_BITMANIP_BLOCK(0xd0,BIT_SET,2) + SHIFTED_CB_BITMANIP_BLOCK(0xd8,BIT_SET,3) + SHIFTED_CB_BITMANIP_BLOCK(0xe0,BIT_SET,4) + SHIFTED_CB_BITMANIP_BLOCK(0xe8,BIT_SET,5) + SHIFTED_CB_BITMANIP_BLOCK(0xf0,BIT_SET,6) + SHIFTED_CB_BITMANIP_BLOCK(0xf8,BIT_SET,7) + } +} + + +/* ---------------------------------------- NORMAL OPCODE DECODER +*/ +void Z80_Decode(Z80 *cpu, Z80Byte opcode) +{ + Z80Word *HL; + Z80Byte *H; + Z80Byte *L; + Z80Relative off; + + /* See if we've come here from a IX/IY shift + */ + switch (cpu->shift) + { + case 0xdd: + HL=&(cpu->IX.w); + L=cpu->IX.b+LO; + H=cpu->IX.b+HI; + break; + case 0xfd: + HL=&(cpu->IY.w); + L=cpu->IY.b+LO; + H=cpu->IY.b+HI; + break; + default: + HL=&(cpu->HL.w); + L=cpu->HL.b+LO; + H=cpu->HL.b+HI; + break; + } + + switch(opcode) + { + case 0x00: /* NOP */ + TSTATE(4); + break; + + case 0x01: /* LD BC,nnnn */ + TSTATE(10); + cpu->BC.w=FETCH_WORD; + break; + + case 0x02: /* LD (BC),A */ + TSTATE(7); + POKE(cpu->BC.w,cpu->AF.b[HI]); + break; + + case 0x03: /* INC BC */ + TSTATE(6); + cpu->BC.w++; + break; + + case 0x04: /* INC B */ + TSTATE(4); + INC8(cpu->BC.b[HI]); + break; + + case 0x05: /* DEC B */ + TSTATE(4); + DEC8(cpu->BC.b[HI]); + break; + + case 0x06: /* LD B,n */ + TSTATE(7); + cpu->BC.b[HI]=FETCH_BYTE; + break; + + case 0x07: /* RLCA */ + TSTATE(4); + RLCA; + break; + + case 0x08: /* EX AF,AF' */ + TSTATE(4); + SWAP(cpu->AF.w,cpu->AF_); + break; + + case 0x09: /* ADD HL,BC */ + TSTATE(11); + ADD16(*HL,cpu->BC.w); + break; + + case 0x0a: /* LD A,(BC) */ + TSTATE(7); + cpu->AF.b[HI]=PEEK(cpu->BC.w); + break; + + case 0x0b: /* DEC BC */ + TSTATE(6); + cpu->BC.w--; + break; + + case 0x0c: /* INC C */ + TSTATE(4); + INC8(cpu->BC.b[LO]); + break; + + case 0x0d: /* DEC C */ + TSTATE(4); + DEC8(cpu->BC.b[LO]); + break; + + case 0x0e: /* LD C,n */ + TSTATE(7); + cpu->BC.b[LO]=FETCH_BYTE; + break; + + case 0x0f: /* RRCA */ + TSTATE(4); + RRCA; + break; + + case 0x10: /* DJNZ */ + if (--(cpu->BC.b[HI])) + { + TSTATE(13); + JR; + } + else + { + TSTATE(8); + NOJR; + } + break; + + case 0x11: /* LD DE,nnnn */ + TSTATE(10); + cpu->DE.w=FETCH_WORD; + break; + + case 0x12: /* LD (DE),A */ + TSTATE(7); + POKE(cpu->DE.w,cpu->AF.b[HI]); + break; + + case 0x13: /* INC DE */ + TSTATE(6); + cpu->DE.w++; + break; + + case 0x14: /* INC D */ + TSTATE(4); + INC8(cpu->DE.b[HI]); + break; + + case 0x15: /* DEC D */ + TSTATE(4); + DEC8(cpu->DE.b[HI]); + break; + + case 0x16: /* LD D,n */ + TSTATE(7); + cpu->DE.b[HI]=FETCH_BYTE; + break; + + case 0x17: /* RLA */ + TSTATE(4); + RLA; + break; + + case 0x18: /* JR d */ + TSTATE(12); + JR; + break; + + case 0x19: /* ADD HL,DE */ + TSTATE(11); + ADD16(*HL,cpu->DE.w); + break; + + case 0x1a: /* LD A,(DE) */ + TSTATE(7); + cpu->AF.b[HI]=PEEK(cpu->DE.w); + break; + + case 0x1b: /* DEC DE */ + TSTATE(6); + cpu->DE.w--; + break; + + case 0x1c: /* INC E */ + TSTATE(4); + INC8(cpu->DE.b[LO]); + break; + + case 0x1d: /* DEC E */ + TSTATE(4); + DEC8(cpu->DE.b[LO]); + break; + + case 0x1e: /* LD E,n */ + TSTATE(7); + cpu->DE.b[LO]=FETCH_BYTE; + break; + + case 0x1f: /* RRA */ + TSTATE(4); + RRA; + break; + + case 0x20: /* JR NZ,e */ + JR_COND(!IS_Z); + break; + + case 0x21: /* LD HL,nnnn */ + TSTATE(10); + *HL=FETCH_WORD; + break; + + case 0x22: /* LD (nnnn),HL */ + TSTATE(16); + POKEW(FETCH_WORD,*HL); + break; + + case 0x23: /* INC HL */ + TSTATE(6); + (*HL)++; + break; + + case 0x24: /* INC H */ + TSTATE(4); + INC8(*H); + break; + + case 0x25: /* DEC H */ + TSTATE(4); + DEC8(*H); + break; + + case 0x26: /* LD H,n */ + TSTATE(7); + *H=FETCH_BYTE; + break; + + case 0x27: /* DAA */ + TSTATE(4); + DAA(cpu); + break; + + case 0x28: /* JR Z,d */ + JR_COND(IS_Z); + break; + + case 0x29: /* ADD HL,HL */ + TSTATE(11); + ADD16(*HL,*HL); + break; + + case 0x2a: /* LD HL,(nnnn) */ + TSTATE(7); + *HL=PEEKW(FETCH_WORD); + break; + + case 0x2b: /* DEC HL */ + TSTATE(6); + (*HL)--; + break; + + case 0x2c: /* INC L */ + TSTATE(4); + INC8(*L); + break; + + case 0x2d: /* DEC L */ + TSTATE(4); + DEC8(*L); + break; + + case 0x2e: /* LD L,n */ + TSTATE(7); + *L=FETCH_BYTE; + break; + + case 0x2f: /* CPL */ + TSTATE(4); + cpu->AF.b[HI]^=0xff; + SETFLAG(H_Z80); + SETFLAG(N_Z80); + SETHIDDEN(cpu->AF.b[HI]); + break; + + case 0x30: /* JR NC,d */ + JR_COND(!IS_C); + break; + + case 0x31: /* LD SP,nnnn */ + TSTATE(10); + cpu->SP=FETCH_WORD; + break; + + case 0x32: /* LD (nnnn),A */ + TSTATE(13); + POKE(FETCH_WORD,cpu->AF.b[HI]); + break; + + case 0x33: /* INC SP */ + TSTATE(6); + cpu->SP++; + break; + + case 0x34: /* INC (HL) */ + TSTATE(11); + OFFSET(off); + OP_ON_MEM(INC8,*HL+off); + break; + + case 0x35: /* DEC (HL) */ + TSTATE(11); + OFFSET(off); + OP_ON_MEM(DEC8,*HL+off); + break; + + case 0x36: /* LD (HL),n */ + TSTATE(10); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,FETCH_BYTE); + break; + + case 0x37: /* SCF */ + TSTATE(4); + cpu->AF.b[LO]=(cpu->AF.b[LO]&(S_Z80|Z_Z80|P_Z80)) + | C_Z80 + | (cpu->AF.b[HI]&(B3_Z80|B5_Z80)); + break; + + case 0x38: /* JR C,d */ + JR_COND(IS_C); + break; + + case 0x39: /* ADD HL,SP */ + TSTATE(11); + ADD16(*HL,cpu->SP); + break; + + case 0x3a: /* LD A,(nnnn) */ + TSTATE(13); + cpu->AF.b[HI]=cpu->mread(cpu,FETCH_WORD); + break; + + case 0x3b: /* DEC SP */ + TSTATE(6); + cpu->SP--; + break; + + case 0x3c: /* INC A */ + TSTATE(4); + INC8(cpu->AF.b[HI]); + break; + + case 0x3d: /* DEC A */ + TSTATE(4); + DEC8(cpu->AF.b[HI]); + break; + + case 0x3e: /* LD A,n */ + TSTATE(7); + cpu->AF.b[HI]=FETCH_BYTE; + break; + + case 0x3f: /* CCF */ + TSTATE(4); + + if (CARRY) + SETFLAG(H_Z80); + else + CLRFLAG(H_Z80); + + cpu->AF.b[LO]^=C_Z80; + SETHIDDEN(cpu->AF.b[HI]); + break; + + LD_BLOCK(0x40,cpu->BC.b[HI],cpu->BC.b[HI]) + LD_BLOCK(0x48,cpu->BC.b[LO],cpu->BC.b[LO]) + LD_BLOCK(0x50,cpu->DE.b[HI],cpu->DE.b[HI]) + LD_BLOCK(0x58,cpu->DE.b[LO],cpu->DE.b[LO]) + LD_BLOCK(0x60,*H,cpu->HL.b[HI]) + LD_BLOCK(0x68,*L,cpu->HL.b[LO]) + + case 0x70: /* LD (HL),B */ + TSTATE(7); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,cpu->BC.b[HI]); + break; + + case 0x71: /* LD (HL),C */ + TSTATE(7); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,cpu->BC.b[LO]); + break; + + case 0x72: /* LD (HL),D */ + TSTATE(7); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,cpu->DE.b[HI]); + break; + + case 0x73: /* LD (HL),E */ + TSTATE(7); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,cpu->DE.b[LO]); + break; + + case 0x74: /* LD (HL),H */ + TSTATE(7); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,cpu->HL.b[HI]); + break; + + case 0x75: /* LD (HL),L */ + TSTATE(7); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,cpu->HL.b[LO]); + break; + + case 0x76: /* HALT */ + TSTATE(4); + cpu->PC--; + + if (!cpu->halt) + CALLBACK(eZ80_Halt,1); + + cpu->halt=TRUE; + break; + + case 0x77: /* LD (HL),A */ + TSTATE(7); + OFFSET(off); + cpu->mwrite(cpu,*HL+off,cpu->AF.b[HI]); + break; + + LD_BLOCK(0x78,cpu->AF.b[HI],cpu->AF.b[HI]) + + ALU_BLOCK(0x80,ADD8) + ALU_BLOCK(0x88,ADC8) + ALU_BLOCK(0x90,SUB8) + ALU_BLOCK(0x98,SBC8) + ALU_BLOCK(0xa0,AND) + ALU_BLOCK(0xa8,XOR) + ALU_BLOCK(0xb0,OR) + ALU_BLOCK(0xb8,CMP8) + + case 0xc0: /* RET NZ */ + RET_COND(!IS_Z); + break; + + case 0xc1: /* POP BC */ + TSTATE(10); + POP(cpu->BC.w); + break; + + case 0xc2: /* JP NZ,nnnn */ + JP_COND(!IS_Z); + break; + + case 0xc3: /* JP nnnn */ + JP_COND(1); + break; + + case 0xc4: /* CALL NZ,nnnn */ + CALL_COND(!IS_Z); + break; + + case 0xc5: /* PUSH BC */ + TSTATE(10); + PUSH(cpu->BC.w); + break; + + case 0xc6: /* ADD A,n */ + TSTATE(7); + ADD8(FETCH_BYTE); + break; + + case 0xc7: /* RST 0 */ + RST(0); + break; + + case 0xc8: /* RET Z */ + RET_COND(IS_Z); + break; + + case 0xc9: /* RET */ + TSTATE(10); + POP(cpu->PC); + break; + + case 0xca: /* JP Z,nnnn */ + JP_COND(IS_Z); + break; + + case 0xcb: /* CB PREFIX */ + INC_R; + + /* Check for previous IX/IY shift. + */ + if (cpu->shift!=0) + { + Z80Relative cb_offset; + + TSTATE(4); /* Wild stab in the dark! */ + cb_offset=FETCH_BYTE; + ShiftedDecodeCB(cpu,FETCH_BYTE,cb_offset); + } + else + { + DecodeCB(cpu,FETCH_BYTE); + } + break; + + case 0xcc: /* CALL Z,nnnn */ + CALL_COND(IS_Z); + break; + + case 0xcd: /* CALL nnnn */ + CALL_COND(1); + break; + + case 0xce: /* ADC A,n */ + ADC8(FETCH_BYTE); + break; + + case 0xcf: /* RST 8 */ + RST(8); + break; + + case 0xd0: /* RET NC */ + RET_COND(!IS_C); + break; + + case 0xd1: /* POP DE */ + TSTATE(10); + POP(cpu->DE.w); + break; + + case 0xd2: /* JP NC,nnnn */ + JP_COND(!IS_C); + break; + + case 0xd3: /* OUT (n),A */ + TSTATE(11); + if (cpu->pwrite) + cpu->pwrite(cpu,FETCH_BYTE,cpu->AF.b[HI]); + else + cpu->PC++; + break; + + case 0xd4: /* CALL NC,nnnn */ + CALL_COND(!IS_C); + break; + + case 0xd5: /* PUSH DE */ + TSTATE(11); + PUSH(cpu->DE.w); + break; + + case 0xd6: /* SUB A,n */ + TSTATE(7); + SUB8(FETCH_BYTE); + break; + + case 0xd7: /* RST 10 */ + RST(0x10); + break; + + case 0xd8: /* RET C */ + RET_COND(IS_C); + break; + + case 0xd9: /* EXX */ + TSTATE(4); + SWAP(cpu->BC.w,cpu->BC_); + SWAP(cpu->DE.w,cpu->DE_); + SWAP(cpu->HL.w,cpu->HL_); + break; + + case 0xda: /* JP C,nnnn */ + JP_COND(IS_C); + break; + + case 0xdb: /* IN A,(n) */ + TSTATE(11); + if (cpu->pread) + cpu->AF.b[HI]=cpu->pread(cpu,FETCH_BYTE); + else + cpu->PC++; + break; + + case 0xdc: /* CALL C,nnnn */ + CALL_COND(IS_C); + break; + + case 0xdd: /* DD PREFIX */ + TSTATE(4); + INC_R; + + cpu->shift=opcode; + Z80_Decode(cpu,FETCH_BYTE); + break; + + case 0xde: /* SBC A,n */ + TSTATE(7); + SBC8(FETCH_BYTE); + break; + + case 0xdf: /* RST 18 */ + RST(0x18); + break; + + case 0xe0: /* RET PO */ + RET_COND(!IS_P); + break; + + case 0xe1: /* POP HL */ + TSTATE(10); + POP(*HL); + break; + + case 0xe2: /* JP PO,nnnn */ + JP_COND(!IS_P); + break; + + case 0xe3: /* EX (SP),HL */ + { + Z80Word tmp; + TSTATE(19); + POP(tmp); + PUSH(*HL); + *HL=tmp; + } + break; + + case 0xe4: /* CALL PO,nnnn */ + CALL_COND(!IS_P); + break; + + case 0xe5: /* PUSH HL */ + TSTATE(10); + PUSH(*HL); + break; + + case 0xe6: /* AND A,n */ + TSTATE(7); + AND(FETCH_BYTE); + break; + + case 0xe7: /* RST 20 */ + RST(0x20); + break; + + case 0xe8: /* RET PE */ + RET_COND(IS_P); + break; + + case 0xe9: /* JP (HL) */ + TSTATE(4); + cpu->PC=*HL; + break; + + case 0xea: /* JP PE,nnnn */ + JP_COND(IS_P); + break; + + case 0xeb: /* EX DE,HL */ + TSTATE(4); + SWAP(cpu->DE.w,*HL); + break; + + case 0xec: /* CALL PE,nnnn */ + CALL_COND(IS_P); + break; + + case 0xed: /* ED PREFIX */ + INC_R; + DecodeED(cpu,FETCH_BYTE); + break; + + case 0xee: /* XOR A,n */ + TSTATE(7); + XOR(FETCH_BYTE); + break; + + case 0xef: /* RST 28 */ + RST(0x28); + break; + + case 0xf0: /* RET P */ + RET_COND(!IS_S); + break; + + case 0xf1: /* POP AF */ + TSTATE(10); + POP(cpu->AF.w); + break; + + case 0xf2: /* JP P,nnnn */ + JP_COND(!IS_S); + break; + + case 0xf3: /* DI */ + TSTATE(4); + cpu->IFF1=0; + cpu->IFF2=0; + break; + + case 0xf4: /* CALL P,nnnn */ + CALL_COND(!IS_S); + break; + + case 0xf5: /* PUSH AF */ + TSTATE(10); + PUSH(cpu->AF.w); + break; + + case 0xf6: /* OR A,n */ + TSTATE(7); + OR(FETCH_BYTE); + break; + + case 0xf7: /* RST 30 */ + RST(0x30); + break; + + case 0xf8: /* RET M */ + RET_COND(IS_S); + break; + + case 0xf9: /* LD SP,HL */ + TSTATE(6); + cpu->SP=*HL; + break; + + case 0xfa: /* JP M,nnnn */ + JP_COND(IS_S); + break; + + case 0xfb: /* EI */ + TSTATE(4); + cpu->IFF1=1; + cpu->IFF2=1; + break; + + case 0xfc: /* CALL M,nnnn */ + CALL_COND(IS_S); + break; + + case 0xfd: /* FD PREFIX */ + TSTATE(4); + INC_R; + + cpu->shift=opcode; + Z80_Decode(cpu,FETCH_BYTE); + break; + + case 0xfe: /* CP A,n */ + TSTATE(7); + CMP8(FETCH_BYTE); + break; + + case 0xff: /* RST 38 */ + RST(0x38); + break; + + } +} + + +/* END OF FILE */ diff --git a/src/z80_dis.c b/src/z80_dis.c new file mode 100644 index 0000000..9d42829 --- /dev/null +++ b/src/z80_dis.c @@ -0,0 +1,2476 @@ +/* + + z80 - Z80 Emulator + + Copyright (C) 2006 Ian Cowburn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + +*/ +static const char ident[]="$Id$"; + +#ifdef ENABLE_DISASSEM + +#include +#include +#include + +#include "z80.h" +#include "z80_private.h" + +static Z80Relative cb_off; + +/* ---------------------------------------- SHARED ROUTINES +*/ +static const char *z80_dis_reg8[]={"b","c","d","e","h","l","(hl)","a"}; +static const char *z80_dis_reg16[]={"bc","de","hl","sp"}; +static const char *z80_dis_condition[]={"nz","z","nc","c","po","pe","p","m"}; + +static const char *dis_op; +static const char *dis_arg; + +const char *Z80_Dis_Printf(const char *format, ...) +{ + static int p=0; + static char s[16][80]; + va_list arg; + + va_start(arg,format); + p=(p+1)%16; + vsprintf(s[p],format,arg); + va_end(arg); + + return s[p]; +} + + +Z80Byte Z80_Dis_FetchByte(Z80 *cpu, Z80Word *pc) +{ + return cpu->disread(cpu,(*pc)++); +} + + +Z80Word Z80_Dis_FetchWord(Z80 *cpu, Z80Word *pc) +{ + Z80Byte l,h; + + l=Z80_Dis_FetchByte(cpu,pc); + h=Z80_Dis_FetchByte(cpu,pc); + + return ((Z80Word)h<<8)|l; +} + + +void Z80_Dis_Set(const char *op, const char *arg) +{ + dis_op=op; + dis_arg=arg; +} + + +const char *Z80_Dis_GetOp(void) +{ + return dis_op ? dis_op : ""; +} + + +const char *Z80_Dis_GetArg(void) +{ + return dis_arg ? dis_arg : ""; +} + + +static const char *GetLabel(Z80Word w) +{ + if (z80_labels) + { + int f; + + for(f=0;z80_labels[f].label;f++) + { + if (z80_labels[f].address==w) + { + return z80_labels[f].label; + } + } + } + + return NULL; +} + + + +/* ---------------------------------------- CB xx BYTE OPCODES +*/ +static void DIS_RLC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("rlc",reg); +} + +static void DIS_RRC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("rrc",reg); +} + +static void DIS_RL_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("rl",reg); +} + +static void DIS_RR_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("rr",reg); +} + +static void DIS_SLA_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("sla",reg); +} + +static void DIS_SRA_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("sra",reg); +} + +static void DIS_SLL_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("sll",reg); +} + +static void DIS_SRL_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("srl",reg); +} + +static void DIS_BIT_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + int bit; + + reg=z80_dis_reg8[op%8]; + bit=(op-0x40)/8; + Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s",bit,reg)); +} + +static void DIS_RES_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + int bit; + + reg=z80_dis_reg8[op%8]; + bit=(op-0x80)/8; + Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s",bit,reg)); +} + +static void DIS_SET_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + int bit; + + reg=z80_dis_reg8[op%8]; + bit=(op-0xc0)/8; + Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s",bit,reg)); +} + +/* ---------------------------------------- DD OPCODES +*/ + +static const char *IX_RelStr(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + static char s[80]; + Z80Relative r; + + r=(Z80Relative)Z80_Dis_FetchByte(z80,pc); + + if (r<0) + sprintf(s,"(ix-$%.2x)",-r); + else + sprintf(s,"(ix+$%.2x)",r); + + return(s); +} + + +static const char *IX_RelStrCB(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + static char s[80]; + Z80Relative r; + + r=(Z80Relative)cb_off; + + if (r<0) + sprintf(s,"(ix-$%.2x)",-r); + else + sprintf(s,"(ix+$%.2x)",r); + + return(s); +} + + +static const char *XR8(Z80 *z80, int reg, Z80Word *pc) +{ + switch(reg) + { + case 0: + return("b"); + break; + case 1: + return("c"); + break; + case 2: + return("d"); + break; + case 3: + return("e"); + break; + case 4: + return("ixh"); + break; + case 5: + return("ixl"); + break; + case 6: + return(IX_RelStr(z80,0,pc)); + break; + case 7: + return("a"); + break; + default: + return(Z80_Dis_Printf("BUG %d",reg)); + break; + } +} + +static void DIS_DD_NOP(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + dis_opcode_z80[op](z80,op,pc); +} + +static void DIS_ADD_IX_BC(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","ix,bc"); +} + +static void DIS_ADD_IX_DE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","ix,de"); +} + +static void DIS_LD_IX_WORD(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld",Z80_Dis_Printf("ix,$%.4x",Z80_Dis_FetchWord(z80,pc))); +} + +static void DIS_LD_ADDR_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),ix",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),ix",w)); +} + +static void DIS_INC_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc","ix"); +} + +static void DIS_INC_IXH(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc","ixh"); +} + +static void DIS_DEC_IXH(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec","ixh"); +} + +static void DIS_LD_IXH_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld",Z80_Dis_Printf("ixh,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_ADD_IX_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","ix,ix"); +} + +static void DIS_LD_IX_ADDR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("ix,(%s)",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("ix,($%.4x)",w)); +} + +static void DIS_DEC_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec","ix"); +} + +static void DIS_INC_IXL(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc","ixl"); +} + +static void DIS_DEC_IXL(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec","ixl"); +} + +static void DIS_LD_IXL_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld",Z80_Dis_Printf("ixl,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_INC_IIX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc",Z80_Dis_Printf("%s",IX_RelStr(z80,op,pc))); +} + +static void DIS_DEC_IIX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec",Z80_Dis_Printf("%s",IX_RelStr(z80,op,pc))); +} + +static void DIS_LD_IIX_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *rel; + int b; + + rel=IX_RelStr(z80,op,pc); + b=Z80_Dis_FetchByte(z80,pc); + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.2x",rel,b)); +} + + +static void DIS_ADD_IX_SP(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","ix,sp"); +} + +static void DIS_XLD_R8_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int src_r,dest_r; + const char *src,*dest; + + dest_r=(op-0x40)/8; + src_r=op%8; + + /* IX can't be used as source and destination when reading z80ory + */ + if (dest_r==6) + { + dest=XR8(z80,dest_r,pc); + src=z80_dis_reg8[src_r]; + } + else if (((dest_r==4)||(dest_r==5))&&(src_r==6)) + { + dest=z80_dis_reg8[dest_r]; + src=XR8(z80,src_r,pc); + } + else + { + dest=XR8(z80,dest_r,pc); + src=XR8(z80,src_r,pc); + } + + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src)); +} + +static void DIS_XADD_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc))); +} + +static void DIS_XADC_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("adc",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc))); +} + +static void DIS_XSUB_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("sub",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc))); +} + +static void DIS_XSBC_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("sbc",Z80_Dis_Printf("a,%s",XR8(z80,(op%8),pc))); +} + +static void DIS_XAND_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("and",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc))); +} + +static void DIS_XXOR_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("xor",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc))); +} + +static void DIS_X_OR_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("or",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc))); +} + +static void DIS_XCP_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cp",Z80_Dis_Printf("%s",XR8(z80,(op%8),pc))); +} + +static void DIS_POP_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("pop","ix"); +} + +static void DIS_EX_ISP_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ex","(sp),ix"); +} + +static void DIS_PUSH_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("push","ix"); +} + +static void DIS_JP_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("jp","(ix)"); +} + +static void DIS_LD_SP_IX(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld","sp,ix"); +} + +static void DIS_DD_CB_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + cb_off=(Z80Relative)Z80_Dis_FetchByte(z80,pc); + nop=Z80_Dis_FetchByte(z80,pc); + dis_DD_CB_opcode[nop](z80,nop,pc); +} + +static void DIS_DD_DD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_DD_opcode[nop](z80,nop,pc); +} + +static void DIS_DD_ED_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_ED_opcode[nop](z80,nop,pc); +} + +static void DIS_DD_FD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_FD_opcode[nop](z80,nop,pc); +} + + +/* ---------------------------------------- DD CB OPCODES +*/ + +static void DIS_RLC_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rlc",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + { + Z80_Dis_Set("rlc",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); + } +} + +static void DIS_RRC_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rrc",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("rrc",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_RL_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rl",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("rl",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_RR_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rr",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("rr",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SLA_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("sla",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("sla",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SRA_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("sra",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("sra",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SRL_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("srl",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("srl",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SLL_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("sll",Z80_Dis_Printf("%s",IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("sll",Z80_Dis_Printf("%s[%s]",IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_BIT_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + int bit; + + reg=(op%8); + bit=(op-0x40)/8; + + if (reg==6) + Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s",bit,IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s[%s]",bit,IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_RES_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + int bit; + + reg=(op%8); + bit=(op-0x80)/8; + + if (reg==6) + Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s",bit,IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s[%s]",bit,IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SET_IX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + int bit; + + reg=(op%8); + bit=(op-0xc0)/8; + + if (reg==6) + Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s",bit,IX_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s[%s]",bit,IX_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + + +/* ---------------------------------------- ED OPCODES +*/ + +static const char *ER8(int reg) +{ + switch(reg) + { + case 0: + return("b"); + break; + case 1: + return("c"); + break; + case 2: + return("d"); + break; + case 3: + return("e"); + break; + case 4: + return("h"); + break; + case 5: + return("l"); + break; + case 6: + return("0"); + break; + case 7: + return("a"); + break; + } + + return "?"; +} + +/* Assumes illegal ED ops are being used for break points +*/ +static void DIS_ED_NOP(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("brk",Z80_Dis_Printf("$%.2x",op)); +} + +static void DIS_IN_R8_C(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("in",Z80_Dis_Printf("%s,(c)",ER8((op-0x40)/8))); +} + +static void DIS_OUT_C_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("out",Z80_Dis_Printf("(c),%s",ER8((op-0x40)/8))); +} + +static void DIS_SBC_HL_R16(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("sbc",Z80_Dis_Printf("hl,%s",z80_dis_reg16[(op-0x40)/16])); +} + +static void DIS_ED_LD_ADDR_R16(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),%s",p,z80_dis_reg16[(op-0x40)/16])); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),%s",w,z80_dis_reg16[(op-0x40)/16])); +} + +static void DIS_NEG(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("neg",NULL); +} + +static void DIS_RETN(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("retn",NULL); +} + +static void DIS_IM_0(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("im","0"); +} + +static void DIS_LD_I_A(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld","i,a"); +} + +static void DIS_ADC_HL_R16(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("adc",Z80_Dis_Printf("hl,%s",z80_dis_reg16[(op-0x40)/16])); +} + +static void DIS_ED_LD_R16_ADDR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,(%s)",z80_dis_reg16[(op-0x40)/16],p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,($%.4x)",z80_dis_reg16[(op-0x40)/16],w)); +} + +static void DIS_RETI(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("reti",NULL); +} + +static void DIS_LD_R_A(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld","r,a"); +} + +static void DIS_IM_1(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("im","1"); +} + +static void DIS_LD_A_I(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld","a,i"); +} + +static void DIS_IM_2(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("im","2"); +} + +static void DIS_LD_A_R(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld","a,r"); +} + +static void DIS_RRD(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("rrd",NULL); +} + +static void DIS_RLD(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("rld",NULL); +} + +static void DIS_LDI(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ldi",NULL); +} + +static void DIS_CPI(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cpi",NULL); +} + +static void DIS_INI(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ini",NULL); +} + +static void DIS_OUTI(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("outi",NULL); +} + +static void DIS_LDD(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ldd",NULL); +} + +static void DIS_CPD(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cpd",NULL); +} + +static void DIS_IND(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ind",NULL); +} + +static void DIS_OUTD(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("outd",NULL); +} + +static void DIS_LDIR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ldir",NULL); +} + +static void DIS_CPIR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cpir",NULL); +} + +static void DIS_INIR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inir",NULL); +} + +static void DIS_OTIR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("otir",NULL); +} + +static void DIS_LDDR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("lddr",NULL); +} + +static void DIS_CPDR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cpdr",NULL); +} + +static void DIS_INDR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("indr",NULL); +} + +static void DIS_OTDR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("otdr",NULL); +} + + +/* ---------------------------------------- FD OPCODES +*/ + +static const char *IY_RelStr(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + static char s[80]; + Z80Relative r; + + r=(Z80Relative)Z80_Dis_FetchByte(z80,pc); + + if (r<0) + sprintf(s,"(iy-$%.2x)",-r); + else + sprintf(s,"(iy+$%.2x)",r); + + return(s); +} + + +static const char *IY_RelStrCB(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + static char s[80]; + Z80Relative r; + + r=(Z80Relative)cb_off; + + if (r<0) + sprintf(s,"(iy-$%.2x)",-r); + else + sprintf(s,"(iy+$%.2x)",r); + + return(s); +} + + +static const char *YR8(Z80 *z80, int reg, Z80Word *pc) +{ + switch(reg) + { + case 0: + return("b"); + break; + case 1: + return("c"); + break; + case 2: + return("d"); + break; + case 3: + return("e"); + break; + case 4: + return("iyh"); + break; + case 5: + return("iyl"); + break; + case 6: + return(IY_RelStr(z80,0,pc)); + break; + case 7: + return("a"); + break; + default: + return(Z80_Dis_Printf("BUG %d",reg)); + break; + } +} + +static void DIS_FD_NOP(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + dis_opcode_z80[op](z80,op,pc); +} + +static void DIS_ADD_IY_BC(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","iy,bc"); +} + +static void DIS_ADD_IY_DE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","iy,de"); +} + +static void DIS_LD_IY_WORD(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld",Z80_Dis_Printf("iy,$%.4x",Z80_Dis_FetchWord(z80,pc))); +} + +static void DIS_LD_ADDR_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),iy",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),iy",w)); +} + +static void DIS_INC_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc","iy"); +} + +static void DIS_INC_IYH(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc","iyh"); +} + +static void DIS_DEC_IYH(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec","iyh"); +} + +static void DIS_LD_IYH_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld",Z80_Dis_Printf("iyh,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_ADD_IY_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","iy,iy"); +} + +static void DIS_LD_IY_ADDR(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("iy,(%s)",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("iy,($%.4x)",w)); +} + +static void DIS_DEC_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec","iy"); +} + +static void DIS_INC_IYL(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc","iyl"); +} + +static void DIS_DEC_IYL(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec","iyl"); +} + +static void DIS_LD_IYL_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld",Z80_Dis_Printf("iyl,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_INC_IIY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("inc",Z80_Dis_Printf("%s",IY_RelStr(z80,op,pc))); +} + +static void DIS_DEC_IIY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("dec",Z80_Dis_Printf("%s",IY_RelStr(z80,op,pc))); +} + +static void DIS_LD_IIY_BYTE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *rel; + int b; + + rel=IY_RelStr(z80,op,pc); + b=Z80_Dis_FetchByte(z80,pc); + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.2x",rel,b)); +} + + +static void DIS_ADD_IY_SP(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add","iy,sp"); +} + +static void DIS_YLD_R8_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int src_r,dest_r; + const char *src,*dest; + + dest_r=(op-0x40)/8; + src_r=op%8; + + /* IY can't be used as source and destination when reading z80ory + */ + if (dest_r==6) + { + dest=YR8(z80,dest_r,pc); + src=z80_dis_reg8[src_r]; + } + else if (((dest_r==4)||(dest_r==5))&&(src_r==6)) + { + dest=z80_dis_reg8[dest_r]; + src=YR8(z80,src_r,pc); + } + else + { + dest=YR8(z80,dest_r,pc); + src=YR8(z80,src_r,pc); + } + + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src)); +} + +static void DIS_YADD_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc))); +} + +static void DIS_YADC_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("adc",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc))); +} + +static void DIS_YSUB_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("sub",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc))); +} + +static void DIS_YSBC_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("sbc",Z80_Dis_Printf("a,%s",YR8(z80,(op%8),pc))); +} + +static void DIS_YAND_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("and",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc))); +} + +static void DIS_YYOR_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("xor",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc))); +} + +static void DIS_Y_OR_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("or",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc))); +} + +static void DIS_YCP_R8(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cp",Z80_Dis_Printf("%s",YR8(z80,(op%8),pc))); +} + +static void DIS_POP_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("pop","iy"); +} + +static void DIS_EY_ISP_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ex","(sp),iy"); +} + +static void DIS_PUSH_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("push","iy"); +} + +static void DIS_JP_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("jp","(iy)"); +} + +static void DIS_LD_SP_IY(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld","sp,iy"); +} + +static void DIS_FD_CB_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + cb_off=(Z80Relative)Z80_Dis_FetchByte(z80,pc); + nop=Z80_Dis_FetchByte(z80,pc); + dis_FD_CB_opcode[nop](z80,nop,pc); +} + +static void DIS_FD_DD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_DD_opcode[nop](z80,nop,pc); +} + +static void DIS_FD_ED_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_ED_opcode[nop](z80,nop,pc); +} + +static void DIS_FD_FD_DECODE(Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_FD_opcode[nop](z80,nop,pc); +} + + +/* ---------------------------------------- FD CB OPCODES +*/ + +static void DIS_RLC_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rlc",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("rlc",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_RRC_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rrc",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("rrc",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_RL_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rl",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("rl",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_RR_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("rr",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("rr",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SLA_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("sla",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("sla",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SRA_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("sra",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("sra",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SRL_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("srl",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("srl",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SLL_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + + reg=(op%8); + + if (reg==6) + Z80_Dis_Set("sll",Z80_Dis_Printf("%s",IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("sll",Z80_Dis_Printf("%s[%s]",IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_BIT_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + int bit; + + reg=(op%8); + bit=(op-0x40)/8; + + if (reg==6) + Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s",bit,IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("bit",Z80_Dis_Printf("%d,%s[%s]",bit,IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_RES_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + int bit; + + reg=(op%8); + bit=(op-0x80)/8; + + if (reg==6) + Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s",bit,IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("res",Z80_Dis_Printf("%d,%s[%s]",bit,IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + +static void DIS_SET_IY (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int reg; + int bit; + + reg=(op%8); + bit=(op-0xc0)/8; + + if (reg==6) + Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s",bit,IY_RelStrCB(z80,op,pc))); + else + Z80_Dis_Set("set",Z80_Dis_Printf("%d,%s[%s]",bit,IY_RelStrCB(z80,op,pc),z80_dis_reg8[reg])); +} + + +/* ---------------------------------------- SINGLE BYTE OPCODES +*/ +static void DIS_NOP (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("nop",NULL); +} + +static void DIS_LD_R16_WORD (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op&0x30)/0x10]; + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.4x",reg,Z80_Dis_FetchWord(z80,pc))); +} + +static void DIS_LD_R16_A (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op&0x30)/0x10]; + Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),a",reg)); +} + +static void DIS_INC_R16 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op&0x30)/0x10]; + Z80_Dis_Set("inc",reg); +} + +static void DIS_INC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[(op&0x38)/0x8]; + Z80_Dis_Set("inc",reg); +} + +static void DIS_DEC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[(op&0x38)/0x8]; + Z80_Dis_Set("dec",reg); +} + +static void DIS_LD_R8_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[(op&0x38)/0x8]; + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,$%.2x",reg,Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_RLCA (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("rlca",NULL); +} + +static void DIS_EX_AF_AF (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ex","af,af'"); +} + +static void DIS_ADD_HL_R16 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op&0x30)/0x10]; + Z80_Dis_Set("add",Z80_Dis_Printf("hl,%s",reg)); +} + +static void DIS_LD_A_R16 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op&0x30)/0x10]; + Z80_Dis_Set("ld",Z80_Dis_Printf("a,(%s)",reg)); +} + +static void DIS_DEC_R16 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op&0x30)/0x10]; + Z80_Dis_Set("dec",reg); +} + +static void DIS_RRCA (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("rrca",NULL); +} + +static void DIS_DJNZ (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word new; + + new=*pc+(Z80Relative)z80->disread(z80,*pc)+1; + (*pc)++; + Z80_Dis_Set("djnz",Z80_Dis_Printf("$%.4x",new)); +} + +static void DIS_RLA (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("rla",NULL); +} + +static void DIS_JR (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word new; + const char *p; + + new=*pc+(Z80Relative)z80->disread(z80,*pc)+1; + (*pc)++; + + if ((p=GetLabel(new))) + Z80_Dis_Set("jr",Z80_Dis_Printf("%s",p)); + else + Z80_Dis_Set("jr",Z80_Dis_Printf("$%.4x",new)); +} + +static void DIS_RRA (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("rra",NULL); +} + +static void DIS_JR_CO (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *con; + Z80Word new; + const char *p; + + con=z80_dis_condition[(op-0x20)/8]; + new=*pc+(Z80Relative)z80->disread(z80,*pc)+1; + (*pc)++; + + if ((p=GetLabel(new))) + Z80_Dis_Set("jr",Z80_Dis_Printf("%s,%s",con,p)); + else + Z80_Dis_Set("jr",Z80_Dis_Printf("%s,$%.4x",con,new)); +} + +static void DIS_LD_ADDR_HL (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),hl",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),hl",w)); +} + +static void DIS_DAA (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("daa",NULL); +} + +static void DIS_LD_HL_ADDR (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("hl,(%s)",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("hl,($%.4x)",w)); +} + +static void DIS_CPL (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cpl",NULL); +} + +static void DIS_LD_ADDR_A (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("(%s),a",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("($%.4x),a",w)); +} + +static void DIS_SCF (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("scf",NULL); +} + +static void DIS_LD_A_ADDR (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("ld",Z80_Dis_Printf("a,(%s)",p)); + else + Z80_Dis_Set("ld",Z80_Dis_Printf("a,($%.4x)",w)); +} + +static void DIS_CCF (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ccf",NULL); +} + +static void DIS_LD_R8_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *src,*dest; + + dest=z80_dis_reg8[(op-0x40)/8]; + src=z80_dis_reg8[op%8]; + Z80_Dis_Set("ld",Z80_Dis_Printf("%s,%s",dest,src)); +} + +static void DIS_HALT (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("halt",NULL); +} + +static void DIS_ADD_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("add",Z80_Dis_Printf("a,%s",reg)); +} + +static void DIS_ADC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("adc",Z80_Dis_Printf("a,%s",reg)); +} + +static void DIS_SUB_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("sub",Z80_Dis_Printf("a,%s",reg)); +} + +static void DIS_SBC_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("sbc",Z80_Dis_Printf("a,%s",reg)); +} + +static void DIS_AND_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("and",Z80_Dis_Printf("%s",reg)); +} + +static void DIS_XOR_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("xor",Z80_Dis_Printf("%s",reg)); +} + +static void DIS_OR_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("or",Z80_Dis_Printf("%s",reg)); +} + +static void DIS_CP_R8 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg8[op%8]; + Z80_Dis_Set("cp",Z80_Dis_Printf("%s",reg)); +} + + +static void DIS_RET_CO (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *con; + + con=z80_dis_condition[(op-0xc0)/8]; + Z80_Dis_Set("ret",con); +} + +static void DIS_POP_R16 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op-0xc0)/16]; + + if (!strcmp(reg,"sp")) + reg="af"; + + Z80_Dis_Set("pop",reg); +} + +static void DIS_JP (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("jp",Z80_Dis_Printf("%s",p)); + else + Z80_Dis_Set("jp",Z80_Dis_Printf("$%.4x",w)); +} + +static void DIS_PUSH_R16 (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *reg; + + reg=z80_dis_reg16[(op-0xc0)/16]; + + if (!strcmp(reg,"sp")) + reg="af"; + + Z80_Dis_Set("push",reg); +} + +static void DIS_ADD_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("add",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_RST (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int add; + + add=(op&0x3f)-7; + Z80_Dis_Set("rst",Z80_Dis_Printf("%.2xh",add)); +} + +static void DIS_RET (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ret",NULL); +} + +static void DIS_JP_CO (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *con; + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + con=z80_dis_condition[(op-0xc0)/8]; + + if ((p=GetLabel(w))) + Z80_Dis_Set("jp",Z80_Dis_Printf("%s,%s",con,p)); + else + Z80_Dis_Set("jp",Z80_Dis_Printf("%s,$%.4x",con,w)); +} + +static void DIS_CB_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_CB_opcode[nop](z80,nop,pc); +} + +static void DIS_CALL_CO (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + const char *con; + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + con=z80_dis_condition[(op-0xc0)/8]; + + if ((p=GetLabel(w))) + Z80_Dis_Set("call",Z80_Dis_Printf("%s,%s",con,p)); + else + Z80_Dis_Set("call",Z80_Dis_Printf("%s,$%.4x",con,w)); +} + +static void DIS_CALL (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80Word w; + const char *p; + + w=Z80_Dis_FetchWord(z80,pc); + + if ((p=GetLabel(w))) + Z80_Dis_Set("call",Z80_Dis_Printf("%s",p)); + else + Z80_Dis_Set("call",Z80_Dis_Printf("$%.4x",w)); +} + +static void DIS_ADC_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("adc",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_OUT_BYTE_A (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("out",Z80_Dis_Printf("($%.2x),a",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_SUB_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("sub",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_EXX (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("exx",NULL); +} + +static void DIS_IN_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("in",Z80_Dis_Printf("a,($%.2x)",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_DD_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_DD_opcode[nop](z80,nop,pc); +} + +static void DIS_SBC_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("sbc",Z80_Dis_Printf("a,$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + + +static void DIS_EX_ISP_HL (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ex","(sp),hl"); +} + +static void DIS_AND_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("and",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_JP_HL (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("jp","(hl)"); +} + +static void DIS_EX_DE_HL (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ex","de,hl"); +} + +static void DIS_ED_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_ED_opcode[nop](z80,nop,pc); +} + +static void DIS_XOR_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("xor",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_DI (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("di",NULL); +} + +static void DIS_OR_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("or",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + +static void DIS_LD_SP_HL (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ld","sp,hl"); +} + +static void DIS_EI (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("ei",NULL); +} + +static void DIS_FD_DECODE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + int nop; + + nop=Z80_Dis_FetchByte(z80,pc); + dis_FD_opcode[nop](z80,nop,pc); +} + +static void DIS_CP_A_BYTE (Z80 *z80, Z80Byte op, Z80Word *pc) +{ + Z80_Dis_Set("cp",Z80_Dis_Printf("$%.2x",Z80_Dis_FetchByte(z80,pc))); +} + + +/* ---------------------------------------- TABLES +*/ + +/* CB opcodes +*/ +DIS_OP_CALLBACK dis_CB_opcode[0x100]= + { +/* 0x00 - 0x03 */ DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, +/* 0x04 - 0x07 */ DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, DIS_RLC_R8, +/* 0x08 - 0x0b */ DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, +/* 0x0c - 0x0f */ DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, DIS_RRC_R8, + +/* 0x10 - 0x13 */ DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, +/* 0x14 - 0x17 */ DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, DIS_RL_R8, +/* 0x18 - 0x1b */ DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, +/* 0x1c - 0x1f */ DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, DIS_RR_R8, + +/* 0x20 - 0x23 */ DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, +/* 0x24 - 0x27 */ DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, DIS_SLA_R8, +/* 0x28 - 0x2b */ DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, +/* 0x2c - 0x2f */ DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, DIS_SRA_R8, + +/* 0x30 - 0x33 */ DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, +/* 0x34 - 0x37 */ DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, DIS_SLL_R8, +/* 0x38 - 0x3b */ DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, +/* 0x3c - 0x3f */ DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, DIS_SRL_R8, + +/* 0x40 - 0x43 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x44 - 0x47 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x48 - 0x4b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x4c - 0x4f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + +/* 0x50 - 0x53 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x54 - 0x57 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x58 - 0x5b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x5c - 0x5f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + +/* 0x60 - 0x63 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x64 - 0x67 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x68 - 0x6b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x6c - 0x6f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + +/* 0x70 - 0x73 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x74 - 0x77 */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x78 - 0x7b */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, +/* 0x7c - 0x7f */ DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, DIS_BIT_R8, + +/* 0x80 - 0x83 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0x84 - 0x87 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0x88 - 0x8b */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0x8c - 0x8f */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + +/* 0x90 - 0x93 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0x94 - 0x97 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0x98 - 0x9b */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0x9c - 0x9f */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + +/* 0xa0 - 0xa3 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0xa4 - 0xa7 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0xa8 - 0xab */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0xac - 0xaf */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + +/* 0xb0 - 0xb3 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0xb4 - 0xb7 */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0xb8 - 0xbb */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, +/* 0xbc - 0xbf */ DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, DIS_RES_R8, + +/* 0xc0 - 0xc3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xc4 - 0xc7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xc8 - 0xcb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xcc - 0xcf */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + +/* 0xd0 - 0xd3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xd4 - 0xd7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xd8 - 0xdb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xdc - 0xdf */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + +/* 0xe0 - 0xe3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xe4 - 0xe7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xe8 - 0xeb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xec - 0xef */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + +/* 0xf0 - 0xf3 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xf4 - 0xf7 */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xf8 - 0xfb */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, +/* 0xfc - 0xff */ DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, DIS_SET_R8, + }; + +/* DIS_DD opcodes +*/ +DIS_OP_CALLBACK dis_DD_opcode[0x100]= + { +/* 0x00 - 0x03 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x04 - 0x07 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x08 - 0x0b */ DIS_DD_NOP, DIS_ADD_IX_BC, DIS_DD_NOP, DIS_DD_NOP, +/* 0x0c - 0x0f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + +/* 0x10 - 0x13 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x14 - 0x17 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x18 - 0x1b */ DIS_DD_NOP, DIS_ADD_IX_DE, DIS_DD_NOP, DIS_DD_NOP, +/* 0x1c - 0x1f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + +/* 0x20 - 0x23 */ DIS_DD_NOP, DIS_LD_IX_WORD, DIS_LD_ADDR_IX, DIS_INC_IX, +/* 0x24 - 0x27 */ DIS_INC_IXH, DIS_DEC_IXH, DIS_LD_IXH_BYTE, DIS_DD_NOP, +/* 0x28 - 0x2b */ DIS_DD_NOP, DIS_ADD_IX_IX, DIS_LD_IX_ADDR, DIS_DEC_IX, +/* 0x2c - 0x2f */ DIS_INC_IXL, DIS_DEC_IXL, DIS_LD_IXL_BYTE, DIS_DD_NOP, + +/* 0x30 - 0x33 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x34 - 0x37 */ DIS_INC_IIX, DIS_DEC_IIX, DIS_LD_IIX_BYTE, DIS_DD_NOP, +/* 0x38 - 0x3b */ DIS_DD_NOP, DIS_ADD_IX_SP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x3c - 0x3f */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + +/* 0x40 - 0x43 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x44 - 0x47 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, +/* 0x48 - 0x4b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x4c - 0x4f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + +/* 0x50 - 0x53 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x54 - 0x57 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, +/* 0x58 - 0x5b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x5c - 0x5f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + +/* 0x60 - 0x63 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, +/* 0x64 - 0x67 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, +/* 0x68 - 0x6b */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, +/* 0x6c - 0x6f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, + +/* 0x70 - 0x73 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, +/* 0x74 - 0x77 */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, DIS_XLD_R8_R8, +/* 0x78 - 0x7b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x7c - 0x7f */ DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_XLD_R8_R8, DIS_DD_NOP, + +/* 0x80 - 0x83 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x84 - 0x87 */ DIS_XADD_R8, DIS_XADD_R8, DIS_XADD_R8, DIS_DD_NOP, +/* 0x88 - 0x8b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x8c - 0x8f */ DIS_XADC_R8, DIS_XADC_R8, DIS_XADC_R8, DIS_DD_NOP, + +/* 0x90 - 0x93 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x94 - 0x97 */ DIS_XSUB_R8, DIS_XSUB_R8, DIS_XSUB_R8, DIS_DD_NOP, +/* 0x98 - 0x9b */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0x9c - 0x9f */ DIS_XSBC_R8, DIS_XSBC_R8, DIS_XSBC_R8, DIS_DD_NOP, + +/* 0xa0 - 0xa3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xa4 - 0xa7 */ DIS_XAND_R8, DIS_XAND_R8, DIS_XAND_R8, DIS_DD_NOP, +/* 0xa8 - 0xab */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xac - 0xaf */ DIS_XXOR_R8, DIS_XXOR_R8, DIS_XXOR_R8, DIS_DD_NOP, + +/* 0xb0 - 0xb3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xb4 - 0xb7 */ DIS_X_OR_R8, DIS_X_OR_R8, DIS_X_OR_R8, DIS_DD_NOP, +/* 0xb8 - 0xbb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xbc - 0xbf */ DIS_XCP_R8, DIS_XCP_R8, DIS_XCP_R8, DIS_DD_NOP, + +/* 0xc0 - 0xc3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xc4 - 0xc7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xc8 - 0xcb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_CB_DECODE, +/* 0xcc - 0xcf */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, + +/* 0xd0 - 0xd3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xd4 - 0xd7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xd8 - 0xdb */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xdc - 0xdf */ DIS_DD_NOP, DIS_DD_DD_DECODE, DIS_DD_NOP, DIS_DD_NOP, + +/* 0xe0 - 0xe3 */ DIS_DD_NOP, DIS_POP_IX, DIS_DD_NOP, DIS_EX_ISP_IX, +/* 0xe4 - 0xe7 */ DIS_DD_NOP, DIS_PUSH_IX, DIS_DD_NOP, DIS_DD_NOP, +/* 0xe8 - 0xeb */ DIS_DD_NOP, DIS_JP_IX, DIS_DD_NOP, DIS_DD_NOP, +/* 0xec - 0xef */ DIS_DD_NOP, DIS_DD_ED_DECODE, DIS_DD_NOP, DIS_DD_NOP, + +/* 0xf0 - 0xf3 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xf4 - 0xf7 */ DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, DIS_DD_NOP, +/* 0xf8 - 0xfb */ DIS_DD_NOP, DIS_LD_SP_IX, DIS_DD_NOP, DIS_DD_NOP, +/* 0xfc - 0xff */ DIS_DD_NOP, DIS_DD_FD_DECODE, DIS_DD_NOP, DIS_DD_NOP, + }; + + +/* DIS_DD DIS_CB opcodes +*/ +DIS_OP_CALLBACK dis_DD_CB_opcode[0x100]= + { +/* 0x00 - 0x03 */ DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, +/* 0x04 - 0x07 */ DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, DIS_RLC_IX, +/* 0x08 - 0x0b */ DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, +/* 0x0c - 0x0f */ DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, DIS_RRC_IX, + +/* 0x10 - 0x13 */ DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, +/* 0x14 - 0x17 */ DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, DIS_RL_IX, +/* 0x18 - 0x1b */ DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, +/* 0x1c - 0x1f */ DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, DIS_RR_IX, + +/* 0x20 - 0x23 */ DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, +/* 0x24 - 0x27 */ DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, DIS_SLA_IX, +/* 0x28 - 0x2b */ DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, +/* 0x2c - 0x2f */ DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, DIS_SRA_IX, + +/* 0x30 - 0x33 */ DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, +/* 0x34 - 0x37 */ DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, DIS_SLL_IX, +/* 0x38 - 0x3b */ DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, +/* 0x3c - 0x3f */ DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, DIS_SRL_IX, + +/* 0x40 - 0x43 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x44 - 0x47 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x48 - 0x4b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x4c - 0x4f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + +/* 0x50 - 0x53 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x54 - 0x57 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x58 - 0x5b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x5c - 0x5f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + +/* 0x60 - 0x63 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x64 - 0x67 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x68 - 0x6b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x6c - 0x6f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + +/* 0x70 - 0x73 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x74 - 0x77 */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x78 - 0x7b */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, +/* 0x7c - 0x7f */ DIS_BIT_IX,DIS_BIT_IX, DIS_BIT_IX, DIS_BIT_IX, + +/* 0x80 - 0x83 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0x84 - 0x87 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0x88 - 0x8b */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0x8c - 0x8f */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + +/* 0x90 - 0x93 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0x94 - 0x97 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0x98 - 0x9b */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0x9c - 0x9f */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + +/* 0xa0 - 0xa3 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0xa4 - 0xa7 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0xa8 - 0xab */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0xac - 0xaf */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + +/* 0xb0 - 0xb3 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0xb4 - 0xb7 */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0xb8 - 0xbb */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, +/* 0xbc - 0xbf */ DIS_RES_IX,DIS_RES_IX, DIS_RES_IX, DIS_RES_IX, + +/* 0xc0 - 0xc3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xc4 - 0xc7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xc8 - 0xcb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xcc - 0xcf */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + +/* 0xd0 - 0xd3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xd4 - 0xd7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xd8 - 0xdb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xdc - 0xdf */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + +/* 0xe0 - 0xe3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xe4 - 0xe7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xe8 - 0xeb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xec - 0xef */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + +/* 0xf0 - 0xf3 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xf4 - 0xf7 */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xf8 - 0xfb */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, +/* 0xfc - 0xff */ DIS_SET_IX,DIS_SET_IX, DIS_SET_IX, DIS_SET_IX, + }; + +/* DIS_ED opcodes +*/ +DIS_OP_CALLBACK dis_ED_opcode[0x100]= + { +/* 0x00 - 0x03 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x04 - 0x07 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x08 - 0x0b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x0c - 0x0f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0x10 - 0x13 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x14 - 0x17 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x18 - 0x1b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x1c - 0x1f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0x20 - 0x23 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x24 - 0x27 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x28 - 0x2b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x2c - 0x2f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0x30 - 0x33 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x34 - 0x37 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x38 - 0x3b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x3c - 0x3f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0x40 - 0x43 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, +/* 0x44 - 0x47 */ DIS_NEG, DIS_RETN, DIS_IM_0, DIS_LD_I_A, +/* 0x48 - 0x4b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, +/* 0x4c - 0x4f */ DIS_NEG, DIS_RETI, DIS_IM_0, DIS_LD_R_A, + +/* 0x50 - 0x53 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, +/* 0x54 - 0x57 */ DIS_NEG, DIS_RETN, DIS_IM_1, DIS_LD_A_I, +/* 0x58 - 0x5b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, +/* 0x5c - 0x5f */ DIS_NEG, DIS_RETI, DIS_IM_2, DIS_LD_A_R, + +/* 0x60 - 0x63 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, +/* 0x64 - 0x67 */ DIS_NEG, DIS_RETN, DIS_IM_0, DIS_RRD, +/* 0x68 - 0x6b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, +/* 0x6c - 0x6f */ DIS_NEG, DIS_RETI, DIS_IM_0, DIS_RLD, + +/* 0x70 - 0x73 */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_SBC_HL_R16, DIS_ED_LD_ADDR_R16, +/* 0x74 - 0x77 */ DIS_NEG, DIS_RETN, DIS_IM_1, DIS_ED_NOP, +/* 0x78 - 0x7b */ DIS_IN_R8_C, DIS_OUT_C_R8, DIS_ADC_HL_R16, DIS_ED_LD_R16_ADDR, +/* 0x7c - 0x7f */ DIS_NEG, DIS_RETI, DIS_IM_2, DIS_ED_NOP, + +/* 0x80 - 0x83 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x84 - 0x87 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x88 - 0x8b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x8c - 0x8f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0x90 - 0x93 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x94 - 0x97 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x98 - 0x9b */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0x9c - 0x9f */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0xa0 - 0xa3 */ DIS_LDI, DIS_CPI, DIS_INI, DIS_OUTI, +/* 0xa4 - 0xa7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xa8 - 0xab */ DIS_LDD, DIS_CPD, DIS_IND, DIS_OUTD, +/* 0xac - 0xaf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0xb0 - 0xb3 */ DIS_LDIR, DIS_CPIR, DIS_INIR, DIS_OTIR, +/* 0xb4 - 0xb7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xb8 - 0xbb */ DIS_LDDR, DIS_CPDR, DIS_INDR, DIS_OTDR, +/* 0xbc - 0xbf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0xc0 - 0xc3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xc4 - 0xc7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xc8 - 0xcb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xcc - 0xcf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0xd0 - 0xd3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xd4 - 0xd7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xd8 - 0xdb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xdc - 0xdf */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0xe0 - 0xe3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xe4 - 0xe7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xe8 - 0xeb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xec - 0xef */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + +/* 0xf0 - 0xf3 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xf4 - 0xf7 */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xf8 - 0xfb */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, +/* 0xfc - 0xff */ DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, DIS_ED_NOP, + }; + +/* DIS_FD opcodes +*/ +DIS_OP_CALLBACK dis_FD_opcode[0x100]= + { +/* 0x00 - 0x03 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x04 - 0x07 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x08 - 0x0b */ DIS_FD_NOP, DIS_ADD_IY_BC, DIS_FD_NOP, DIS_FD_NOP, +/* 0x0c - 0x0f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + +/* 0x10 - 0x13 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x14 - 0x17 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x18 - 0x1b */ DIS_FD_NOP, DIS_ADD_IY_DE, DIS_FD_NOP, DIS_FD_NOP, +/* 0x1c - 0x1f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + +/* 0x20 - 0x23 */ DIS_FD_NOP, DIS_LD_IY_WORD, DIS_LD_ADDR_IY, DIS_INC_IY, +/* 0x24 - 0x27 */ DIS_INC_IYH, DIS_DEC_IYH, DIS_LD_IYH_BYTE, DIS_FD_NOP, +/* 0x28 - 0x2b */ DIS_FD_NOP, DIS_ADD_IY_IY, DIS_LD_IY_ADDR, DIS_DEC_IY, +/* 0x2c - 0x2f */ DIS_INC_IYL, DIS_DEC_IYL, DIS_LD_IYL_BYTE, DIS_FD_NOP, + +/* 0x30 - 0x33 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x34 - 0x37 */ DIS_INC_IIY, DIS_DEC_IIY, DIS_LD_IIY_BYTE, DIS_FD_NOP, +/* 0x38 - 0x3b */ DIS_FD_NOP, DIS_ADD_IY_SP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x3c - 0x3f */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + +/* 0x40 - 0x43 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x44 - 0x47 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, +/* 0x48 - 0x4b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x4c - 0x4f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + +/* 0x50 - 0x53 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x54 - 0x57 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, +/* 0x58 - 0x5b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x5c - 0x5f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + +/* 0x60 - 0x63 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, +/* 0x64 - 0x67 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, +/* 0x68 - 0x6b */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, +/* 0x6c - 0x6f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, + +/* 0x70 - 0x73 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, +/* 0x74 - 0x77 */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, DIS_YLD_R8_R8, +/* 0x78 - 0x7b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x7c - 0x7f */ DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_YLD_R8_R8, DIS_FD_NOP, + +/* 0x80 - 0x83 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x84 - 0x87 */ DIS_YADD_R8, DIS_YADD_R8, DIS_YADD_R8, DIS_FD_NOP, +/* 0x88 - 0x8b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x8c - 0x8f */ DIS_YADC_R8, DIS_YADC_R8, DIS_YADC_R8, DIS_FD_NOP, + +/* 0x90 - 0x93 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x94 - 0x97 */ DIS_YSUB_R8, DIS_YSUB_R8, DIS_YSUB_R8, DIS_FD_NOP, +/* 0x98 - 0x9b */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0x9c - 0x9f */ DIS_YSBC_R8, DIS_YSBC_R8, DIS_YSBC_R8, DIS_FD_NOP, + +/* 0xa0 - 0xa3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xa4 - 0xa7 */ DIS_YAND_R8, DIS_YAND_R8, DIS_YAND_R8, DIS_FD_NOP, +/* 0xa8 - 0xab */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xac - 0xaf */ DIS_YYOR_R8, DIS_YYOR_R8, DIS_YYOR_R8, DIS_FD_NOP, + +/* 0xb0 - 0xb3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xb4 - 0xb7 */ DIS_Y_OR_R8, DIS_Y_OR_R8, DIS_Y_OR_R8, DIS_FD_NOP, +/* 0xb8 - 0xbb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xbc - 0xbf */ DIS_YCP_R8, DIS_YCP_R8, DIS_YCP_R8, DIS_FD_NOP, + +/* 0xc0 - 0xc3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xc4 - 0xc7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xc8 - 0xcb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_CB_DECODE, +/* 0xcc - 0xcf */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, + +/* 0xd0 - 0xd3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xd4 - 0xd7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xd8 - 0xdb */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xdc - 0xdf */ DIS_FD_NOP, DIS_FD_DD_DECODE, DIS_FD_NOP, DIS_FD_NOP, + +/* 0xe0 - 0xe3 */ DIS_FD_NOP, DIS_POP_IY, DIS_FD_NOP, DIS_EY_ISP_IY, +/* 0xe4 - 0xe7 */ DIS_FD_NOP, DIS_PUSH_IY, DIS_FD_NOP, DIS_FD_NOP, +/* 0xe8 - 0xeb */ DIS_FD_NOP, DIS_JP_IY, DIS_FD_NOP, DIS_FD_NOP, +/* 0xec - 0xef */ DIS_FD_NOP, DIS_FD_ED_DECODE, DIS_FD_NOP, DIS_FD_NOP, + +/* 0xf0 - 0xf3 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xf4 - 0xf7 */ DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, DIS_FD_NOP, +/* 0xf8 - 0xfb */ DIS_FD_NOP, DIS_LD_SP_IY, DIS_FD_NOP, DIS_FD_NOP, +/* 0xfc - 0xff */ DIS_FD_NOP, DIS_FD_FD_DECODE, DIS_FD_NOP, DIS_FD_NOP, + }; + + +/* DIS_FD DIS_CB opcodes +*/ +DIS_OP_CALLBACK dis_FD_CB_opcode[0x100]= + { +/* 0x00 - 0x03 */ DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, +/* 0x04 - 0x07 */ DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, DIS_RLC_IY, +/* 0x08 - 0x0b */ DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, +/* 0x0c - 0x0f */ DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, DIS_RRC_IY, + +/* 0x10 - 0x13 */ DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, +/* 0x14 - 0x17 */ DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, DIS_RL_IY, +/* 0x18 - 0x1b */ DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, +/* 0x1c - 0x1f */ DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, DIS_RR_IY, + +/* 0x20 - 0x23 */ DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, +/* 0x24 - 0x27 */ DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, DIS_SLA_IY, +/* 0x28 - 0x2b */ DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, +/* 0x2c - 0x2f */ DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, DIS_SRA_IY, + +/* 0x30 - 0x33 */ DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, +/* 0x34 - 0x37 */ DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, DIS_SLL_IY, +/* 0x38 - 0x3b */ DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, +/* 0x3c - 0x3f */ DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, DIS_SRL_IY, + +/* 0x40 - 0x43 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x44 - 0x47 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x48 - 0x4b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x4c - 0x4f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + +/* 0x50 - 0x53 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x54 - 0x57 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x58 - 0x5b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x5c - 0x5f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + +/* 0x60 - 0x63 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x64 - 0x67 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x68 - 0x6b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x6c - 0x6f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + +/* 0x70 - 0x73 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x74 - 0x77 */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x78 - 0x7b */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, +/* 0x7c - 0x7f */ DIS_BIT_IY,DIS_BIT_IY, DIS_BIT_IY, DIS_BIT_IY, + +/* 0x80 - 0x83 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0x84 - 0x87 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0x88 - 0x8b */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0x8c - 0x8f */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + +/* 0x90 - 0x93 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0x94 - 0x97 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0x98 - 0x9b */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0x9c - 0x9f */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + +/* 0xa0 - 0xa3 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0xa4 - 0xa7 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0xa8 - 0xab */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0xac - 0xaf */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + +/* 0xb0 - 0xb3 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0xb4 - 0xb7 */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0xb8 - 0xbb */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, +/* 0xbc - 0xbf */ DIS_RES_IY,DIS_RES_IY, DIS_RES_IY, DIS_RES_IY, + +/* 0xc0 - 0xc3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xc4 - 0xc7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xc8 - 0xcb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xcc - 0xcf */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + +/* 0xd0 - 0xd3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xd4 - 0xd7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xd8 - 0xdb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xdc - 0xdf */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + +/* 0xe0 - 0xe3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xe4 - 0xe7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xe8 - 0xeb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xec - 0xef */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + +/* 0xf0 - 0xf3 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xf4 - 0xf7 */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xf8 - 0xfb */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, +/* 0xfc - 0xff */ DIS_SET_IY,DIS_SET_IY, DIS_SET_IY, DIS_SET_IY, + }; + +/* DIS_First/single byte opcodes +*/ +DIS_OP_CALLBACK dis_opcode_z80[0x100]= + { +/* 0x00 - 0x03 */ DIS_NOP, DIS_LD_R16_WORD, DIS_LD_R16_A, DIS_INC_R16, +/* 0x04 - 0x07 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RLCA, +/* 0x08 - 0x0b */ DIS_EX_AF_AF, DIS_ADD_HL_R16, DIS_LD_A_R16, DIS_DEC_R16, +/* 0x0c - 0x0f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RRCA, + +/* 0x10 - 0x13 */ DIS_DJNZ, DIS_LD_R16_WORD, DIS_LD_R16_A, DIS_INC_R16, +/* 0x14 - 0x17 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RLA, +/* 0x18 - 0x1b */ DIS_JR, DIS_ADD_HL_R16, DIS_LD_A_R16, DIS_DEC_R16, +/* 0x1c - 0x1f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_RRA, + +/* 0x20 - 0x23 */ DIS_JR_CO, DIS_LD_R16_WORD, DIS_LD_ADDR_HL, DIS_INC_R16, +/* 0x24 - 0x27 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_DAA, +/* 0x28 - 0x2b */ DIS_JR_CO, DIS_ADD_HL_R16, DIS_LD_HL_ADDR, DIS_DEC_R16, +/* 0x2c - 0x2f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_CPL, + +/* 0x30 - 0x33 */ DIS_JR_CO, DIS_LD_R16_WORD, DIS_LD_ADDR_A, DIS_INC_R16, +/* 0x34 - 0x37 */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_SCF, +/* 0x38 - 0x3b */ DIS_JR_CO, DIS_ADD_HL_R16, DIS_LD_A_ADDR, DIS_DEC_R16, +/* 0x3c - 0x3f */ DIS_INC_R8, DIS_DEC_R8, DIS_LD_R8_BYTE, DIS_CCF, + +/* 0x40 - 0x43 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x44 - 0x47 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x48 - 0x4b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x4c - 0x4f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + +/* 0x50 - 0x53 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x54 - 0x57 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x58 - 0x5b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x5c - 0x5f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + +/* 0x60 - 0x63 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x64 - 0x67 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x68 - 0x6b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x6c - 0x6f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + +/* 0x70 - 0x73 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x74 - 0x77 */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_HALT, DIS_LD_R8_R8, +/* 0x78 - 0x7b */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, +/* 0x7c - 0x7f */ DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, DIS_LD_R8_R8, + +/* 0x80 - 0x83 */ DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, +/* 0x84 - 0x87 */ DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, DIS_ADD_R8, +/* 0x88 - 0x8b */ DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, +/* 0x8c - 0x8f */ DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, DIS_ADC_R8, + +/* 0x90 - 0x93 */ DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, +/* 0x94 - 0x97 */ DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, DIS_SUB_R8, +/* 0x98 - 0x9b */ DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, +/* 0x9c - 0x9f */ DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, DIS_SBC_R8, + +/* 0xa0 - 0xa3 */ DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, +/* 0xa4 - 0xa7 */ DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, DIS_AND_R8, +/* 0xa8 - 0xab */ DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, +/* 0xac - 0xaf */ DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, DIS_XOR_R8, + +/* 0xb0 - 0xb3 */ DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, +/* 0xb4 - 0xb7 */ DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, DIS_OR_R8, +/* 0xb8 - 0xbb */ DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, +/* 0xbc - 0xbf */ DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, DIS_CP_R8, + +/* 0xc0 - 0xc3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_JP, +/* 0xc4 - 0xc7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_ADD_A_BYTE, DIS_RST, +/* 0xc8 - 0xcb */ DIS_RET_CO, DIS_RET, DIS_JP_CO, DIS_CB_DECODE, +/* 0xcc - 0xcf */ DIS_CALL_CO, DIS_CALL, DIS_ADC_A_BYTE, DIS_RST, + +/* 0xd0 - 0xd3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_OUT_BYTE_A, +/* 0xd4 - 0xd7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_SUB_A_BYTE, DIS_RST, +/* 0xd8 - 0xdb */ DIS_RET_CO, DIS_EXX, DIS_JP_CO, DIS_IN_A_BYTE, +/* 0xdc - 0xdf */ DIS_CALL_CO, DIS_DD_DECODE, DIS_SBC_A_BYTE, DIS_RST, + +/* 0xe0 - 0xe3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_EX_ISP_HL, +/* 0xe4 - 0xe7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_AND_A_BYTE, DIS_RST, +/* 0xe8 - 0xeb */ DIS_RET_CO, DIS_JP_HL, DIS_JP_CO, DIS_EX_DE_HL, +/* 0xec - 0xef */ DIS_CALL_CO, DIS_ED_DECODE, DIS_XOR_A_BYTE, DIS_RST, + +/* 0xf0 - 0xf3 */ DIS_RET_CO, DIS_POP_R16, DIS_JP_CO, DIS_DI, +/* 0xf4 - 0xf7 */ DIS_CALL_CO, DIS_PUSH_R16, DIS_OR_A_BYTE, DIS_RST, +/* 0xf8 - 0xfb */ DIS_RET_CO, DIS_LD_SP_HL, DIS_JP_CO, DIS_EI, +/* 0xfc - 0xff */ DIS_CALL_CO, DIS_FD_DECODE, DIS_CP_A_BYTE, DIS_RST, + }; + + +#endif + +/* END OF FILE */ diff --git a/src/z80_private.h b/src/z80_private.h new file mode 100644 index 0000000..6675c12 --- /dev/null +++ b/src/z80_private.h @@ -0,0 +1,252 @@ +/* + + z80 - Z80 emulation + + Copyright (C) 2006 Ian Cowburn (ianc@noddybox.demon.co.uk) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + + $Id$ + + Private macros for Z80 + +*/ + +#ifndef Z80_PRIVATE_H +#define Z80_PRIVATE_H "$Id$" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_PER_CALLBACK 10 + + +/* ---------------------------------------- TYPES +*/ + +typedef signed short sword; + +typedef union +{ + Z80Word w; + Z80Byte b[2]; +} Z80Reg; + +struct Z80 +{ + Z80Val cycle; + + Z80Word PC; + + Z80Reg AF; + Z80Reg BC; + Z80Reg DE; + Z80Reg HL; + + Z80Word AF_; + Z80Word BC_; + Z80Word DE_; + Z80Word HL_; + + Z80Reg IX; + Z80Reg IY; + + Z80Word SP; + + Z80Byte IFF1; + Z80Byte IFF2; + Z80Byte IM; + Z80Byte I; + Z80Byte R; + int halt; + + Z80Byte shift; + + int raise; + Z80Byte devbyte; + int nmi; + + Z80ReadMemory disread; + + Z80ReadMemory mread; + Z80WriteMemory mwrite; + + Z80ReadPort pread; + Z80WritePort pwrite; + + Z80Callback callback[eZ80_NO_CALLBACK][MAX_PER_CALLBACK]; + + int last_cb; +}; + + +/* ---------------------------------------- MACROS +*/ + +/* NOTE: A lot of these macros assume you have a variable called 'cpu' + which is a pointer to Z80 +*/ + + +/* Invoke a callback class +*/ +#define CALLBACK(r,d) do \ + { \ + int f; \ + \ + for(f=0;fcallback[r][f]) \ + cpu->callback[r][f](cpu,d); \ + } while(0) + +/* Flag register +*/ +#define C_Z80 0x01 +#define N_Z80 0x02 +#define P_Z80 0x04 +#define V_Z80 P_Z80 +#define H_Z80 0x10 +#define Z_Z80 0x40 +#define S_Z80 0x80 + +#define B3_Z80 0x08 +#define B5_Z80 0x20 + + +#define SET(v,b) (v)|=b +#define CLR(v,b) (v)&=~(b) + +#define SETFLAG(f) SET(cpu->AF.b[LO],f) +#define CLRFLAG(f) CLR(cpu->AF.b[LO],f) + +#define PEEK(addr) (cpu->mread(cpu,addr)) +#define PEEKW(addr) FPEEKW(cpu,addr) + +#define POKE(addr,val) cpu->mwrite(cpu,addr,val) +#define POKEW(addr,val) FPOKEW(cpu,addr,val) + +#define FETCH_BYTE (cpu->mread(cpu,cpu->PC++)) +#define FETCH_WORD (cpu->PC+=2,FPEEKW(cpu,cpu->PC-2)) + +#define IS_C (cpu->AF.b[LO]&C_Z80) +#define IS_N (cpu->AF.b[LO]&N_Z80) +#define IS_P (cpu->AF.b[LO]&P_Z80) +#define IS_H (cpu->AF.b[LO]&H_Z80) +#define IS_Z (cpu->AF.b[LO]&Z_Z80) +#define IS_S (cpu->AF.b[LO]&S_Z80) + +#define CARRY IS_C + +#define IS_IX_IY (cpu->shift==0xdd || cpu->shift==0xfd) +#define OFFSET(off) off=(IS_IX_IY ? (Z80Relative)FETCH_BYTE:0) + +#define TSTATE(n) cpu->cycle+=n + +#define ADD_R(v) cpu->R=((cpu->R&0x80)|((cpu->R+(v))&0x7f)) +#define INC_R ADD_R(1) + +#define PUSH(REG) do \ + { \ + Z80Word pushv=REG; \ + cpu->SP-=2; \ + cpu->mwrite(cpu,cpu->SP,pushv); \ + cpu->mwrite(cpu,cpu->SP+1,pushv>>8);\ + } while(0) + +#define POP(REG) do \ + { \ + REG=PEEK(cpu->SP) | \ + (Z80Word)PEEK(cpu->SP+1)<<8; \ + cpu->SP+=2; \ + } while(0) + +#define SETHIDDEN(res) cpu->AF.b[LO]=(cpu->AF.b[LO]&~(B3_Z80|B5_Z80))|\ + ((res)&(B3_Z80|B5_Z80)) + +#define CALL do \ + { \ + PUSH(cpu->PC+2); \ + cpu->PC=PEEKW(cpu->PC); \ + } while(0) + +#define NOCALL cpu->PC+=2 +#define JP cpu->PC=PEEKW(cpu->PC) +#define NOJP cpu->PC+=2 +#define JR cpu->PC+=(Z80Relative)PEEK(cpu->PC)+1 +#define NOJR cpu->PC++ + +#define OUT(P,V) do \ + { \ + if (cpu->pwrite) \ + cpu->pwrite(cpu,P,V); \ + } while(0) + +#define IN(P) (cpu->pread?cpu->pread(cpu,P):0) + + + +/* ---------------------------------------- LABELS +*/ +extern Z80Label *z80_labels; + + +/* ---------------------------------------- FLAG TABLES +*/ +extern Z80Byte PSZtable[512]; +extern Z80Byte SZtable[512]; +extern Z80Byte Ptable[512]; +extern Z80Byte Stable[512]; +extern Z80Byte Ztable[512]; + + +/* ---------------------------------------- GLOBAL GENERAL OPCODES/ROUTINES +*/ +void Z80_Decode(Z80 *cpu, Z80Byte opcode); +void Z80_InitialiseInternals(void); + + +/* ---------------------------------------- DISASSEMBLY +*/ +#ifdef ENABLE_DISASSEM +typedef void (*DIS_OP_CALLBACK)(Z80 *z80, Z80Byte op, Z80Word *pc); + +extern DIS_OP_CALLBACK dis_CB_opcode[]; +extern DIS_OP_CALLBACK dis_DD_opcode[]; +extern DIS_OP_CALLBACK dis_DD_CB_opcode[]; +extern DIS_OP_CALLBACK dis_ED_opcode[]; +extern DIS_OP_CALLBACK dis_FD_opcode[]; +extern DIS_OP_CALLBACK dis_FD_CB_opcode[]; +extern DIS_OP_CALLBACK dis_opcode_z80[]; + +const char *Z80_Dis_Printf(const char *format, ...); + +Z80Byte Z80_Dis_FetchByte(Z80 *cpu, Z80Word *pc); +Z80Word Z80_Dis_FetchWord(Z80 *cpu, Z80Word *pc); + +void Z80_Dis_Set(const char *op, const char *arg); +const char *Z80_Dis_GetOp(void); +const char *Z80_Dis_GetArg(void); +#endif /* ENABLE_DISASSEM */ + +#endif /* Z80_PRIVATE_H */ + +/* END OF FILE */ diff --git a/src/zx81.c b/src/zx81.c index cb81d80..092d575 100644 --- a/src/zx81.c +++ b/src/zx81.c @@ -537,11 +537,6 @@ Z80Byte ZX81ReadMem(Z80 *z80, Z80Word addr) { Z80Byte b; - /* B6 of R is tied to the IRQ line (only when HSYNC active?) - if ((HSYNC)&&(!(z80->R&0x40))) - z80->IRQ=TRUE; - */ - b=mem[addr&0x7fff]; /* If bit 6 of the opcode is set the opcode is sent as is to the @@ -565,16 +560,6 @@ Z80Byte ZX81ReadMem(Z80 *z80, Z80Word addr) } -Z80Word ZX81ReadWord(Z80 *z80, Z80Word addr) -{ - Z80Word l,h; - - l=ZX81ReadMem(z80,addr); - h=ZX81ReadMem(z80,addr+1); - return (h<<8)|l; -} - - void ZX81WriteMem(Z80 *z80, Z80Word addr, Z80Byte val) { addr=addr&0x7fff; @@ -584,18 +569,6 @@ void ZX81WriteMem(Z80 *z80, Z80Word addr, Z80Byte val) } -void ZX81WriteWord(Z80 *z80, Z80Word addr, Z80Word val) -{ - if (addr>=RAMBOT && addr<=RAMTOP) - mem[addr]=val&0xff; - - addr++; - - if (addr>=RAMBOT && addr<=RAMTOP) - mem[addr]=val>>8; -} - - Z80Byte ZX81ReadPort(Z80 *z80, Z80Word port) { Z80Byte b=0; diff --git a/src/zx81.h b/src/zx81.h index f308e8b..ea22343 100644 --- a/src/zx81.h +++ b/src/zx81.h @@ -43,8 +43,6 @@ void ZX81KeyEvent(SDL_Event *e); */ Z80Byte ZX81ReadMem(Z80 *z80, Z80Word addr); void ZX81WriteMem(Z80 *z80, Z80Word addr, Z80Byte val); -Z80Word ZX81ReadWord(Z80 *z80, Z80Word addr); -void ZX81WriteWord(Z80 *z80, Z80Word addr, Z80Word val); Z80Byte ZX81ReadPort(Z80 *z80, Z80Word port); void ZX81WritePort(Z80 *z80, Z80Word port, Z80Byte val); Z80Byte ZX81ReadForDisassem(Z80 *z80, Z80Word addr); -- cgit v1.2.3