/* z80.jscpp: z80 supplementary functions
Copyright (c) 1999-2008 Philip Kendall, Matthew Westcott
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 3 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, see .
Contact details:
Matthew Westcott, 14 Daisy Hill Drive, Adlington, Chorley, Lancs PR6 9NE UNITED KINGDOM
*/
#include "z80_macros.jscpp"
/* Whether a half carry occured or not can be determined by looking at
the 3rd bit of the two arguments and the result; these are hashed
into this table in the form r12, where r is the 3rd bit of the
result, 1 is the 3rd bit of the 1st argument and 2 is the
third bit of the 2nd argument; the tables differ for add and subtract
operations */
var halfcarry_add_table = [ 0, FLAG_H, FLAG_H, FLAG_H, 0, 0, 0, FLAG_H ];
var halfcarry_sub_table = [ 0, 0, FLAG_H, 0, FLAG_H, 0, FLAG_H, FLAG_H ];
/* Similarly, overflow can be determined by looking at the 7th bits; again
the hash into this table is r12 */
var overflow_add_table = [ 0, 0, 0, FLAG_V, FLAG_V, 0, 0, 0 ];
var overflow_sub_table = [ 0, FLAG_V, 0, 0, 0, 0, FLAG_V, 0 ];
/* Some more tables; initialised in z80_init_tables() */
var sz53_table = []; /* The S, Z, 5 and 3 bits of the index */
var parity_table = []; /* The parity of the lookup value */
var sz53p_table = []; /* OR the above two tables together */
/* This is what everything acts on! */
var z80 = {
a:0, f:0, b:0, c:0, d:0, e:0, h:0, l:0,
a_:0, f_:0, b_:0, c_:0, d_:0, e_:0, h_:0, l_:0,
ixh:0, ixl:0, iyh:0, iyl:0,
i:0,
r:0, /* The low seven bits of the R register. 16 bits long
so it can also act as an RZX instruction counter */
r7:0, /* The high bit of the R register */
sp:0, pc:0,
iff1:0, iff2:0, im:0, halted:false
};
/* Set up the z80 emulation */
function z80_init() {
z80_init_tables();
}
/* Initalise the tables used to set flags */
function z80_init_tables() {
var i,j,k;
var parity;
for(i=0;i<0x100;i++) {
sz53_table[i]= i & ( FLAG_3 | FLAG_5 | FLAG_S );
j=i; parity=0;
for(k=0;k<8;k++) { parity ^= j & 1; j >>=1; }
parity_table[i]= ( parity ? 0 : FLAG_P );
sz53p_table[i] = sz53_table[i] | parity_table[i];
}
sz53_table[0] |= FLAG_Z;
sz53p_table[0] |= FLAG_Z;
}
/* Reset the z80 */
function z80_reset() {
A =F =B =C =D =E =H =L =0;
A_ =F_ =B_ =C_ =D_ =E_=H_ =L_=0;
IXH=IXL=IYH=IYL=0;
I=R=R7=0;
SP=PC=0;
IFF1=IFF2=IM=0;
z80.halted=0;
}
/* Process a z80 maskable interrupt */
function z80_interrupt() {
/* Process if IFF1 set && (if a Timex machine, SCLD INTDISABLE is clear) */
if( IFF1 ) {
if( z80.halted ) { PC++; PC &= 0xffff; z80.halted = false; }
IFF1=IFF2=0;
SP = (SP - 1) & 0xffff;
writebyte( SP, PCHR );
SP = (SP - 1) & 0xffff;
writebyte( SP, PCLR );
R = (R+1) & 0x7f; /* rzx_instructions_offset--; */
switch(IM) {
case 0: PC = 0x0038; tstates+=12; break;
case 1: PC = 0x0038; tstates+=13; break;
case 2:
{
var inttemp=(0x100*I)+0xff;
var pcl = readbyte(inttemp++); inttemp &= 0xffff; var pch = readbyte(inttemp);
PC = pcl | (pch << 8);
tstates+=19;
break;
}
default:
ui_error( UI_ERROR_ERROR, "Unknown interrupt mode %d", IM );
fuse_abort();
}
}
}
/* Process a z80 non-maskable interrupt */
function z80_nmi() {
/* FIXME: what happens if the z80 is HALTed? */
IFF1 = 0;
SP = (SP - 1) & 0xffff;
writebyte( SP, PCHR );
SP = (SP - 1) & 0xffff;
writebyte( SP, PCLR );
/* FIXME: how is R affected? */
/* FIXME: how does contention apply here? */
tstates += 11; PC = 0x0066;
}