/* proc8080.cpp - class Processor8080 for emulation of 8080/8085 (20-Oct-2006) Copyright (c) 1994-2006, Alexander Shabarshin (alexander@shabarshin.com) This file is part of OrioniX (testing emulator of computer ORION). OrioniX 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. OrioniX 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 OrioniX; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // 02-Apr-1994 - Begin of implementation // 06-Oct-1996 - First version for Borland-C++ 2.0 // 20-Jun-1997 - Some fixes // 17-Jan-1998 - Port to Watcom-C/C++ 10.0 // 26-Sep-2000 - Some fixed // 17-Oct-2006 - Some modifications for OrioniX #include "proc8080.h" #define M getM() #define BC getBC() #define DE getDE() #define HL getHL() #define PSW getPSW() Processor8080::Processor8080() { PC=SP=0; time=timel=0; INTR=SH_FALSE; HALT=SH_FALSE; par = new SH_BYTE[256]; if(par==NULL) error(2); for(int j=0;j<255;j++) { int p=SH_TRUE; int b=j; for(int i=0;i<8;i++) { if(b&1) { if(p) p=SH_FALSE; else p=SH_TRUE; } b=b>>1; } par[j]=(SH_BYTE)p; } }; void Processor8080::error(int n,SH_BYTE b) { char s[100]; switch(n) { case 0: sprintf(s,"Wrong instruction #%8.8X",b); break; case 1: sprintf(s,"File error"); break; case 2: sprintf(s,"Out of memory"); break; case 3: sprintf(s,"Invalid configuration"); break; default: strcpy(s,"Unknown error"); } printf("\n\nERROR%u: %s !!!\n\n",n,s); exit(1); } unsigned long Processor8080::step(unsigned long t) { SH_WORD aa,w; SH_BYTE bb,cc=0; SH_BIT bi,ok=SH_TRUE; unsigned long l,count=0; time+=t; while(ok) { if(timel>time) break; if(INTR && i_) cc=interruption(); else cc=get(PC++); HALT=SH_FALSE; switch(cc) { case 0x00: // NOP timel+=4; break; case 0x01: // LXI B,## timel+=10; C=get(PC++); B=get(PC++); break; case 0x11: // LXI D,## timel+=10; E=get(PC++); D=get(PC++); break; case 0x21: // LXI H,## timel+=10; L=get(PC++); H=get(PC++); break; case 0x31: // LXI SP,## timel+=10; SP=getw(PC); PC+=2; break; case 0x02: // STAX B timel+=7; put(BC,A); break; case 0x12: // STAX D timel+=7; put(DE,A); break; case 0x22: // SHLD ## timel+=16; aa=getw(PC); PC+=2; put(aa++,L); put(aa,H); break; case 0x32: // STA ## timel+=13; put(getw(PC),A); PC+=2; break; case 0x03: // INX B timel+=5; setBC(BC+1); break; case 0x13: // INX D timel+=5; setDE(DE+1); break; case 0x23: // INX H timel+=5; setHL(HL+1); break; case 0x33: // INX SP timel+=5; SP++; break; case 0x04: // INR B timel+=5; bi=c_; B=plus(B,1); c_=bi; flag_all(B); break; case 0x14: // INR D timel+=5; bi=c_; D=plus(D,1); c_=bi; flag_all(D); break; case 0x24: // INR H timel+=5; bi=c_; H=plus(H,1); c_=bi; flag_all(H); break; case 0x34: // INR M timel+=10; bi=c_; bb=plus(get(HL),1); c_=bi; flag_all(bb); put(HL,bb); break; case 0x05: // DCR B timel+=5; bi=c_; B=minus(B,1); c_=bi; flag_all(B); break; case 0x15: // DCR D timel+=5; bi=c_; D=minus(D,1); c_=bi; flag_all(D); break; case 0x25: // DCR H timel+=5; bi=c_; H=minus(H,1); c_=bi; flag_all(H); break; case 0x35: // DCR M timel+=10; bi=c_; bb=minus(get(HL),1); c_=bi; flag_all(bb); put(HL,bb); break; case 0x06: // MVI B,# timel+=7; B=get(PC++); break; case 0x16: // MVI D,# timel+=7; D=get(PC++); break; case 0x26: // MVI H,# timel+=7; H=get(PC++); break; case 0x36: // MVI M,# timel+=10; put(HL,get(PC++)); break; case 0x07: // RLC timel+=4; w=A; w<<=1; c_=(w&0x0100)>>8; A=(w&0x00FE)|c_; break; case 0x17: // RAL timel+=4; w=A; w<<=1; A=(w&0x00FE)|c_; c_=(w&0x0100)>>8; break; case 0x27: // DAA timel+=4; if(A>9) A+=6; //??? break; case 0x37: // STC timel+=4; c_=SH_TRUE; break; case 0x0B: // DCX B timel+=5; setBC(BC-1); break; case 0x1B: // DCX D timel+=5; setDE(DE-1); break; case 0x2B: // DCX H timel+=5; setHL(HL-1); break; case 0x3B: // DCX SP timel+=5; SP--; break; case 0x0C: // INR C timel+=5; bi=c_; C=plus(C,1); c_=bi; flag_all(C); break; case 0x1C: // INR E timel+=5; bi=c_; E=plus(E,1); c_=bi; flag_all(E); break; case 0x2C: // INR L timel+=5; bi=c_; L=plus(L,1); c_=bi; flag_all(L); break; case 0x3C: // INR A timel+=5; bi=c_; A=plus(A,1); c_=bi; flag_all(A); break; case 0x0D: // DCR C timel+=5; bi=c_; C=minus(C,1); c_=bi; flag_all(C); break; case 0x1D: // DCR E timel+=5; bi=c_; E=minus(E,1); c_=bi; flag_all(E); break; case 0x2D: // DCR L timel+=5; bi=c_; L=minus(L,1); c_=bi; flag_all(L); break; case 0x3D: // DCR A timel+=5; bi=c_; A=minus(A,1); c_=bi; flag_all(A); break; case 0x0E: // MVI C,# timel+=7; C=get(PC++); break; case 0x1E: // MVI E,# timel+=7; E=get(PC++); break; case 0x2E: // MVI L,# timel+=7; L=get(PC++); break; case 0x3E: // MVI A,# timel+=7; A=get(PC++); break; case 0x0F: // RRC timel+=4; w=A; w<<=7; c_=(w&0x0080)>>7; A=((w&0x7F00)>>8)|(c_<<7); break; case 0x1F: // RAR timel+=4; w=A; w<<=7; A=((w&0x7F00)>>8)|(c_<<7); c_=(w&0x0080)>>7; break; case 0x2F: // CMA timel+=4; A=~A; break; case 0x3F: // CMC timel+=4; if(c_) c_=SH_FALSE; else c_=SH_TRUE; break; case 0x0A: // LDAX B timel+=7; A=get(BC); break; case 0x1A: // LDAX D timel+=7; A=get(DE); break; case 0x2A: // LHLD ## timel+=16; aa=getw(PC); PC+=2; L=get(aa++); H=get(aa); break; case 0x3A: // LDA ## timel+=13; aa=getw(PC); PC+=2; A=get(aa); break; case 0x09: // DAD B timel+=10; l=HL+BC; if(l>0xFFFF) c_=1; else c_=0; w=l&0xFFFF; setHL(w); break; case 0x19: // DAD D timel+=10; l=HL+DE; if(l>0xFFFF) c_=1; else c_=0; w=l&0xFFFF; setHL(w); break; case 0x29: // DAD H timel+=10; l=HL+HL; if(l>0xFFFF) c_=1; else c_=0; w=l&0xFFFF; setHL(w); break; case 0x39: // DAD SP timel+=10; l=HL+SP; if(l>0xFFFF) c_=1; else c_=0; w=l&0xFFFF; setHL(w); break; case 0x40: // MOV B,B timel+=5; B=B;break; case 0x41: // MOV B,C timel+=5; B=C;break; case 0x42: // MOV B,D timel+=5; B=D;break; case 0x43: // MOV B,E timel+=5; B=E;break; case 0x44: // MOV B,H timel+=5; B=H;break; case 0x45: // MOV B,L timel+=5; B=L;break; case 0x46: // MOV B,M timel+=7; B=M;break; case 0x47: // MOV B,A timel+=5; B=A;break; case 0x48: // MOV C,B timel+=5; C=B;break; case 0x49: // MOV C,C timel+=5; C=C;break; case 0x4A: // MOV C,D timel+=5; C=D;break; case 0x4B: // MOV C,E timel+=5; C=E;break; case 0x4C: // MOV C,H timel+=5; C=H;break; case 0x4D: // MOV C,L timel+=5; C=L;break; case 0x4E: // MOV C,M timel+=7; C=M;break; case 0x4F: // MOV C,A timel+=5; C=A;break; case 0x50: // MOV D,B timel+=5; D=B;break; case 0x51: // MOV D,C timel+=5; D=C;break; case 0x52: // MOV D,D timel+=5; D=D;break; case 0x53: // MOV D,E timel+=5; D=E;break; case 0x54: // MOV D,H timel+=5; D=H;break; case 0x55: // MOV D,L timel+=5; D=L;break; case 0x56: // MOV D,M timel+=7; D=M;break; case 0x57: // MOV D,A timel+=5; D=A;break; case 0x58: // MOV E,B timel+=5; E=B;break; case 0x59: // MOV E,C timel+=5; E=C;break; case 0x5A: // MOV E,D timel+=5; E=D;break; case 0x5B: // MOV E,E timel+=5; E=E;break; case 0x5C: // MOV E,H timel+=5; E=H;break; case 0x5D: // MOV E,L timel+=5; E=L;break; case 0x5E: // MOV E,M timel+=7; E=M;break; case 0x5F: // MOV E,A timel+=5; E=A;break; case 0x60: // MOV H,B timel+=5; H=B;break; case 0x61: // MOV H,C timel+=5; H=C;break; case 0x62: // MOV H,D timel+=5; H=D;break; case 0x63: // MOV H,E timel+=5; H=E;break; case 0x64: // MOV H,H timel+=5; H=H;break; case 0x65: // MOV H,L timel+=5; H=L;break; case 0x66: // MOV H,M timel+=7; H=M;break; case 0x67: // MOV H,A timel+=5; H=A;break; case 0x68: // MOV L,B timel+=5; L=B;break; case 0x69: // MOV L,C timel+=5; L=C;break; case 0x6A: // MOV L,D timel+=5; L=D;break; case 0x6B: // MOV L,E timel+=5; L=E;break; case 0x6C: // MOV L,H timel+=5; L=H;break; case 0x6D: // MOV L,L timel+=5; L=L;break; case 0x6E: // MOV L,M timel+=7; L=M;break; case 0x6F: // MOV L,A timel+=5; L=A;break; case 0x70: // MOV M,B timel+=7; put(HL,B);break; case 0x71: // MOV M,C timel+=7; put(HL,C);break; case 0x72: // MOV M,D timel+=7; put(HL,D);break; case 0x73: // MOV M,E timel+=7; put(HL,E);break; case 0x74: // MOV M,H timel+=7; put(HL,H);break; case 0x75: // MOV M,L timel+=7; put(HL,L);break; case 0x76: // HLT timel+=7; HALT=SH_TRUE;break; case 0x77: // MOV M,A timel+=7; put(HL,A);break; case 0x78: // MOV A,B timel+=5; A=B;break; case 0x79: // MOV A,C timel+=5; A=C;break; case 0x7A: // MOV A,D timel+=5; A=D;break; case 0x7B: // MOV A,E timel+=5; A=E;break; case 0x7C: // MOV A,H timel+=5; A=H;break; case 0x7D: // MOV A,L timel+=5; A=L;break; case 0x7E: // MOV A,M timel+=7; A=M;break; case 0x7F: // MOV A,A timel+=5; A=A;break; case 0x80: // ADD B timel+=4; A=plus(A,B); flag_all(A); break; case 0x81: // ADD C timel+=4; A=plus(A,C); flag_all(A); break; case 0x82: // ADD D timel+=4; A=plus(A,D); flag_all(A); break; case 0x83: // ADD E timel+=4; A=plus(A,E); flag_all(A); break; case 0x84: // ADD H timel+=4; A=plus(A,H); flag_all(A); break; case 0x85: // ADD L timel+=4; A=plus(A,L); flag_all(A); break; case 0x86: // ADD M timel+=7; A=plus(A,M); flag_all(A); break; case 0x87: // ADD A timel+=4; A=plus(A,A); flag_all(A); break; case 0xC6: // ADI # timel+=7; bb=get(PC++); A=plus(A,bb); flag_all(A); break; case 0x88: // ADC B timel+=4; A=plus(A,B,c_); flag_all(A); break; case 0x89: // ADC C timel+=4; A=plus(A,C,c_); flag_all(A); break; case 0x8A: // ADC D timel+=4; A=plus(A,D,c_); flag_all(A); break; case 0x8B: // ADC E timel+=4; A=plus(A,E,c_); flag_all(A); break; case 0x8C: // ADC H timel+=4; A=plus(A,H,c_); flag_all(A); break; case 0x8D: // ADC L timel+=4; A=plus(A,L,c_); flag_all(A); break; case 0x8E: // ADC M timel+=7; A=plus(A,M,c_); flag_all(A); break; case 0x8F: // ADC A timel+=4; A=plus(A,A,c_); flag_all(A); break; case 0xCE: // ACI # timel+=7; bb=get(PC++); A=plus(A,bb,c_); flag_all(A); break; case 0x90: // SUB B timel+=4; A=minus(A,B); flag_all(A); break; case 0x91: // SUB C timel+=4; A=minus(A,C); flag_all(A); break; case 0x92: // SUB D timel+=4; A=minus(A,D); flag_all(A); break; case 0x93: // SUB E timel+=4; A=minus(A,E); flag_all(A); break; case 0x94: // SUB H timel+=4; A=minus(A,H); flag_all(A); break; case 0x95: // SUB L timel+=4; A=minus(A,L); flag_all(A); break; case 0x96: // SUB M timel+=7; A=minus(A,M); flag_all(A); break; case 0x97: // SUB A timel+=4; A=minus(A,A); flag_all(A); break; case 0xD6: // SUI # timel+=7; bb=get(PC++); A=minus(A,bb); flag_all(A); break; case 0x98: // SBB B timel+=4; A=minus(A,B,c_); flag_all(A); break; case 0x99: // SBB C timel+=4; A=minus(A,C,c_); flag_all(A); break; case 0x9A: // SBB D timel+=4; A=minus(A,D,c_); flag_all(A); break; case 0x9B: // SBB E timel+=4; A=minus(A,E,c_); flag_all(A); break; case 0x9C: // SBB H timel+=4; A=minus(A,H,c_); flag_all(A); break; case 0x9D: // SBB L timel+=4; A=minus(A,L,c_); flag_all(A); break; case 0x9E: // SBB M timel+=7; A=minus(A,M,c_); flag_all(A); break; case 0x9F: // SBB A timel+=4; A=minus(A,A,c_); flag_all(A); break; case 0xDE: // SBI # timel+=7; bb=get(PC++); A=minus(A,bb,c_); flag_all(A); break; case 0xA0: // ANA B timel+=4; A&=B; c_=SH_TRUE; a_=SH_TRUE; flag_all(A); break; case 0xA1: // ANA C timel+=4; A&=C; c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xA2: // ANA D timel+=4; A&=D; c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xA3: // ANA E timel+=4; A&=E; c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xA4: // ANA H timel+=4; A&=H; c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xA5: // ANA L timel+=4; A&=L; c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xA6: // ANA M timel+=7; A&=M; c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xA7: // ANA A timel+=4; A&=A; c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xE6: // ANI # timel+=7; A&=get(PC++); c_=SH_FALSE; a_=SH_TRUE; flag_all(A); break; case 0xA8: // XRA B timel+=4; A^=B; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xA9: // XRA C timel+=4; A^=C; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xAA: // XRA D timel+=4; A^=D; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xAB: // XRA E timel+=4; A^=E; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xAC: // XRA H timel+=4; A^=H; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xAD: // XRA L timel+=4; A^=L; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xAE: // XRA M timel+=7; A^=M; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xAF: // XRA A timel+=4; A^=A; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xEE: // XRI # timel+=7; A^=get(PC++); c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB0: // ORA B timel+=4; A|=B; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB1: // ORA C timel+=4; A|=C; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB2: // ORA D timel+=4; A|=D; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB3: // ORA E timel+=4; A|=E; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB4: // ORA H timel+=4; A|=H; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB5: // ORA L timel+=4; A|=L; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB6: // ORA M timel+=7; A|=M; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB7: // ORA A timel+=4; A|=A; c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xF6: // ORI # timel+=7; A|=get(PC++); c_=SH_FALSE; a_=SH_FALSE; flag_all(A); break; case 0xB8: // CMP B timel+=4; bb=minus(A,B); flag_all(bb); break; case 0xB9: // CMP C timel+=4; bb=minus(A,C); flag_all(bb); break; case 0xBA: // CMP D timel+=4; bb=minus(A,D); flag_all(bb); break; case 0xBB: // CMP E timel+=4; bb=minus(A,E); flag_all(bb); break; case 0xBC: // CMP H timel+=4; bb=minus(A,H); flag_all(bb); break; case 0xBD: // CMP L timel+=4; bb=minus(A,L); flag_all(bb); break; case 0xBE: // CMP M timel+=7; bb=minus(A,M); flag_all(bb); break; case 0xBF: // CMP A timel+=4; bb=minus(A,A); flag_all(bb); break; case 0xFE: // CPI # timel+=7; bb=minus(A,get(PC++)); flag_all(bb); break; case 0xC0: // RNZ if(!z_){timel+=11;ret();} else timel+=5; break; case 0xD0: // RNC if(!c_){timel+=11;ret();} else timel+=5; break; case 0xE0: // RPO if(!p_){timel+=11;ret();} else timel+=5; break; case 0xF0: // RP if(!s_){timel+=11;ret();} else timel+=5; break; case 0xC8: // RZ if(z_){timel+=11;ret();} else timel+=5; break; case 0xD8: // RC if(c_){timel+=11;ret();} else timel+=5; break; case 0xE8: // RPE if(p_){timel+=11;ret();} else timel+=5; break; case 0xF8: // RM if(s_){timel+=11;ret();} else timel+=5; break; case 0xC2: // JNZ timel+=10; if(!z_)PC=getw(PC); else PC+=2; break; case 0xD2: // JNC timel+=10; if(!c_)PC=getw(PC); else PC+=2; break; case 0xE2: // JPO timel+=10; if(!p_)PC=getw(PC); else PC+=2; break; case 0xF2: // JP timel+=10; if(!s_)PC=getw(PC); else PC+=2; break; case 0xCA: // JZ timel+=10; if(z_)PC=getw(PC); else PC+=2; break; case 0xDA: // JC timel+=10; if(c_)PC=getw(PC); else PC+=2; break; case 0xEA: // JPE timel+=10; if(p_)PC=getw(PC); else PC+=2; break; case 0xFA: // JM timel+=10; if(s_)PC=getw(PC); else PC+=2; break; case 0xC4: // CNZ if(!z_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xD4: // CNC if(!c_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xE4: // CPO if(!p_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xF4: // CP if(!s_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xCC: // CZ if(z_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xDC: // CC if(c_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xEC: // CPE if(p_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xFC: // CM if(s_) { timel+=17; aa=getw(PC); PC+=2; call(aa); } else { timel+=11; PC+=2; } break; case 0xC7: // RST 0 timel+=11; call(0x0000); break; case 0xCF: // RST 1 timel+=11; call(0x0008); break; case 0xD7: // RST 2 timel+=11; call(0x0010); break; case 0xDF: // RST 3 timel+=11; call(0x0018); break; case 0xE7: // RST 4 timel+=11; call(0x0020); break; case 0xEF: // RST 5 timel+=11; call(0x0028); break; case 0xF7: // RST 6 timel+=11; call(0x0030); break; case 0xFF: // RST 7 timel+=11; call(0x0038); break; case 0xC1: // POP B timel+=10; setBC(getw(SP)); SP+=2; break; case 0xD1: // POP D timel+=10; setDE(getw(SP)); SP+=2; break; case 0xE1: // POP H timel+=10; setHL(getw(SP)); SP+=2; break; case 0xF1: // POP PSW timel+=10; setPSW(getw(SP)); SP+=2; break; case 0xC5: // PUSH B timel+=11; SP-=2; putw(SP,BC); break; case 0xD5: // PUSH D timel+=11; SP-=2; putw(SP,DE); break; case 0xE5: // PUSH H timel+=11; SP-=2; putw(SP,HL); break; case 0xF5: // PUSH PSW timel+=11; SP-=2; putw(SP,PSW); break; case 0xC3: // JMP timel+=10; PC=getw(PC); break; case 0xD3: // OUT # timel+=10; outp(get(PC++),A); break; case 0xDB: // IN # timel+=10; A=inp(get(PC++)); break; case 0xE3: // XTHL timel+=18; w=getw(SP); putw(SP,HL); setHL(w); break; case 0xEB: // XCHG timel+=4; w=DE; setDE(HL); setHL(w); break; case 0xF3: // DI timel+=4; i_=SH_FALSE; break; case 0xFB: // EI timel+=4; i_=SH_TRUE; break; case 0xC9: // RET timel+=10; ret(); break; case 0xE9: // PCHL timel+=5; PC=HL; break; case 0xF9: // SPHL timel+=5; SP=HL; break; case 0xCD: // CALL ## timel+=17; aa=getw(PC); PC+=2; call(aa); break; default: ok=SH_FALSE; } if(aux(cc,ok)) ok=SH_TRUE; if(!ok) error(0,cc); else count++; } return count; }