summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/expr.c728
-rw-r--r--src/expr.h59
-rw-r--r--src/z80.c366
-rw-r--r--src/z80.h245
-rw-r--r--src/z80_decode.c2522
-rw-r--r--src/z80_dis.c2476
-rw-r--r--src/z80_private.h252
7 files changed, 6648 insertions, 0 deletions
diff --git a/src/expr.c b/src/expr.c
new file mode 100644
index 0000000..9369e1d
--- /dev/null
+++ b/src/expr.c
@@ -0,0 +1,728 @@
+/*
+ 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
+ {
+ /* 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;
+ }
+ }
+
+ 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 */
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..ced7fbd
--- /dev/null
+++ b/src/z80_decode.c
@@ -0,0 +1,2522 @@
+/*
+
+ 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)
+ {
+ Z80Word port;
+
+ port=FETCH_BYTE;
+ port|=(Z80Word)cpu->AF.b[HI]<<8;
+ cpu->AF.b[HI]=cpu->pread(cpu,port);
+ }
+ 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 */