kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
546 wiersze
8.9 KiB
C
546 wiersze
8.9 KiB
C
/* Emulations of the ED operations of the Z80 instruction set.
|
|
* Copyright (C) 1994 Ian Collier.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#define input(var) { unsigned short u;\
|
|
var=u=in(b,c);\
|
|
tstates+=u>>8;\
|
|
f=(f&1)|(var&0xa8)|((!var)<<6)|parity(var);\
|
|
}
|
|
#define sbchl(x) { unsigned short z=(x);\
|
|
unsigned long t=(hl-z-cy)&0x1ffff;\
|
|
f=((t>>8)&0xa8)|(t>>16)|2|\
|
|
(((hl&0xfff)<(z&0xfff)+cy)<<4)|\
|
|
(((hl^z)&(hl^t)&0x8000)>>13)|\
|
|
((!(t&0xffff))<<6)|2;\
|
|
l=t;\
|
|
h=t>>8;\
|
|
}
|
|
|
|
#define adchl(x) { unsigned short z=(x);\
|
|
unsigned long t=hl+z+cy;\
|
|
f=((t>>8)&0xa8)|(t>>16)|\
|
|
(((hl&0xfff)+(z&0xfff)+cy>0xfff)<<4)|\
|
|
(((~hl^z)&(hl^t)&0x8000)>>13)|\
|
|
((!(t&0xffff))<<6)|2;\
|
|
l=t;\
|
|
h=t>>8;\
|
|
}
|
|
|
|
#define neg (a=-a,\
|
|
f=(a&0xa8)|((!a)<<6)|(((a&15)>0)<<4)|((a==128)<<2)|2|(a>0))
|
|
|
|
{
|
|
unsigned char op=fetch(pc&0x7fff);
|
|
pc++;
|
|
radjust++;
|
|
switch(op){
|
|
instr(0x40,8);
|
|
input(b);
|
|
endinstr;
|
|
|
|
instr(0x41,8);
|
|
tstates+=out(b,c,b);
|
|
endinstr;
|
|
|
|
instr(0x42,11);
|
|
sbchl(bc);
|
|
endinstr;
|
|
|
|
instr(0x43,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
store2b(addr,b,c);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x44,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x45,4);
|
|
iff1=iff2;
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x46,4);
|
|
im=0;
|
|
endinstr;
|
|
|
|
instr(0x47,5);
|
|
i=a;
|
|
endinstr;
|
|
|
|
instr(0x48,8);
|
|
input(c);
|
|
endinstr;
|
|
|
|
instr(0x49,8);
|
|
tstates+=out(b,c,c);
|
|
endinstr;
|
|
|
|
instr(0x4a,11);
|
|
adchl(bc);
|
|
endinstr;
|
|
|
|
instr(0x4b,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
c=fetch(addr);
|
|
b=fetch(addr+1);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x4c,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x4d,4);
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x4e,4);
|
|
im=1;
|
|
endinstr;
|
|
|
|
instr(0x4f,5);
|
|
r=a;
|
|
radjust=r;
|
|
endinstr;
|
|
|
|
instr(0x50,8);
|
|
input(d);
|
|
endinstr;
|
|
|
|
instr(0x51,8);
|
|
tstates+=out(b,c,d);
|
|
endinstr;
|
|
|
|
instr(0x52,11);
|
|
sbchl(de);
|
|
endinstr;
|
|
|
|
instr(0x53,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
store2b(addr,d,e);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x54,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x55,4);
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x56,4);
|
|
im=2;
|
|
endinstr;
|
|
|
|
instr(0x57,5);
|
|
a=i;
|
|
f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2);
|
|
endinstr;
|
|
|
|
instr(0x58,8);
|
|
input(e);
|
|
endinstr;
|
|
|
|
instr(0x59,8);
|
|
tstates+=out(b,c,e);
|
|
endinstr;
|
|
|
|
instr(0x5a,11);
|
|
adchl(de);
|
|
endinstr;
|
|
|
|
instr(0x5b,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
e=fetch(addr);
|
|
d=fetch(addr+1);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x5c,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x5d,4);
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x5e,4);
|
|
im=3;
|
|
endinstr;
|
|
|
|
instr(0x5f,5);
|
|
r=(r&0x80)|(radjust&0x7f);
|
|
a=r;
|
|
f=(f&1)|(a&0xa8)|((!a)<<6)|(iff2<<2);
|
|
endinstr;
|
|
|
|
instr(0x60,8);
|
|
input(h);
|
|
endinstr;
|
|
|
|
instr(0x61,8);
|
|
tstates+=out(b,c,h);
|
|
endinstr;
|
|
|
|
instr(0x62,11);
|
|
sbchl(hl);
|
|
endinstr;
|
|
|
|
instr(0x63,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
store2b(addr,h,l);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x64,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x65,4);
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x66,4);
|
|
im=0;
|
|
endinstr;
|
|
|
|
instr(0x67,14);
|
|
{unsigned char t=fetch(hl);
|
|
unsigned char u=(a<<4)|(t>>4);
|
|
a=(a&0xf0)|(t&0x0f);
|
|
store(hl,u);
|
|
f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x68,8);
|
|
input(l);
|
|
endinstr;
|
|
|
|
instr(0x69,8);
|
|
tstates+=out(b,c,l);
|
|
endinstr;
|
|
|
|
instr(0x6a,11);
|
|
adchl(hl);
|
|
endinstr;
|
|
|
|
instr(0x6b,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
l=fetch(addr);
|
|
h=fetch(addr+1);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x6c,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x6d,4);
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x6e,4);
|
|
im=1;
|
|
endinstr;
|
|
|
|
instr(0x6f,5);
|
|
{unsigned char t=fetch(hl);
|
|
unsigned char u=(a&0x0f)|(t<<4);
|
|
a=(a&0xf0)|(t>>4);
|
|
store(hl,u);
|
|
f=(f&1)|(a&0xa8)|((!a)<<6)|parity(a);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x70,8);
|
|
{unsigned char x;input(x);}
|
|
endinstr;
|
|
|
|
instr(0x71,8);
|
|
tstates+=out(b,c,0);
|
|
endinstr;
|
|
|
|
instr(0x72,11);
|
|
sbchl(sp);
|
|
endinstr;
|
|
|
|
instr(0x73,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
store2(addr,sp);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x74,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x75,4);
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x76,4);
|
|
im=2;
|
|
endinstr;
|
|
|
|
instr(0x78,8);
|
|
input(a);
|
|
endinstr;
|
|
|
|
instr(0x79,8);
|
|
tstates+=out(b,c,a);
|
|
endinstr;
|
|
|
|
instr(0x7a,11);
|
|
adchl(sp);
|
|
endinstr;
|
|
|
|
instr(0x7b,16);
|
|
{unsigned short addr=fetch2(pc);
|
|
pc+=2;
|
|
sp=fetch2(addr);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0x7c,4);
|
|
neg;
|
|
endinstr;
|
|
|
|
instr(0x7d,4);
|
|
ret;
|
|
endinstr;
|
|
|
|
instr(0x7e,4);
|
|
im=3;
|
|
endinstr;
|
|
|
|
instr(0xa0,12);
|
|
{unsigned char x=fetch(hl);
|
|
store(de,x);
|
|
if(!++l)h++;
|
|
if(!++e)d++;
|
|
if(!c--)b--;
|
|
f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xa1,12);
|
|
{unsigned char carry=cy;
|
|
cpa(fetch(hl));
|
|
if(!++l)h++;
|
|
if(!c--)b--;
|
|
f=(f&0xfa)|carry|(((b|c)>0)<<2);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xa2,12);
|
|
{unsigned short t=in(b,c);
|
|
store(hl,t);
|
|
tstates+=t>>8;
|
|
if(!++l)h++;
|
|
b--;
|
|
f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c)&4);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xa3,12); /* I can't determine the correct flags outcome for the
|
|
block OUT instructions. Spec says that the carry
|
|
flag is left unchanged and N is set to 1, but that
|
|
doesn't seem to be the case... */
|
|
{unsigned char x=fetch(hl);
|
|
tstates+=out(b,c,x);
|
|
if(!++l)h++;
|
|
b--;
|
|
f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xa8,12);
|
|
{unsigned char x=fetch(hl);
|
|
store(de,x);
|
|
if(!l--)h--;
|
|
if(!e--)d--;
|
|
if(!c--)b--;
|
|
f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xa9,12);
|
|
{unsigned char carry=cy;
|
|
cpa(fetch(hl));
|
|
if(!l--)h--;
|
|
if(!c--)b--;
|
|
f=(f&0xfa)|carry|(((b|c)>0)<<2);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xaa,12);
|
|
{unsigned short t=in(b,c);
|
|
store(hl,t);
|
|
tstates+=t>>8;
|
|
if(!l--)h--;
|
|
b--;
|
|
f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c^4)&4);
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xab,12);
|
|
{unsigned char x=fetch(hl);
|
|
tstates+=out(b,c,x);
|
|
if(!l--)h--;
|
|
b--;
|
|
f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
|
|
}
|
|
endinstr;
|
|
|
|
/* Note: the Z80 implements "*R" as "*" followed by JR -2. No reason
|
|
to change this... */
|
|
|
|
instr(0xb0,12);
|
|
{unsigned char x=fetch(hl);
|
|
store(de,x);
|
|
if(!++l)h++;
|
|
if(!++e)d++;
|
|
if(!c--)b--;
|
|
f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
|
|
if(b|c)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xb1,12);
|
|
{unsigned char carry=cy;
|
|
cpa(fetch(hl));
|
|
if(!++l)h++;
|
|
if(!c--)b--;
|
|
f=(f&0xfa)|carry|(((b|c)>0)<<2);
|
|
if((f&0x44)==4)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xb2,12);
|
|
{unsigned short t=in(b,c);
|
|
store(hl,t);
|
|
tstates+=t>>8;
|
|
if(!++l)h++;
|
|
b--;
|
|
f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c)&4);
|
|
if(b)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xb3,12);
|
|
{unsigned char x=fetch(hl);
|
|
tstates+=out(b,c,x);
|
|
if(!++l)h++;
|
|
b--;
|
|
f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
|
|
if(b)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xb8,12);
|
|
{unsigned char x=fetch(hl);
|
|
store(de,x);
|
|
if(!l--)h--;
|
|
if(!e--)d--;
|
|
if(!c--)b--;
|
|
f=(f&0xc1)|(x&0x28)|(((b|c)>0)<<2);
|
|
if(b|c)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xb9,12);
|
|
{unsigned char carry=cy;
|
|
cpa(fetch(hl));
|
|
if(!l--)h--;
|
|
if(!c--)b--;
|
|
f=(f&0xfa)|carry|(((b|c)>0)<<2);
|
|
if((f&0x44)==4)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xba,12);
|
|
{unsigned short t=in(b,c);
|
|
store(hl,t);
|
|
tstates+=t>>8;
|
|
if(!l--)h--;
|
|
b--;
|
|
f=(b&0xa8)|((b>0)<<6)|2|((parity(b)^c^4)&4);
|
|
if(b)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
instr(0xbb,12);
|
|
{unsigned char x=fetch(hl);
|
|
tstates+=out(b,c,x);
|
|
if(!l--)h--;
|
|
b--;
|
|
f=(f&1)|0x12|(b&0xa8)|((b==0)<<6);
|
|
if(b)pc-=2,tstates+=5;
|
|
}
|
|
endinstr;
|
|
|
|
/* save/load patches */
|
|
|
|
instr(0xfc,4);
|
|
#ifdef SZ81 /* Added by Thunor */
|
|
if(!zx80 && hl < 0x8000)
|
|
{
|
|
sdl_load_file(hl,LOAD_FILE_METHOD_NAMEDLOAD);
|
|
}
|
|
else /* if((!zx80 && hl >= 0x8000) || zx80) */
|
|
{
|
|
sdl_load_file(hl,LOAD_FILE_METHOD_SELECTLOAD);
|
|
}
|
|
#else
|
|
load_p(hl);
|
|
#endif
|
|
framewait=1;
|
|
endinstr;
|
|
|
|
instr(0xfd,4);
|
|
#ifdef SZ81 /* Added by Thunor */
|
|
if(zx80)
|
|
{
|
|
sdl_save_file(hl,SAVE_FILE_METHOD_UNNAMEDSAVE);
|
|
}
|
|
else
|
|
{
|
|
sdl_save_file(hl,SAVE_FILE_METHOD_NAMEDSAVE);
|
|
}
|
|
#else
|
|
save_p(hl);
|
|
#endif
|
|
framewait=1;
|
|
endinstr;
|
|
|
|
default: tstates+=4;
|
|
|
|
}}
|
|
|