MCUME/MCUME_teensy41/teensy81/edops.h

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