home *** CD-ROM | disk | FTP | other *** search
- /* Kernel.c: Z80 initialization and main cycle - basic support routines.
- *
- * Copyright 1996 Rui Fernando Ferreira Ribeiro.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*
- * History:
- * 4th April 96:
- * . Modified R register handling -- about 10% speed
- * increase -- see also [ld8bits.c]
- * . Modified central loop of emulation (execute()) for
- * a faster emulation
- * . Spoted an error in Z80 emulation - handling IX or IY
- * prefixes, if next instruction is not a HL instruction,
- * the prefix will affect all instructions until if founds
- * a HL instruction or a ED prefix -- but it's surprising
- * how failed only 4 of nearly 2000 spectrum programs
- * tested.
- *
- * 5th April 96:
- * . Modified handling of IX and IY prefixes --
- * extensive changes in the code. This will fix the error
- * spoted and will increase once more the emulation speed.
- */
-
- #include "env.h"
- #include "ivars.h"
-
- /* Increment the lower 7 bits of R in each M1 cycle
- */
- #define inc_R() (R++)
-
- /* Opcode being interpreted - in IX or IY */
- static UCHAR opcode;
-
- /*=========================================================================*
- * do_reset *
- *=========================================================================*/
- void do_reset()
- {
- /* CPU internal flags */
- _IM = IFF1 = IFF2 =
-
- /* CPU registers */
- R_BIT7 = R = I =
-
- HL = BC = DE = AF = IX = IY = SP =
-
- /* alternative registers */
- HL2 = BC2 = DE2 = AF2 =
-
- /* flags CPU */
- flags._S = flags._Z = flags._X = flags._H = flags._Y =
- flags._P = flags._N = flags._C = 0;
- /* Interrupt counter */
- ResetTickCounter();
- /* Program Counter */
- PutPC(0);
- }
-
- /*=========================================================================*
- * execute *
- *=========================================================================*/
- void execute()
- {
- /* Z80 main cycle */
- /* --> 0xDD e 0xFD are only 'switches' wich map IX or IY in HL
- till instruction end [but not in instructions prefixed by ED]
- --> 0xED, 0xCB are 'gates' to another sets of instructions
- */
- if(DelayEmVal)
- {
-
- while(clock_ticks < INT_TIME)
- {
- inc_R();
- /* Call funtion indexed by opcode */
- (*instruc_tabl[Getnextbyte()])();
- }
-
- // Spend a bit of time ---
- {
- USHORT i;
-
- i = DelayEmVal;
- while(i)
- {
- (void)do_nothing(&i);
- {
- USHORT j = i;
-
- while(j)
- (void)do_nothing(&j);
- }
- }
- }
- }
- else
- {
- while(clock_ticks < INT_TIME)
- {
- inc_R();
- /* Call funtion indexed by opcode */
- (*instruc_tabl[Getnextbyte()])();
- }
- }
- /* do_int_tasks(); */
- /* if interrupts activated */
- if(IFF1)
- {
- do_interrupt();
- }
- else
- ResetTickCounter();
- }
-
- /*=========================================================================*
- * execute_IX *
- *=========================================================================*/
- static void execute_IX()
- {
- inc_R(); /* It appears to be this way */
-
- (*instruc_tablIX[Getnextbyte()])();
- }
-
- /*=========================================================================*
- * execute_IY *
- *=========================================================================*/
- static void execute_IY()
- {
- inc_R(); /* It appears to be this way */
-
- /* Call function acording to opcode */
- (*instruc_tablIY[Getnextbyte()])();
- }
-
- /*=========================================================================*
- * execute_CB *
- *=========================================================================*/
- static void execute_CB()
- {
- inc_R();
- (*instruc_tablCB[Getnextbyte()])();
- }
-
- /*=========================================================================*
- * execute_IXCB *
- *=========================================================================*/
- static void execute_IXCB()
- {
- /*If IX or IY is active, then the next byte isn∩t
- a instruction, but a displacement for IX or IY
- */
- lastbyte = Getnextbyte();
- (*instruc_tablIXCB[Getnextbyte()])();
- }
-
- /*=========================================================================*
- * execute_CB *
- *=========================================================================*/
- static void execute_IYCB()
- {
- /*If IX or IY is active, then the next byte isn∩t
- a instruction, but a displacement for IX or IY
- */
- lastbyte = Getnextbyte();
- (*instruc_tablIYCB[Getnextbyte()])();
- }
-
- /*=========================================================================*
- * execute_ED *
- *=========================================================================*/
- static void execute_ED()
- {
- inc_R();
- (*instruc_tablED[Getnextbyte()])();
- }
-
- /* EOF: Kernel.c */