diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 323 | ||||
| -rw-r--r-- | src/expr.c | 735 | ||||
| -rw-r--r-- | src/expr.h | 59 | ||||
| -rw-r--r-- | src/main.c | 8 | ||||
| -rw-r--r-- | src/memmenu.c | 14 | ||||
| -rw-r--r-- | src/z80.c | 366 | ||||
| -rw-r--r-- | src/z80.h | 245 | ||||
| -rw-r--r-- | src/z80_decode.c | 2516 | ||||
| -rw-r--r-- | src/z80_dis.c | 2476 | ||||
| -rw-r--r-- | src/z80_private.h | 252 | ||||
| -rw-r--r-- | src/zx81.c | 27 | ||||
| -rw-r--r-- | src/zx81.h | 2 | 
12 files changed, 6845 insertions, 178 deletions
| 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 <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +/* ---------------------------------------- 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_SHIFTR: +		if (right<0) +		{ +		    sprintf(error,"Cannot shift right 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=left<right; +		break; + +	    case TYPE_GT: +		*result=left>right; +		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 */ @@ -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 <ianc@noddybox.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$ + +    Z80 + +*/ +#include <stdlib.h> +#include <string.h> + +#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;f<eZ80_NO_CALLBACK;f++) +	    for(r=0;r<MAX_PER_CALLBACK;r++) +		cpu->callback[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;f<MAX_PER_CALLBACK;f++) +    { +    	if (!cpu->callback[reason][f]) +	{ +	    cpu->callback[reason][f]=callback; +	    return TRUE; +	} +    } + +    return FALSE; +} + + +void Z80RemoveCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback) +{ +    int f; + +    for(f=0;f<MAX_PER_CALLBACK;f++) +    	if (cpu->callback[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 <ianc@noddybox.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$ + +*/ + +#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 <ianc@noddybox.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$ + +*/ +#include <stdlib.h> +#include <limits.h> + +#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<<b)) +		p++; + +	if (p&1) +	    p=0; +	else +	    p=P_Z80; + +	if (f) +	    z=0; +	else +	    z=Z_Z80; + +	if (f&0x80) +	    s=S_Z80; +	else +	    s=0; + +	Ptable[f]=p; +	Stable[f]=s; +	Ztable[f]=z; +	SZtable[f]=z|s; +	PSZtable[f]=z|s|p; + +	Ptable[f+256]=Ptable[f]|C_Z80; +	Stable[f+256]=Stable[f]|C_Z80; +	Ztable[f+256]=Ztable[f]|C_Z80; +	SZtable[f+256]=SZtable[f]|C_Z80; +	PSZtable[f+256]=PSZtable[f]|C_Z80; +    } +} + +static Z80Word FPEEKW(Z80 *cpu, Z80Word addr) +{ +    return (PEEK(addr) | (Z80Word)PEEK(addr+1)<<8); +} + + +static void FPOKEW(Z80 *cpu, Z80Word addr, Z80Word val) +{ +    cpu->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<<B)) \ +    { \ +	if (B==7 && (REG&S_Z80)) cpu->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<<B) +#define BIT_RES(REG,B) (REG)&=~(1<<B) + + +/* ---------------------------------------- JUMP OPERATIONS +*/ +#define JR_COND(COND) \ +do { \ +    if (COND) \ +    { \ +	TSTATE(12); \ +	JR; \ +    } \ +    else \ +    { \ +	TSTATE(7); \ +	NOJR; \ +    } \ +} while(0) + + +#define JP_COND(COND) \ +do { \ +    TSTATE(10); \ +    if (COND) \ +    { \ +	JP; \ +    } \ +    else \ +    { \ +	NOJP; \ +    } \ +} while(0) + + +#define CALL_COND(COND) \ +do { \ +    if (COND) \ +    { \ +	TSTATE(17); \ +	CALL; \ +    } \ +    else \ +    { \ +	TSTATE(10); \ +	NOCALL; \ +    } \ +} while(0) + + +#define RET_COND(COND) \ +do { \ +    if (COND) \ +    { \ +	TSTATE(11); \ +	POP(cpu->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 <ianc@noddybox.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$ + +*/ +static const char ident[]="$Id$"; + +#ifdef ENABLE_DISASSEM + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#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;f<MAX_PER_CALLBACK;f++)		\ +			    if (cpu->callback[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 */ @@ -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; @@ -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); | 
