/* 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; }