/* Copyright holders: Sarah Walker, Tenshi see COPYING for more details */ //1B64 - Vid_SetMode (Vid_Vesa.c) //6689c - CONS_Printf /*SHR AX,1 4 clocks - fetch opcode 4 clocks - fetch mod/rm 2 clocks - execute 2 clocks - fetch opcode 1 2 clocks - fetch opcode 2 4 clocks - fetch mod/rm 2 clocks - fetch opcode 1 2 clocks - execute 2 clocks - fetch opcode 2 etc*/ #include #include "ibm.h" #include "cpu.h" #include "keyboard.h" #include "mem.h" #include "nmi.h" #include "pic.h" #include "timer.h" #include "x86.h" int xt_cpu_multi; int nmi = 0; int nextcyc=0; int cycdiff; int is8086=0; int memcycs; int nopageerrors=0; void FETCHCOMPLETE(); uint8_t readmembl(uint32_t addr); void writemembl(uint32_t addr, uint8_t val); uint16_t readmemwl(uint32_t seg, uint32_t addr); void writememwl(uint32_t seg, uint32_t addr, uint16_t val); uint32_t readmemll(uint32_t seg, uint32_t addr); void writememll(uint32_t seg, uint32_t addr, uint32_t val); #undef readmemb #undef readmemw uint8_t readmemb(uint32_t a) { if (a!=(cs+cpu_state.pc)) memcycs+=4; if (readlookup2[(a)>>12]==-1) return readmembl(a); else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); } uint8_t readmembf(uint32_t a) { if (readlookup2[(a)>>12]==-1) return readmembl(a); else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); } uint16_t readmemw(uint32_t s, uint16_t a) { if (a!=(cs+cpu_state.pc)) memcycs+=(8>>is8086); if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s,a); else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a); } void refreshread() { /*pclog("Refreshread\n"); */FETCHCOMPLETE(); memcycs+=4; } #undef fetchea #define fetchea() { rmdat=FETCH(); \ cpu_reg=(rmdat>>3)&7; \ cpu_mod=(rmdat>>6)&3; \ cpu_rm=rmdat&7; \ if (cpu_mod!=3) fetcheal(); } void writemembl(uint32_t addr, uint8_t val); void writememb(uint32_t a, uint8_t v) { memcycs+=4; if (writelookup2[(a)>>12]==-1) writemembl(a,v); else *(uint8_t *)(writelookup2[a >> 12] + a) = v; } void writememwl(uint32_t seg, uint32_t addr, uint16_t val); void writememw(uint32_t s, uint32_t a, uint16_t v) { memcycs+=(8>>is8086); if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v; } void writememll(uint32_t seg, uint32_t addr, uint32_t val); void writememl(uint32_t s, uint32_t a, uint32_t v) { if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s,a,v); else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v; } void dumpregs(); uint16_t oldcs; int oldcpl; int tempc; uint8_t opcode; int times=0; uint16_t pc2,pc3; int noint=0; int output=0; int shadowbios=0; int ins=0; //#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a)) int ssegs; int fetchcycles=0,memcycs,fetchclocks; uint8_t prefetchqueue[6]; uint16_t prefetchpc; int prefetchw=0; inline uint8_t FETCH() { uint8_t temp; /* temp=prefetchqueue[0]; prefetchqueue[0]=prefetchqueue[1]; prefetchqueue[1]=prefetchqueue[2]; prefetchqueue[2]=prefetchqueue[3]; prefetchqueue[3]=prefetchqueue[4]; prefetchqueue[4]=prefetchqueue[5]; if (prefetchw<=((is8086)?4:3)) { prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++; if (is8086 && (prefetchpc&1)) { prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++; } }*/ // uint8_t temp=readmemb(cs+pc); // if (output) printf("FETCH %04X %i\n",pc,fetchcycles); if (prefetchw==0) //(fetchcycles<4) { cycles-=(4-(fetchcycles&3)); fetchclocks+=(4-(fetchcycles&3)); fetchcycles=4; temp=readmembf(cs+cpu_state.pc); prefetchpc = cpu_state.pc = cpu_state.pc + 1; // if (output) printf(" FETCH %04X:%04X %02X %04X %04X %i\n",CS,pc-1,temp,pc,prefetchpc,prefetchw); if (is8086 && (cpu_state.pc&1)) { prefetchqueue[0]=readmembf(cs+cpu_state.pc); // if (output) printf(" PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]); prefetchpc++; prefetchw++; } } else { temp=prefetchqueue[0]; prefetchqueue[0]=prefetchqueue[1]; prefetchqueue[1]=prefetchqueue[2]; prefetchqueue[2]=prefetchqueue[3]; prefetchqueue[3]=prefetchqueue[4]; prefetchqueue[4]=prefetchqueue[5]; prefetchw--; // if (output) printf("PREFETCH %04X:%04X %02X %04X %04X %i\n",CS,pc,temp,pc,prefetchpc,prefetchw); fetchcycles-=4; // fetchclocks+=4; cpu_state.pc++; } // if (output) printf("%i\n",fetchcycles); return temp; } inline void FETCHADD(int c) { int d; // if (output) printf("FETCHADD %i\n",c); if (c<0) return; if (prefetchw>((is8086)?4:3)) return; d=c+(fetchcycles&3); while (d>3 && prefetchw<((is8086)?6:4)) { d-=4; if (is8086 && !(prefetchpc&1)) { prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); // printf("PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]); prefetchpc++; prefetchw++; } if (prefetchw<6) { prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); // printf("PREFETCHED from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]); prefetchpc++; prefetchw++; } } fetchcycles+=c; if (fetchcycles>16) fetchcycles=16; // if (fetchcycles>24) fetchcycles=24; } void FETCHCOMPLETE() { // pclog("Fetchcomplete %i %i %i\n",fetchcycles&3,fetchcycles,prefetchw); if (!(fetchcycles&3)) return; if (prefetchw>((is8086)?4:3)) return; if (!prefetchw) nextcyc=(4-(fetchcycles&3)); cycles-=(4-(fetchcycles&3)); fetchclocks+=(4-(fetchcycles&3)); if (is8086 && !(prefetchpc&1)) { prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); // printf("PREFETCHEDc from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]); prefetchpc++; prefetchw++; } if (prefetchw<6) { prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); // printf("PREFETCHEDc from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]); prefetchpc++; prefetchw++; } fetchcycles+=(4-(fetchcycles&3)); } inline void FETCHCLEAR() { /* int c; fetchcycles=0; prefetchpc=pc; if (is8086 && (prefetchpc&1)) cycles-=4; for (c=0;c<((is8086)?6:4);c++) { prefetchqueue[c]=readmembf(cs+prefetchpc); if (!is8086 || !(prefetchpc&1)) cycles-=4; prefetchpc++; } prefetchw=(is8086)?6:4;*/ // fetchcycles=0; prefetchpc=cpu_state.pc; prefetchw=0; memcycs=cycdiff-cycles; fetchclocks=0; // memcycs=cycles; /* prefetchqueue[0]=readmembf(cs+prefetchpc); prefetchpc++; prefetchw=1; if (is8086 && prefetchpc&1) { prefetchqueue[1]=readmembf(cs+prefetchpc); prefetchpc++; }*/ } static uint16_t getword() { uint8_t temp=FETCH(); return temp|(FETCH()<<8); } /*EA calculation*/ /*R/M - bits 0-2 - R/M bits 3-5 - Reg bits 6-7 - mod From 386 programmers manual : r8(/r) AL CL DL BL AH CH DH BH r16(/r) AX CX DX BX SP BP SI DI r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI /digit (Opcode) 0 1 2 3 4 5 6 7 REG = 000 001 010 011 100 101 110 111 ÚÄÄÄAddress disp8 denotes an 8-bit displacement following the ModR/M byte, to be sign-extended and added to the index. disp16 denotes a 16-bit displacement following the ModR/M byte, to be added to the index. Default segment register is SS for the effective addresses containing a BP index, DS for other effective addresses. ÄÄ¿ ÚMod R/M¿ ÚÄÄÄÄÄÄÄÄModR/M Values in HexadecimalÄÄÄÄÄÄÄÄ¿ [BX + SI] 000 00 08 10 18 20 28 30 38 [BX + DI] 001 01 09 11 19 21 29 31 39 [BP + SI] 010 02 0A 12 1A 22 2A 32 3A [BP + DI] 011 03 0B 13 1B 23 2B 33 3B [SI] 00 100 04 0C 14 1C 24 2C 34 3C [DI] 101 05 0D 15 1D 25 2D 35 3D disp16 110 06 0E 16 1E 26 2E 36 3E [BX] 111 07 0F 17 1F 27 2F 37 3F [BX+SI]+disp8 000 40 48 50 58 60 68 70 78 [BX+DI]+disp8 001 41 49 51 59 61 69 71 79 [BP+SI]+disp8 010 42 4A 52 5A 62 6A 72 7A [BP+DI]+disp8 011 43 4B 53 5B 63 6B 73 7B [SI]+disp8 01 100 44 4C 54 5C 64 6C 74 7C [DI]+disp8 101 45 4D 55 5D 65 6D 75 7D [BP]+disp8 110 46 4E 56 5E 66 6E 76 7E [BX]+disp8 111 47 4F 57 5F 67 6F 77 7F [BX+SI]+disp16 000 80 88 90 98 A0 A8 B0 B8 [BX+DI]+disp16 001 81 89 91 99 A1 A9 B1 B9 [BX+SI]+disp16 010 82 8A 92 9A A2 AA B2 BA [BX+DI]+disp16 011 83 8B 93 9B A3 AB B3 BB [SI]+disp16 10 100 84 8C 94 9C A4 AC B4 BC [DI]+disp16 101 85 8D 95 9D A5 AD B5 BD [BP]+disp16 110 86 8E 96 9E A6 AE B6 BE [BX]+disp16 111 87 8F 97 9F A7 AF B7 BF EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8 ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9 EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF mod = 11 - register 10 - address + 16 bit displacement 01 - address + 8 bit displacement 00 - address reg = If mod=11, (depending on data size, 16 bits/8 bits, 32 bits=extend 16 bit registers) 0=AX/AL 1=CX/CL 2=DX/DL 3=BX/BL 4=SP/AH 5=BP/CH 6=SI/DH 7=DI/BH Otherwise, LSB selects SI/DI (0=SI), NMSB selects BX/BP (0=BX), and MSB selects whether BX/BP are used at all (0=used). mod=00 is an exception though 6=16 bit displacement only 7=[BX] Usage varies with instructions. MOV AL,BL has ModR/M as C3, for example. mod=11, reg=0, r/m=3 MOV uses reg as dest, and r/m as src. reg 0 is AL, reg 3 is BL If BP or SP are in address calc, seg is SS, else DS */ int cycles=0; uint32_t easeg,eaaddr; int rmdat; uint16_t zero=0; uint16_t *mod1add[2][8]; uint32_t *mod1seg[8]; int slowrm[8]; void makemod1table() { mod1add[0][0]=&BX; mod1add[0][1]=&BX; mod1add[0][2]=&BP; mod1add[0][3]=&BP; mod1add[0][4]=&SI; mod1add[0][5]=&DI; mod1add[0][6]=&BP; mod1add[0][7]=&BX; mod1add[1][0]=&SI; mod1add[1][1]=&DI; mod1add[1][2]=&SI; mod1add[1][3]=&DI; mod1add[1][4]=&zero; mod1add[1][5]=&zero; mod1add[1][6]=&zero; mod1add[1][7]=&zero; slowrm[0]=0; slowrm[1]=1; slowrm[2]=1; slowrm[3]=0; mod1seg[0]=&ds; mod1seg[1]=&ds; mod1seg[2]=&ss; mod1seg[3]=&ss; mod1seg[4]=&ds; mod1seg[5]=&ds; mod1seg[6]=&ss; mod1seg[7]=&ds; } static void fetcheal() { if (!cpu_mod && cpu_rm==6) { eaaddr=getword(); easeg=ds; FETCHADD(6); } else { switch (cpu_mod) { case 0: eaaddr=0; if (cpu_rm&4) FETCHADD(5); else FETCHADD(7+slowrm[cpu_rm]); break; case 1: eaaddr=(uint16_t)(int8_t)FETCH(); if (cpu_rm&4) FETCHADD(9); else FETCHADD(11+slowrm[cpu_rm]); break; case 2: eaaddr=getword(); if (cpu_rm&4) FETCHADD(9); else FETCHADD(11+slowrm[cpu_rm]); break; case 3: if (!(cpu_rm&4)) FETCHADD(2+slowrm[cpu_rm]); return; } eaaddr+=(*mod1add[0][cpu_rm])+(*mod1add[1][cpu_rm]); easeg=*mod1seg[cpu_rm]; eaaddr&=0xFFFF; } cpu_state.last_ea = eaaddr; } static inline uint8_t geteab() { if (cpu_mod == 3) return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l; return readmemb(easeg+eaaddr); } static inline uint16_t geteaw() { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; // if (output==3) printf("GETEAW %04X:%08X\n",easeg,eaaddr); return readmemw(easeg,eaaddr); } static inline uint16_t geteaw2() { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; // printf("Getting addr from %04X:%04X %05X\n",easeg,eaaddr+2,easeg+eaaddr+2); return readmemw(easeg,(eaaddr+2)&0xFFFF); } static inline void seteab(uint8_t val) { if (cpu_mod == 3) { if (cpu_rm & 4) cpu_state.regs[cpu_rm & 3].b.h = val; else cpu_state.regs[cpu_rm & 3].b.l = val; } else { writememb(easeg+eaaddr,val); } } static inline void seteaw(uint16_t val) { if (cpu_mod == 3) cpu_state.regs[cpu_rm].w = val; else { writememw(easeg,eaaddr,val); // writememb(easeg+eaaddr+1,val>>8); } } #define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) #define setr8(r,v) if (r & 4) cpu_state.regs[r & 3].b.h = v; \ else cpu_state.regs[r & 3].b.l = v; /*Flags*/ uint8_t znptable8[256]; uint16_t znptable16[65536]; void makeznptable() { int c,d; for (c=0;c<256;c++) { d=0; if (c&1) d++; if (c&2) d++; if (c&4) d++; if (c&8) d++; if (c&16) d++; if (c&32) d++; if (c&64) d++; if (c&128) d++; if (d&1) znptable8[c]=0; else znptable8[c]=P_FLAG; if (c == 0xb1) pclog("znp8 b1 = %i %02X\n", d, znptable8[c]); if (!c) znptable8[c]|=Z_FLAG; if (c&0x80) znptable8[c]|=N_FLAG; } for (c=0;c<65536;c++) { d=0; if (c&1) d++; if (c&2) d++; if (c&4) d++; if (c&8) d++; if (c&16) d++; if (c&32) d++; if (c&64) d++; if (c&128) d++; if (d&1) znptable16[c]=0; else znptable16[c]=P_FLAG; if (c == 0xb1) pclog("znp16 b1 = %i %02X\n", d, znptable16[c]); if (c == 0x65b1) pclog("znp16 65b1 = %i %02X\n", d, znptable16[c]); if (!c) znptable16[c]|=Z_FLAG; if (c&0x8000) znptable16[c]|=N_FLAG; } // makemod1table(); } int timetolive=0; extern uint32_t oldcs2; extern uint32_t oldpc2; int indump = 0; void dumpregs() { int c,d=0,e=0,ff; #ifndef RELEASE_BUILD FILE *f; if (indump) return; indump = 1; // return; output=0; // return; // savenvr(); // return; chdir(pcempath); nopageerrors=1; /* f=fopen("rram3.dmp","wb"); for (c=0;c<0x8000000;c++) putc(readmemb(c+0x10000000),f); fclose(f);*/ f=fopen("ram.dmp","wb"); fwrite(ram,mem_size*1024,1,f); fclose(f); /* pclog("Dumping rram5.dmp\n"); f=fopen("rram5.dmp","wb"); for (c=0;c<0x1000000;c++) putc(readmemb(c+0x10150000),f); fclose(f);*/ pclog("Dumping rram.dmp\n"); f=fopen("rram.dmp","wb"); for (c=0;c<0x1000000;c++) putc(readmemb(c),f); fclose(f); /* f=fopen("rram2.dmp","wb"); for (c=0;c<0x100000;c++) putc(readmemb(c+0xbff00000),f); fclose(f); f = fopen("stack.dmp","wb"); for (c = 0; c < 0x6000; c++) putc(readmemb(c+0xFFDFA000), f); fclose(f); f = fopen("tempx.dmp","wb"); for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFC816000), f); fclose(f); f = fopen("tempx2.dmp","wb"); for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFDEF5000), f); fclose(f);*/ pclog("Dumping rram4.dmp\n"); f=fopen("rram4.dmp","wb"); for (c=0;c<0x0050000;c++) { abrt = 0; putc(readmemb386l(0,c+0x80000000),f); } fclose(f); pclog("Dumping done\n"); /* f=fopen("rram6.dmp","wb"); for (c=0;c<0x1000000;c++) putc(readmemb(c+0xBF000000),f); fclose(f);*/ /* f=fopen("ram6.bin","wb"); fwrite(ram+0x10100,0xA000,1,f); fclose(f); f=fopen("boot.bin","wb"); fwrite(ram+0x7C00,0x200,1,f); fclose(f); f=fopen("ram7.bin","wb"); fwrite(ram+0x11100,0x2000,1,f); fclose(f); f=fopen("ram8.bin","wb"); fwrite(ram+0x3D210,0x200,1,f); fclose(f); */ /* f=fopen("bios.dmp","wb"); fwrite(rom,0x20000,1,f); fclose(f);*/ /* f=fopen("kernel.dmp","wb"); for (c=0;c<0x200000;c++) putc(readmemb(c+0xC0000000),f); fclose(f);*/ /* f=fopen("rram.dmp","wb"); for (c=0;c<0x1500000;c++) putc(readmemb(c),f); fclose(f); if (!times) { f=fopen("thing.dmp","wb"); fwrite(ram+0x11E50,0x1000,1,f); fclose(f); }*/ #endif if (is386) printf("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); else printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); printf("%04X:%04X %04X:%04X\n",oldcs,oldpc, oldcs2, oldpc2); printf("%i ins\n",ins); if (is386) printf("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); else printf("In %s mode\n",(msw&1)?"protected":"real"); printf("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); if (is386) { printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); } printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); printf("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); printf("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); printf("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); printf("TR : base=%06X limit=%04X\n", tr.base, tr.limit); if (is386) { printf("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); printf("CR0=%08X CR2=%08X CR3=%08X\n",cr0,cr2,cr3); } printf("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum); for (c=0;c<1024*1024;c++) { if (readlookup2[c]!=0xFFFFFFFF) d++; if (writelookup2[c]!=0xFFFFFFFF) e++; } printf("Entries in readlookup : %i writelookup : %i\n",d,e); x87_dumpregs(); indump = 0; } int resets = 0; int x86_was_reset = 0; void resetx86() { pclog("x86 reset\n"); resets++; ins = 0; use32=0; stack32=0; // i86_Reset(); // cs=0xFFFF0; cpu_state.pc=0; msw=0; if (is486) cr0 = 1 << 30; else cr0 = 0; cr4 = 0; eflags=0; cgate32=0; loadcs(0xFFFF); rammask=0xFFFFFFFF; idt.base = 0; flags=2; makeznptable(); resetreadlookup(); makemod1table(); resetmcr(); FETCHCLEAR(); x87_reset(); cpu_set_edx(); ESP=0; mmu_perm=4; memset(inscounts, 0, sizeof(inscounts)); x86seg_reset(); codegen_reset(); x86_was_reset = 1; } void softresetx86() { // dumpregs(); // exit(-1); use32=0; stack32=0; // i86_Reset(); // cs=0xFFFF0; cpu_state.pc=0; msw=0; cr0=0; cr4 = 0; eflags=0; cgate32=0; loadcs(0xFFFF); //rammask=0xFFFFFFFF; flags=2; idt.base = 0; x86seg_reset(); x86_was_reset = 1; } static void setznp8(uint8_t val) { flags&=~0xC4; flags|=znptable8[val]; } static void setznp16(uint16_t val) { flags&=~0xC4; flags|=znptable16[val]; } static void setadd8(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a+(uint16_t)b; flags&=~0x8D5; flags|=znptable8[c&0xFF]; if (c&0x100) flags|=C_FLAG; if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } static void setadd8nc(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a+(uint16_t)b; flags&=~0x8D4; flags|=znptable8[c&0xFF]; if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } static void setadc8(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a+(uint16_t)b+tempc; flags&=~0x8D5; flags|=znptable8[c&0xFF]; if (c&0x100) flags|=C_FLAG; if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } static void setadd16(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a+(uint32_t)b; flags&=~0x8D5; flags|=znptable16[c&0xFFFF]; if (c&0x10000) flags|=C_FLAG; if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } static void setadd16nc(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a+(uint32_t)b; flags&=~0x8D4; flags|=znptable16[c&0xFFFF]; if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } static void setadc16(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a+(uint32_t)b+tempc; flags&=~0x8D5; flags|=znptable16[c&0xFFFF]; if (c&0x10000) flags|=C_FLAG; if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } static void setsub8(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a-(uint16_t)b; flags&=~0x8D5; flags|=znptable8[c&0xFF]; if (c&0x100) flags|=C_FLAG; if ((a^b)&(a^c)&0x80) flags|=V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } static void setsub8nc(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a-(uint16_t)b; flags&=~0x8D4; flags|=znptable8[c&0xFF]; if ((a^b)&(a^c)&0x80) flags|=V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } static void setsbc8(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc); flags&=~0x8D5; flags|=znptable8[c&0xFF]; if (c&0x100) flags|=C_FLAG; if ((a^b)&(a^c)&0x80) flags|=V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } static void setsub16(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a-(uint32_t)b; flags&=~0x8D5; flags|=znptable16[c&0xFFFF]; if (c&0x10000) flags|=C_FLAG; if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; // if (output) printf("%04X %04X %i\n",a^b,a^c,flags&V_FLAG); if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } static void setsub16nc(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a-(uint32_t)b; flags&=~0x8D4; flags|=(znptable16[c&0xFFFF]&~4); flags|=(znptable8[c&0xFF]&4); if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } static void setsbc16(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); flags&=~0x8D5; flags|=(znptable16[c&0xFFFF]&~4); flags|=(znptable8[c&0xFF]&4); if (c&0x10000) flags|=C_FLAG; if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } int current_diff = 0; void clockhardware() { int diff = cycdiff - cycles - current_diff; current_diff += diff; timer_end_period(cycles*xt_cpu_multi); } static int takeint = 0; int firstrepcycle=1; void rep(int fv) { uint8_t temp; int c=CX; uint8_t temp2; uint16_t tempw,tempw2; uint16_t ipc=oldpc;//pc-1; int changeds=0; uint32_t oldds; startrep: temp=FETCH(); // if (firstrepcycle && temp==0xA5) printf("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI); // if (output) printf("REP %02X %04X\n",temp,ipc); switch (temp) { case 0x08: cpu_state.pc=ipc+1; cycles-=2; FETCHCLEAR(); break; case 0x26: /*ES:*/ oldds=ds; ds=es; changeds=1; cycles-=2; goto startrep; break; case 0x2E: /*CS:*/ oldds=ds; ds=cs; changeds=1; cycles-=2; goto startrep; break; case 0x36: /*SS:*/ oldds=ds; ds=ss; changeds=1; cycles-=2; goto startrep; break; case 0x6E: /*REP OUTSB*/ if (c>0) { temp2=readmemb(ds+SI); outb(DX,temp2); if (flags&D_FLAG) SI--; else SI++; c--; cycles-=5; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); } else firstrepcycle=1; break; case 0xA4: /*REP MOVSB*/ while (c>0 && !IRQTEST) { temp2=readmemb(ds+SI); writememb(es+DI,temp2); // if (output) printf("Moved %02X from %04X:%04X to %04X:%04X\n",temp2,ds>>4,SI,es>>4,DI); if (flags&D_FLAG) { DI--; SI--; } else { DI++; SI++; } c--; cycles-=17; clockhardware(); FETCHADD(17-memcycs); } if (IRQTEST && c>0) cpu_state.pc=ipc; // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; // } break; case 0xA5: /*REP MOVSW*/ while (c>0 && !IRQTEST) { memcycs=0; tempw=readmemw(ds,SI); writememw(es,DI,tempw); if (flags&D_FLAG) { DI-=2; SI-=2; } else { DI+=2; SI+=2; } c--; cycles-=17; clockhardware(); FETCHADD(17 - memcycs); } if (IRQTEST && c>0) cpu_state.pc=ipc; // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; // } break; case 0xA6: /*REP CMPSB*/ if (fv) flags|=Z_FLAG; else flags&=~Z_FLAG; while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) { memcycs=0; temp=readmemb(ds+SI); temp2=readmemb(es+DI); // printf("CMPSB %c %c %i %05X %05X %04X:%04X\n",temp,temp2,c,ds+SI,es+DI,cs>>4,pc); if (flags&D_FLAG) { DI--; SI--; } else { DI++; SI++; } c--; cycles -= 30; setsub8(temp,temp2); clockhardware(); FETCHADD(30 - memcycs); } if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; break; case 0xA7: /*REP CMPSW*/ if (fv) flags|=Z_FLAG; else flags&=~Z_FLAG; while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) { memcycs=0; tempw=readmemw(ds,SI); tempw2=readmemw(es,DI); if (flags&D_FLAG) { DI-=2; SI-=2; } else { DI+=2; SI+=2; } c--; cycles -= 30; setsub16(tempw,tempw2); clockhardware(); FETCHADD(30 - memcycs); } if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; // if (firstrepcycle) printf("REP CMPSW %06X:%04X %06X:%04X %04X %04X\n",ds,SI,es,DI,tempw,tempw2); break; case 0xAA: /*REP STOSB*/ while (c>0 && !IRQTEST) { memcycs=0; writememb(es+DI,AL); if (flags&D_FLAG) DI--; else DI++; c--; cycles -= 10; clockhardware(); FETCHADD(10 - memcycs); } if (IRQTEST && c>0) cpu_state.pc=ipc; // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; break; case 0xAB: /*REP STOSW*/ while (c>0 && !IRQTEST) { memcycs=0; writememw(es,DI,AX); if (flags&D_FLAG) DI-=2; else DI+=2; c--; cycles -= 10; clockhardware(); FETCHADD(10 - memcycs); } if (IRQTEST && c>0) cpu_state.pc=ipc; // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); } // else firstrepcycle=1; break; case 0xAC: /*REP LODSB*/ if (c>0) { temp2=readmemb(ds+SI); if (flags&D_FLAG) SI--; else SI++; c--; cycles-=4; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); } else firstrepcycle=1; break; case 0xAD: /*REP LODSW*/ if (c>0) { tempw2=readmemw(ds,SI); if (flags&D_FLAG) SI-=2; else SI+=2; c--; cycles-=4; } if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); } else firstrepcycle=1; break; case 0xAE: /*REP SCASB*/ if (fv) flags|=Z_FLAG; else flags&=~Z_FLAG; if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { temp2=readmemb(es+DI); // if (output) printf("SCASB %02X %c %02X %05X ",temp2,temp2,AL,es+DI); setsub8(AL,temp2); // if (output && flags&Z_FLAG) printf("Match %02X %02X\n",AL,temp2); if (flags&D_FLAG) DI--; else DI++; c--; cycles -= 15; } //if (output) printf("%i %i %i %i\n",c,(c>0),(fv==((flags&Z_FLAG)?1:0)),((c>0) && (fv==((flags&Z_FLAG)?1:0)))); if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); } else firstrepcycle=1; // cycles-=120; break; case 0xAF: /*REP SCASW*/ if (fv) flags|=Z_FLAG; else flags&=~Z_FLAG; if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { tempw=readmemw(es,DI); setsub16(AX,tempw); if (flags&D_FLAG) DI-=2; else DI+=2; c--; cycles -= 15; } if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); } else firstrepcycle=1; break; default: cpu_state.pc = ipc+1; cycles-=20; FETCHCLEAR(); // printf("Bad REP %02X\n",temp); // dumpregs(); // exit(-1); } CX=c; if (changeds) ds=oldds; if (IRQTEST) takeint = 1; // if (pc==ipc) FETCHCLEAR(); } int inhlt=0; uint16_t lastpc,lastcs; int firstrepcycle; int skipnextprint=0; int instime=0; //#if 0 void execx86(int cycs) { uint8_t temp,temp2; uint16_t addr,tempw,tempw2,tempw3,tempw4; int8_t offset; int tempws; uint32_t templ; int c; int tempi; int trap; // printf("Run x86! %i %i\n",cycles,cycs); cycles+=cycs; // i86_Execute(cycs); // return; while (cycles>0) { // old83=old82; // old82=old8; // old8=oldpc|(oldcs<<16); // if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; } // if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime); cycdiff=cycles; timer_start_period(cycles*xt_cpu_multi); current_diff = 0; cycles-=nextcyc; // if (instime) pclog("Cycles %i %i\n",cycles,cycdiff); nextcyc=0; // if (output) printf("CLOCK %i %i\n",cycdiff,cycles); fetchclocks=0; oldcs=CS; oldpc=cpu_state.pc; opcodestart: opcode=FETCH(); tempc=flags&C_FLAG; trap=flags&T_FLAG; cpu_state.pc--; // output=1; // if (output) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X\n",cs>>4,pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags&~0x200,rmdat); //#if 0 if (output) { // if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle) // { if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); skipnextprint=0; // ins++; // } } //#endif cpu_state.pc++; inhlt=0; // if (ins==500000) { dumpregs(); exit(0); }*/ switch (opcode) { case 0x00: /*ADD 8,reg*/ fetchea(); /* if (!rmdat) pc--; if (!rmdat) { fatal("Crashed\n"); // clear_keybuf(); // readkey(); }*/ temp=geteab(); setadd8(temp,getr8(cpu_reg)); temp+=getr8(cpu_reg); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x01: /*ADD 16,reg*/ fetchea(); tempw=geteaw(); setadd16(tempw, cpu_state.regs[cpu_reg].w); tempw += cpu_state.regs[cpu_reg].w; seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x02: /*ADD cpu_reg,8*/ fetchea(); temp=geteab(); setadd8(getr8(cpu_reg),temp); setr8(cpu_reg,getr8(cpu_reg)+temp); cycles-=((cpu_mod==3)?3:13); break; case 0x03: /*ADD cpu_reg,16*/ fetchea(); tempw=geteaw(); setadd16(cpu_state.regs[cpu_reg].w,tempw); cpu_state.regs[cpu_reg].w+=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x04: /*ADD AL,#8*/ temp=FETCH(); setadd8(AL,temp); AL+=temp; cycles-=4; break; case 0x05: /*ADD AX,#16*/ tempw=getword(); setadd16(AX,tempw); AX+=tempw; cycles-=4; break; case 0x06: /*PUSH ES*/ if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),ES); SP-=2; cpu_state.last_ea = SP; cycles-=14; break; case 0x07: /*POP ES*/ if (ssegs) ss=oldss; tempw=readmemw(ss,SP); loadseg(tempw,&_es); SP+=2; cpu_state.last_ea = SP; cycles-=12; break; case 0x08: /*OR 8,reg*/ fetchea(); temp=geteab(); temp|=getr8(cpu_reg); setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x09: /*OR 16,reg*/ fetchea(); tempw=geteaw(); tempw|=cpu_state.regs[cpu_reg].w; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x0A: /*OR cpu_reg,8*/ fetchea(); temp=geteab(); temp|=getr8(cpu_reg); setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?3:13); break; case 0x0B: /*OR reg,16*/ fetchea(); tempw=geteaw(); tempw|=cpu_state.regs[cpu_reg].w; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x0C: /*OR AL,#8*/ AL|=FETCH(); setznp8(AL); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x0D: /*OR AX,#16*/ AX|=getword(); setznp16(AX); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x0E: /*PUSH CS*/ if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),CS); SP-=2; cpu_state.last_ea = SP; cycles-=14; break; case 0x0F: /*POP CS - 8088/8086 only*/ if (ssegs) ss=oldss; tempw=readmemw(ss,SP); loadseg(tempw,&_cs); SP+=2; cpu_state.last_ea = SP; cycles-=12; break; case 0x10: /*ADC 8,reg*/ fetchea(); temp=geteab(); temp2=getr8(cpu_reg); setadc8(temp,temp2); temp+=temp2+tempc; seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x11: /*ADC 16,reg*/ fetchea(); tempw=geteaw(); tempw2=cpu_state.regs[cpu_reg].w; setadc16(tempw,tempw2); tempw+=tempw2+tempc; seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x12: /*ADC cpu_reg,8*/ fetchea(); temp=geteab(); setadc8(getr8(cpu_reg),temp); setr8(cpu_reg,getr8(cpu_reg)+temp+tempc); cycles-=((cpu_mod==3)?3:13); break; case 0x13: /*ADC cpu_reg,16*/ fetchea(); tempw=geteaw(); setadc16(cpu_state.regs[cpu_reg].w,tempw); cpu_state.regs[cpu_reg].w+=tempw+tempc; cycles-=((cpu_mod==3)?3:13); break; case 0x14: /*ADC AL,#8*/ tempw=FETCH(); setadc8(AL,tempw); AL+=tempw+tempc; cycles-=4; break; case 0x15: /*ADC AX,#16*/ tempw=getword(); setadc16(AX,tempw); AX+=tempw+tempc; cycles-=4; break; case 0x16: /*PUSH SS*/ if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),SS); SP-=2; cycles-=14; cpu_state.last_ea = SP; break; case 0x17: /*POP SS*/ if (ssegs) ss=oldss; tempw=readmemw(ss,SP); loadseg(tempw,&_ss); SP+=2; cpu_state.last_ea = SP; noint=1; cycles-=12; // output=1; break; case 0x18: /*SBB 8,reg*/ fetchea(); temp=geteab(); temp2=getr8(cpu_reg); setsbc8(temp,temp2); temp-=(temp2+tempc); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x19: /*SBB 16,reg*/ fetchea(); tempw=geteaw(); tempw2=cpu_state.regs[cpu_reg].w; // printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc); setsbc16(tempw,tempw2); tempw-=(tempw2+tempc); seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x1A: /*SBB cpu_reg,8*/ fetchea(); temp=geteab(); setsbc8(getr8(cpu_reg),temp); setr8(cpu_reg,getr8(cpu_reg)-(temp+tempc)); cycles-=((cpu_mod==3)?3:13); break; case 0x1B: /*SBB cpu_reg,16*/ fetchea(); tempw=geteaw(); tempw2=cpu_state.regs[cpu_reg].w; // printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc); setsbc16(tempw2,tempw); tempw2-=(tempw+tempc); cpu_state.regs[cpu_reg].w=tempw2; cycles-=((cpu_mod==3)?3:13); break; case 0x1C: /*SBB AL,#8*/ temp=FETCH(); setsbc8(AL,temp); AL-=(temp+tempc); cycles-=4; break; case 0x1D: /*SBB AX,#16*/ tempw=getword(); setsbc16(AX,tempw); AX-=(tempw+tempc); cycles-=4; break; case 0x1E: /*PUSH DS*/ if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),DS); SP-=2; cpu_state.last_ea = SP; cycles-=14; break; case 0x1F: /*POP DS*/ if (ssegs) ss=oldss; tempw=readmemw(ss,SP); loadseg(tempw,&_ds); if (ssegs) oldds=ds; SP+=2; cpu_state.last_ea = SP; cycles-=12; break; case 0x20: /*AND 8,reg*/ fetchea(); temp=geteab(); temp&=getr8(cpu_reg); setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x21: /*AND 16,reg*/ fetchea(); tempw=geteaw(); tempw&=cpu_state.regs[cpu_reg].w; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x22: /*AND cpu_reg,8*/ fetchea(); temp=geteab(); temp&=getr8(cpu_reg); setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?3:13); break; case 0x23: /*AND cpu_reg,16*/ fetchea(); tempw=geteaw(); tempw&=cpu_state.regs[cpu_reg].w; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x24: /*AND AL,#8*/ AL&=FETCH(); setznp8(AL); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x25: /*AND AX,#16*/ AX&=getword(); setznp16(AX); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x26: /*ES:*/ oldss=ss; oldds=ds; ds=ss=es; ssegs=2; cycles-=4; goto opcodestart; // break; case 0x27: /*DAA*/ if ((flags&A_FLAG) || ((AL&0xF)>9)) { tempi=((uint16_t)AL)+6; AL+=6; flags|=A_FLAG; if (tempi&0x100) flags|=C_FLAG; } // else // flags&=~A_FLAG; if ((flags&C_FLAG) || (AL>0x9F)) { AL+=0x60; flags|=C_FLAG; } // else // flags&=~C_FLAG; setznp8(AL); cycles-=4; break; case 0x28: /*SUB 8,reg*/ fetchea(); temp=geteab(); setsub8(temp,getr8(cpu_reg)); temp-=getr8(cpu_reg); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x29: /*SUB 16,reg*/ fetchea(); tempw=geteaw(); // printf("%04X:%04X %04X-%04X\n",cs>>4,pc,tempw,cpu_state.regs[cpu_reg].w); setsub16(tempw,cpu_state.regs[cpu_reg].w); tempw-=cpu_state.regs[cpu_reg].w; seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x2A: /*SUB cpu_reg,8*/ fetchea(); temp=geteab(); setsub8(getr8(cpu_reg),temp); setr8(cpu_reg,getr8(cpu_reg)-temp); cycles-=((cpu_mod==3)?3:13); break; case 0x2B: /*SUB cpu_reg,16*/ fetchea(); tempw=geteaw(); // printf("%04X:%04X %04X-%04X\n",cs>>4,pc,cpu_state.regs[cpu_reg].w,tempw); setsub16(cpu_state.regs[cpu_reg].w,tempw); cpu_state.regs[cpu_reg].w-=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x2C: /*SUB AL,#8*/ temp=FETCH(); setsub8(AL,temp); AL-=temp; cycles-=4; break; case 0x2D: /*SUB AX,#16*/ // printf("INS %i\n",ins); // output=1; tempw=getword(); setsub16(AX,tempw); AX-=tempw; cycles-=4; break; case 0x2E: /*CS:*/ oldss=ss; oldds=ds; ds=ss=cs; ssegs=2; cycles-=4; goto opcodestart; case 0x2F: /*DAS*/ if ((flags&A_FLAG)||((AL&0xF)>9)) { tempi=((uint16_t)AL)-6; AL-=6; flags|=A_FLAG; if (tempi&0x100) flags|=C_FLAG; } // else // flags&=~A_FLAG; if ((flags&C_FLAG)||(AL>0x9F)) { AL-=0x60; flags|=C_FLAG; } // else // flags&=~C_FLAG; setznp8(AL); cycles-=4; break; case 0x30: /*XOR 8,reg*/ fetchea(); temp=geteab(); temp^=getr8(cpu_reg); setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x31: /*XOR 16,reg*/ fetchea(); tempw=geteaw(); tempw^=cpu_state.regs[cpu_reg].w; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x32: /*XOR cpu_reg,8*/ fetchea(); temp=geteab(); temp^=getr8(cpu_reg); setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?3:13); break; case 0x33: /*XOR cpu_reg,16*/ fetchea(); tempw=geteaw(); tempw^=cpu_state.regs[cpu_reg].w; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?3:13); break; case 0x34: /*XOR AL,#8*/ AL^=FETCH(); setznp8(AL); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x35: /*XOR AX,#16*/ AX^=getword(); setznp16(AX); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=4; break; case 0x36: /*SS:*/ oldss=ss; oldds=ds; ds=ss=ss; ssegs=2; cycles-=4; goto opcodestart; // break; case 0x37: /*AAA*/ if ((flags&A_FLAG)||((AL&0xF)>9)) { AL+=6; AH++; flags|=(A_FLAG|C_FLAG); } else flags&=~(A_FLAG|C_FLAG); AL&=0xF; cycles-=8; break; case 0x38: /*CMP 8,reg*/ fetchea(); temp=geteab(); // if (output) printf("CMP %02X-%02X\n",temp,getr8(cpu_reg)); setsub8(temp,getr8(cpu_reg)); cycles-=((cpu_mod==3)?3:13); break; case 0x39: /*CMP 16,reg*/ fetchea(); tempw=geteaw(); // if (output) printf("CMP %04X-%04X\n",tempw,cpu_state.regs[cpu_reg].w); setsub16(tempw,cpu_state.regs[cpu_reg].w); cycles-=((cpu_mod==3)?3:13); break; case 0x3A: /*CMP cpu_reg,8*/ fetchea(); temp=geteab(); // if (output) printf("CMP %02X-%02X\n",getr8(cpu_reg),temp); setsub8(getr8(cpu_reg),temp); cycles-=((cpu_mod==3)?3:13); break; case 0x3B: /*CMP cpu_reg,16*/ fetchea(); tempw=geteaw(); // printf("CMP %04X-%04X\n",cpu_state.regs[cpu_reg].w,tempw); setsub16(cpu_state.regs[cpu_reg].w,tempw); cycles-=((cpu_mod==3)?3:13); break; case 0x3C: /*CMP AL,#8*/ temp=FETCH(); setsub8(AL,temp); cycles-=4; break; case 0x3D: /*CMP AX,#16*/ tempw=getword(); setsub16(AX,tempw); cycles-=4; break; case 0x3E: /*DS:*/ oldss=ss; oldds=ds; ds=ss=ds; ssegs=2; cycles-=4; goto opcodestart; // break; case 0x3F: /*AAS*/ if ((flags&A_FLAG)||((AL&0xF)>9)) { AL-=6; AH--; flags|=(A_FLAG|C_FLAG); } else flags&=~(A_FLAG|C_FLAG); AL&=0xF; cycles-=8; break; case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/ case 0x44: case 0x45: case 0x46: case 0x47: setadd16nc(cpu_state.regs[opcode&7].w,1); cpu_state.regs[opcode&7].w++; cycles-=3; break; case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/ case 0x4C: case 0x4D: case 0x4E: case 0x4F: setsub16nc(cpu_state.regs[opcode&7].w,1); cpu_state.regs[opcode&7].w--; cycles-=3; break; case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ case 0x54: case 0x55: case 0x56: case 0x57: if (ssegs) ss=oldss; SP-=2; cpu_state.last_ea = SP; writememw(ss,SP,cpu_state.regs[opcode&7].w); cycles-=15; break; case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ case 0x5C: case 0x5D: case 0x5E: case 0x5F: if (ssegs) ss=oldss; SP+=2; cpu_state.last_ea = SP; cpu_state.regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF); cycles-=12; break; case 0x60: /*JO alias*/ case 0x70: /*JO*/ offset=(int8_t)FETCH(); if (flags&V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x61: /*JNO alias*/ case 0x71: /*JNO*/ offset=(int8_t)FETCH(); if (!(flags&V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x62: /*JB alias*/ case 0x72: /*JB*/ offset=(int8_t)FETCH(); if (flags&C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x63: /*JNB alias*/ case 0x73: /*JNB*/ offset=(int8_t)FETCH(); if (!(flags&C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x64: /*JE alias*/ case 0x74: /*JE*/ offset=(int8_t)FETCH(); if (flags&Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x65: /*JNE alias*/ case 0x75: /*JNE*/ offset=(int8_t)FETCH(); cycles-=4; if (!(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } break; case 0x66: /*JBE alias*/ case 0x76: /*JBE*/ offset=(int8_t)FETCH(); if (flags&(C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x67: /*JNBE alias*/ case 0x77: /*JNBE*/ offset=(int8_t)FETCH(); if (!(flags&(C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x68: /*JS alias*/ case 0x78: /*JS*/ offset=(int8_t)FETCH(); if (flags&N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x69: /*JNS alias*/ case 0x79: /*JNS*/ offset=(int8_t)FETCH(); if (!(flags&N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6A: /*JP alias*/ case 0x7A: /*JP*/ offset=(int8_t)FETCH(); if (flags&P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6B: /*JNP alias*/ case 0x7B: /*JNP*/ offset=(int8_t)FETCH(); if (!(flags&P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6C: /*JL alias*/ case 0x7C: /*JL*/ offset=(int8_t)FETCH(); temp=(flags&N_FLAG)?1:0; temp2=(flags&V_FLAG)?1:0; if (temp!=temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6D: /*JNL alias*/ case 0x7D: /*JNL*/ offset=(int8_t)FETCH(); temp=(flags&N_FLAG)?1:0; temp2=(flags&V_FLAG)?1:0; if (temp==temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6E: /*JLE alias*/ case 0x7E: /*JLE*/ offset=(int8_t)FETCH(); temp=(flags&N_FLAG)?1:0; temp2=(flags&V_FLAG)?1:0; if ((flags&Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x6F: /*JNLE alias*/ case 0x7F: /*JNLE*/ offset=(int8_t)FETCH(); temp=(flags&N_FLAG)?1:0; temp2=(flags&V_FLAG)?1:0; if (!((flags&Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=4; break; case 0x80: case 0x82: fetchea(); temp=geteab(); temp2=FETCH(); switch (rmdat&0x38) { case 0x00: /*ADD b,#8*/ setadd8(temp,temp2); seteab(temp+temp2); cycles-=((cpu_mod==3)?4:23); break; case 0x08: /*OR b,#8*/ temp|=temp2; setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?4:23); break; case 0x10: /*ADC b,#8*/ // temp2+=(flags&C_FLAG); setadc8(temp,temp2); seteab(temp+temp2+tempc); cycles-=((cpu_mod==3)?4:23); break; case 0x18: /*SBB b,#8*/ // temp2+=(flags&C_FLAG); setsbc8(temp,temp2); seteab(temp-(temp2+tempc)); cycles-=((cpu_mod==3)?4:23); break; case 0x20: /*AND b,#8*/ temp&=temp2; setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?4:23); break; case 0x28: /*SUB b,#8*/ setsub8(temp,temp2); seteab(temp-temp2); cycles-=((cpu_mod==3)?4:23); break; case 0x30: /*XOR b,#8*/ temp^=temp2; setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteab(temp); cycles-=((cpu_mod==3)?4:23); break; case 0x38: /*CMP b,#8*/ setsub8(temp,temp2); cycles-=((cpu_mod==3)?4:14); break; // default: // printf("Bad 80 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0x81: fetchea(); tempw=geteaw(); tempw2=getword(); switch (rmdat&0x38) { case 0x00: /*ADD w,#16*/ setadd16(tempw,tempw2); tempw+=tempw2; seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x08: /*OR w,#16*/ tempw|=tempw2; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x10: /*ADC w,#16*/ // tempw2+=(flags&C_FLAG); setadc16(tempw,tempw2); tempw+=tempw2+tempc; seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x20: /*AND w,#16*/ tempw&=tempw2; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x18: /*SBB w,#16*/ // tempw2+=(flags&C_FLAG); setsbc16(tempw,tempw2); seteaw(tempw-(tempw2+tempc)); cycles-=((cpu_mod==3)?4:23); break; case 0x28: /*SUB w,#16*/ setsub16(tempw,tempw2); tempw-=tempw2; seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x30: /*XOR w,#16*/ tempw^=tempw2; setznp16(tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x38: /*CMP w,#16*/ // printf("CMP %04X %04X\n",tempw,tempw2); setsub16(tempw,tempw2); cycles-=((cpu_mod==3)?4:14); break; // default: // printf("Bad 81 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0x83: fetchea(); tempw=geteaw(); tempw2=FETCH(); if (tempw2&0x80) tempw2|=0xFF00; switch (rmdat&0x38) { case 0x00: /*ADD w,#8*/ setadd16(tempw,tempw2); tempw+=tempw2; seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x08: /*OR w,#8*/ tempw|=tempw2; setznp16(tempw); seteaw(tempw); flags&=~(C_FLAG|A_FLAG|V_FLAG); cycles-=((cpu_mod==3)?4:23); break; case 0x10: /*ADC w,#8*/ // tempw2+=(flags&C_FLAG); setadc16(tempw,tempw2); tempw+=tempw2+tempc; seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x18: /*SBB w,#8*/ // tempw2+=(flags&C_FLAG); setsbc16(tempw,tempw2); tempw-=(tempw2+tempc); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x20: /*AND w,#8*/ tempw&=tempw2; setznp16(tempw); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); flags&=~(C_FLAG|A_FLAG|V_FLAG); break; case 0x28: /*SUB w,#8*/ setsub16(tempw,tempw2); tempw-=tempw2; seteaw(tempw); cycles-=((cpu_mod==3)?4:23); break; case 0x30: /*XOR w,#8*/ tempw^=tempw2; setznp16(tempw); seteaw(tempw); cycles-=((cpu_mod==3)?4:23); flags&=~(C_FLAG|A_FLAG|V_FLAG); break; case 0x38: /*CMP w,#8*/ setsub16(tempw,tempw2); cycles-=((cpu_mod==3)?4:14); break; // default: // printf("Bad 83 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0x84: /*TEST b,reg*/ fetchea(); temp=geteab(); temp2=getr8(cpu_reg); setznp8(temp&temp2); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?3:13); break; case 0x85: /*TEST w,reg*/ fetchea(); tempw=geteaw(); tempw2=cpu_state.regs[cpu_reg].w; setznp16(tempw&tempw2); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?3:13); break; case 0x86: /*XCHG b,reg*/ fetchea(); temp=geteab(); seteab(getr8(cpu_reg)); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?4:25); break; case 0x87: /*XCHG w,reg*/ fetchea(); tempw=geteaw(); seteaw(cpu_state.regs[cpu_reg].w); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?4:25); break; case 0x88: /*MOV b,reg*/ fetchea(); seteab(getr8(cpu_reg)); cycles-=((cpu_mod==3)?2:13); break; case 0x89: /*MOV w,reg*/ fetchea(); seteaw(cpu_state.regs[cpu_reg].w); cycles-=((cpu_mod==3)?2:13); break; case 0x8A: /*MOV cpu_reg,b*/ fetchea(); temp=geteab(); setr8(cpu_reg,temp); cycles-=((cpu_mod==3)?2:12); break; case 0x8B: /*MOV cpu_reg,w*/ fetchea(); tempw=geteaw(); cpu_state.regs[cpu_reg].w=tempw; cycles-=((cpu_mod==3)?2:12); break; case 0x8C: /*MOV w,sreg*/ fetchea(); switch (rmdat&0x38) { case 0x00: /*ES*/ seteaw(ES); break; case 0x08: /*CS*/ seteaw(CS); break; case 0x18: /*DS*/ if (ssegs) ds=oldds; seteaw(DS); break; case 0x10: /*SS*/ if (ssegs) ss=oldss; seteaw(SS); break; } cycles-=((cpu_mod==3)?2:13); break; case 0x8D: /*LEA*/ fetchea(); cpu_state.regs[cpu_reg].w=(cpu_mod == 3)?cpu_state.last_ea:eaaddr; cycles-=2; break; case 0x8E: /*MOV sreg,w*/ // if (output) printf("MOV %04X ",pc); fetchea(); // if (output) printf("%04X %02X\n",pc,rmdat); switch (rmdat&0x38) { case 0x00: /*ES*/ tempw=geteaw(); loadseg(tempw,&_es); break; case 0x08: /*CS - 8088/8086 only*/ tempw=geteaw(); loadseg(tempw,&_cs); break; case 0x18: /*DS*/ tempw=geteaw(); loadseg(tempw,&_ds); if (ssegs) oldds=ds; break; case 0x10: /*SS*/ tempw=geteaw(); loadseg(tempw,&_ss); if (ssegs) oldss=ss; // printf("LOAD SS %04X %04X\n",tempw,SS); // printf("SS loaded with %04X %04X:%04X %04X %04X %04X\n",ss>>4,cs>>4,pc,CX,DX,es>>4); break; } cycles-=((cpu_mod==3)?2:12); skipnextprint=1; noint=1; break; case 0x8F: /*POPW*/ fetchea(); if (ssegs) ss=oldss; tempw=readmemw(ss,SP); SP+=2; cpu_state.last_ea = SP; seteaw(tempw); cycles-=25; break; case 0x90: /*NOP*/ cycles-=3; break; case 0x91: case 0x92: case 0x93: /*XCHG AX*/ case 0x94: case 0x95: case 0x96: case 0x97: tempw=AX; AX=cpu_state.regs[opcode&7].w; cpu_state.regs[opcode&7].w=tempw; cycles-=3; break; case 0x98: /*CBW*/ AH=(AL&0x80)?0xFF:0; cycles-=2; break; case 0x99: /*CWD*/ DX=(AX&0x8000)?0xFFFF:0; cycles-=5; break; case 0x9A: /*CALL FAR*/ tempw=getword(); tempw2=getword(); tempw3=CS; tempw4=cpu_state.pc; if (ssegs) ss=oldss; cpu_state.pc=tempw; // printf("0x9a"); loadcs(tempw2); writememw(ss,(SP-2)&0xFFFF,tempw3); writememw(ss,(SP-4)&0xFFFF,tempw4); SP-=4; cpu_state.last_ea = SP; cycles-=36; FETCHCLEAR(); break; case 0x9B: /*WAIT*/ cycles-=4; break; case 0x9C: /*PUSHF*/ if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),flags|0xF000); SP-=2; cpu_state.last_ea = SP; cycles-=14; break; case 0x9D: /*POPF*/ if (ssegs) ss=oldss; flags=readmemw(ss,SP)&0xFFF; SP+=2; cpu_state.last_ea = SP; cycles-=12; break; case 0x9E: /*SAHF*/ flags=(flags&0xFF00)|AH; cycles-=4; break; case 0x9F: /*LAHF*/ AH=flags&0xFF; cycles-=4; break; case 0xA0: /*MOV AL,(w)*/ addr=getword(); AL=readmemb(ds+addr); cycles-=14; break; case 0xA1: /*MOV AX,(w)*/ addr=getword(); // printf("Reading AX from %05X %04X:%04X\n",ds+addr,ds>>4,addr); AX=readmemw(ds,addr); cycles-=!4; break; case 0xA2: /*MOV (w),AL*/ addr=getword(); writememb(ds+addr,AL); cycles-=14; break; case 0xA3: /*MOV (w),AX*/ addr=getword(); // if (!addr) printf("Write !addr %04X:%04X\n",cs>>4,pc); writememw(ds,addr,AX); cycles-=14; break; case 0xA4: /*MOVSB*/ temp=readmemb(ds+SI); writememb(es+DI,temp); if (flags&D_FLAG) { DI--; SI--; } else { DI++; SI++; } cycles-=18; break; case 0xA5: /*MOVSW*/ tempw=readmemw(ds,SI); writememw(es,DI,tempw); if (flags&D_FLAG) { DI-=2; SI-=2; } else { DI+=2; SI+=2; } cycles-=18; break; case 0xA6: /*CMPSB*/ temp =readmemb(ds+SI); temp2=readmemb(es+DI); setsub8(temp,temp2); if (flags&D_FLAG) { DI--; SI--; } else { DI++; SI++; } cycles-=30; break; case 0xA7: /*CMPSW*/ tempw =readmemw(ds,SI); tempw2=readmemw(es,DI); // printf("CMPSW %04X %04X\n",tempw,tempw2); setsub16(tempw,tempw2); if (flags&D_FLAG) { DI-=2; SI-=2; } else { DI+=2; SI+=2; } cycles-=30; break; case 0xA8: /*TEST AL,#8*/ temp=FETCH(); setznp8(AL&temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=5; break; case 0xA9: /*TEST AX,#16*/ tempw=getword(); setznp16(AX&tempw); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=5; break; case 0xAA: /*STOSB*/ writememb(es+DI,AL); if (flags&D_FLAG) DI--; else DI++; cycles-=11; break; case 0xAB: /*STOSW*/ writememw(es,DI,AX); if (flags&D_FLAG) DI-=2; else DI+=2; cycles-=11; break; case 0xAC: /*LODSB*/ AL=readmemb(ds+SI); // printf("LODSB %04X:%04X %02X %04X:%04X\n",cs>>4,pc,AL,ds>>4,SI); if (flags&D_FLAG) SI--; else SI++; cycles-=16; break; case 0xAD: /*LODSW*/ // if (times) printf("LODSW %04X:%04X\n",cs>>4,pc); AX=readmemw(ds,SI); if (flags&D_FLAG) SI-=2; else SI+=2; cycles-=16; break; case 0xAE: /*SCASB*/ temp=readmemb(es+DI); setsub8(AL,temp); if (flags&D_FLAG) DI--; else DI++; cycles-=19; break; case 0xAF: /*SCASW*/ tempw=readmemw(es,DI); setsub16(AX,tempw); if (flags&D_FLAG) DI-=2; else DI+=2; cycles-=19; break; case 0xB0: /*MOV AL,#8*/ AL=FETCH(); cycles-=4; break; case 0xB1: /*MOV CL,#8*/ CL=FETCH(); cycles-=4; break; case 0xB2: /*MOV DL,#8*/ DL=FETCH(); cycles-=4; break; case 0xB3: /*MOV BL,#8*/ BL=FETCH(); cycles-=4; break; case 0xB4: /*MOV AH,#8*/ AH=FETCH(); cycles-=4; break; case 0xB5: /*MOV CH,#8*/ CH=FETCH(); cycles-=4; break; case 0xB6: /*MOV DH,#8*/ DH=FETCH(); cycles-=4; break; case 0xB7: /*MOV BH,#8*/ BH=FETCH(); cycles-=4; break; case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ case 0xBC: case 0xBD: case 0xBE: case 0xBF: cpu_state.regs[opcode&7].w=getword(); cycles-=4; break; case 0xC0: /*RET alias*/ case 0xC2: /*RET*/ tempw=getword(); if (ssegs) ss=oldss; cpu_state.pc=readmemw(ss,SP); // printf("C2\n"); // printf("RET to %04X\n",pc); SP+=2+tempw; cycles-=24; FETCHCLEAR(); break; case 0xC1: /*RET alias*/ case 0xC3: /*RET*/ if (ssegs) ss=oldss; cpu_state.pc=readmemw(ss,SP); // printf("C3\n"); // if (output) printf("RET to %04X %05X\n",pc,ss+SP); SP+=2; cycles-=20; FETCHCLEAR(); break; case 0xC4: /*LES*/ fetchea(); cpu_state.regs[cpu_reg].w=readmemw(easeg,eaaddr); //geteaw(); tempw=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2(); loadseg(tempw,&_es); cycles-=24; break; case 0xC5: /*LDS*/ fetchea(); cpu_state.regs[cpu_reg].w=readmemw(easeg,eaaddr); tempw=readmemw(easeg,(eaaddr+2)&0xFFFF); loadseg(tempw,&_ds); if (ssegs) oldds=ds; cycles-=24; break; case 0xC6: /*MOV b,#8*/ fetchea(); temp=FETCH(); seteab(temp); cycles-=((cpu_mod==3)?4:14); break; case 0xC7: /*MOV w,#16*/ fetchea(); tempw=getword(); seteaw(tempw); cycles-=((cpu_mod==3)?4:14); break; case 0xC8: /*RETF alias*/ case 0xCA: /*RETF*/ tempw=getword(); if (ssegs) ss=oldss; cpu_state.pc=readmemw(ss,SP); // printf("CA\n"); loadcs(readmemw(ss,SP+2)); SP+=4; SP+=tempw; cycles-=33; FETCHCLEAR(); break; case 0xC9: /*RETF alias*/ case 0xCB: /*RETF*/ if (ssegs) ss=oldss; cpu_state.pc=readmemw(ss,SP); // printf("CB\n"); loadcs(readmemw(ss,SP+2)); SP+=4; cycles-=34; FETCHCLEAR(); break; case 0xCC: /*INT 3*/ if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),flags|0xF000); writememw(ss,((SP-4)&0xFFFF),CS); writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); SP-=6; addr=3<<2; flags&=~I_FLAG; flags&=~T_FLAG; // printf("CC %04X:%04X ",CS,pc); cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); FETCHCLEAR(); // printf("%04X:%04X\n",CS,pc); cycles-=72; break; case 0xCD: /*INT*/ lastpc=cpu_state.pc; lastcs=CS; temp=FETCH(); if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),flags|0xF000); writememw(ss,((SP-4)&0xFFFF),CS); writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); flags&=~T_FLAG; SP-=6; addr=temp<<2; cpu_state.pc=readmemw(0,addr); loadcs(readmemw(0,addr+2)); FETCHCLEAR(); cycles-=71; break; case 0xCF: /*IRET*/ if (ssegs) ss=oldss; tempw=CS; tempw2=cpu_state.pc; cpu_state.pc=readmemw(ss,SP); // printf("CF\n"); loadcs(readmemw(ss,((SP+2)&0xFFFF))); flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF; SP+=6; cycles-=44; FETCHCLEAR(); nmi_enable = 1; break; case 0xD0: fetchea(); temp=geteab(); switch (rmdat&0x38) { case 0x00: /*ROL b,1*/ if (temp&0x80) flags|=C_FLAG; else flags&=~C_FLAG; temp<<=1; if (flags&C_FLAG) temp|=1; seteab(temp); // setznp8(temp); if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x08: /*ROR b,1*/ if (temp&1) flags|=C_FLAG; else flags&=~C_FLAG; temp>>=1; if (flags&C_FLAG) temp|=0x80; seteab(temp); // setznp8(temp); if ((temp^(temp>>1))&0x40) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x10: /*RCL b,1*/ temp2=flags&C_FLAG; if (temp&0x80) flags|=C_FLAG; else flags&=~C_FLAG; temp<<=1; if (temp2) temp|=1; seteab(temp); // setznp8(temp); if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x18: /*RCR b,1*/ temp2=flags&C_FLAG; if (temp&1) flags|=C_FLAG; else flags&=~C_FLAG; temp>>=1; if (temp2) temp|=0x80; seteab(temp); // setznp8(temp); if ((temp^(temp>>1))&0x40) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x20: case 0x30: /*SHL b,1*/ if (temp&0x80) flags|=C_FLAG; else flags&=~C_FLAG; if ((temp^(temp<<1))&0x80) flags|=V_FLAG; else flags&=~V_FLAG; temp<<=1; seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?2:23); flags|=A_FLAG; break; case 0x28: /*SHR b,1*/ if (temp&1) flags|=C_FLAG; else flags&=~C_FLAG; if (temp&0x80) flags|=V_FLAG; else flags&=~V_FLAG; temp>>=1; seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?2:23); flags|=A_FLAG; break; case 0x38: /*SAR b,1*/ if (temp&1) flags|=C_FLAG; else flags&=~C_FLAG; temp>>=1; if (temp&0x40) temp|=0x80; seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?2:23); flags|=A_FLAG; flags&=~V_FLAG; break; // default: // printf("Bad D0 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0xD1: fetchea(); tempw=geteaw(); switch (rmdat&0x38) { case 0x00: /*ROL w,1*/ if (tempw&0x8000) flags|=C_FLAG; else flags&=~C_FLAG; tempw<<=1; if (flags&C_FLAG) tempw|=1; seteaw(tempw); // setznp16(tempw); if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x08: /*ROR w,1*/ if (tempw&1) flags|=C_FLAG; else flags&=~C_FLAG; tempw>>=1; if (flags&C_FLAG) tempw|=0x8000; seteaw(tempw); // setznp16(tempw); if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x10: /*RCL w,1*/ temp2=flags&C_FLAG; if (tempw&0x8000) flags|=C_FLAG; else flags&=~C_FLAG; tempw<<=1; if (temp2) tempw|=1; seteaw(tempw); if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x18: /*RCR w,1*/ temp2=flags&C_FLAG; if (tempw&1) flags|=C_FLAG; else flags&=~C_FLAG; tempw>>=1; if (temp2) tempw|=0x8000; seteaw(tempw); // setznp16(tempw); if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?2:23); break; case 0x20: case 0x30: /*SHL w,1*/ if (tempw&0x8000) flags|=C_FLAG; else flags&=~C_FLAG; if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG; else flags&=~V_FLAG; tempw<<=1; seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?2:23); flags|=A_FLAG; break; case 0x28: /*SHR w,1*/ if (tempw&1) flags|=C_FLAG; else flags&=~C_FLAG; if (tempw&0x8000) flags|=V_FLAG; else flags&=~V_FLAG; tempw>>=1; seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?2:23); flags|=A_FLAG; break; case 0x38: /*SAR w,1*/ if (tempw&1) flags|=C_FLAG; else flags&=~C_FLAG; tempw>>=1; if (tempw&0x4000) tempw|=0x8000; seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?2:23); flags|=A_FLAG; flags&=~V_FLAG; break; // default: // printf("Bad D1 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0xD2: fetchea(); temp=geteab(); c=CL; // cycles-=c; if (!c) break; // if (c>7) printf("Shiftb %i %02X\n",rmdat&0x38,c); switch (rmdat&0x38) { case 0x00: /*ROL b,CL*/ while (c>0) { temp2=(temp&0x80)?1:0; temp=(temp<<1)|temp2; c--; cycles-=4; } if (temp2) flags|=C_FLAG; else flags&=~C_FLAG; seteab(temp); // setznp8(temp); if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x08: /*ROR b,CL*/ while (c>0) { temp2=temp&1; temp>>=1; if (temp2) temp|=0x80; c--; cycles-=4; } if (temp2) flags|=C_FLAG; else flags&=~C_FLAG; seteab(temp); if ((temp^(temp>>1))&0x40) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x10: /*RCL b,CL*/ // printf("RCL %i %02X %02X\n",c,CL,temp); while (c>0) { templ=flags&C_FLAG; temp2=temp&0x80; temp<<=1; if (temp2) flags|=C_FLAG; else flags&=~C_FLAG; if (templ) temp|=1; c--; cycles-=4; } // printf("Now %02X\n",temp); seteab(temp); if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x18: /*RCR b,CL*/ while (c>0) { templ=flags&C_FLAG; temp2=temp&1; temp>>=1; if (temp2) flags|=C_FLAG; else flags&=~C_FLAG; if (templ) temp|=0x80; c--; cycles-=4; } // if (temp2) flags|=C_FLAG; // else flags&=~C_FLAG; seteab(temp); if ((temp^(temp>>1))&0x40) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x20: case 0x30: /*SHL b,CL*/ if ((temp<<(c-1))&0x80) flags|=C_FLAG; else flags&=~C_FLAG; temp<<=c; seteab(temp); setznp8(temp); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); flags|=A_FLAG; break; case 0x28: /*SHR b,CL*/ if ((temp>>(c-1))&1) flags|=C_FLAG; else flags&=~C_FLAG; temp>>=c; seteab(temp); setznp8(temp); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); flags|=A_FLAG; break; case 0x38: /*SAR b,CL*/ if ((temp>>(c-1))&1) flags|=C_FLAG; else flags&=~C_FLAG; while (c>0) { temp>>=1; if (temp&0x40) temp|=0x80; c--; cycles-=4; } seteab(temp); setznp8(temp); cycles-=((cpu_mod==3)?8:28); flags|=A_FLAG; break; // default: // printf("Bad D2 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0xD3: fetchea(); tempw=geteaw(); c=CL; // cycles-=c; if (!c) break; // if (c>15) printf("Shiftw %i %02X\n",rmdat&0x38,c); switch (rmdat&0x38) { case 0x00: /*ROL w,CL*/ while (c>0) { temp=(tempw&0x8000)?1:0; tempw=(tempw<<1)|temp; c--; cycles-=4; } if (temp) flags|=C_FLAG; else flags&=~C_FLAG; seteaw(tempw); if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x08: /*ROR w,CL*/ while (c>0) { tempw2=(tempw&1)?0x8000:0; tempw=(tempw>>1)|tempw2; c--; cycles-=4; } if (tempw2) flags|=C_FLAG; else flags&=~C_FLAG; seteaw(tempw); if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x10: /*RCL w,CL*/ while (c>0) { templ=flags&C_FLAG; if (tempw&0x8000) flags|=C_FLAG; else flags&=~C_FLAG; tempw=(tempw<<1)|templ; c--; cycles-=4; } if (temp) flags|=C_FLAG; else flags&=~C_FLAG; seteaw(tempw); if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x18: /*RCR w,CL*/ while (c>0) { templ=flags&C_FLAG; tempw2=(templ&1)?0x8000:0; if (tempw&1) flags|=C_FLAG; else flags&=~C_FLAG; tempw=(tempw>>1)|tempw2; c--; cycles-=4; } if (tempw2) flags|=C_FLAG; else flags&=~C_FLAG; seteaw(tempw); if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; case 0x20: case 0x30: /*SHL w,CL*/ if (c>16) { tempw=0; flags&=~C_FLAG; } else { if ((tempw<<(c-1))&0x8000) flags|=C_FLAG; else flags&=~C_FLAG; tempw<<=c; } seteaw(tempw); setznp16(tempw); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); flags|=A_FLAG; break; case 0x28: /*SHR w,CL*/ if ((tempw>>(c-1))&1) flags|=C_FLAG; else flags&=~C_FLAG; tempw>>=c; seteaw(tempw); setznp16(tempw); cycles-=(c*4); cycles-=((cpu_mod==3)?8:28); flags|=A_FLAG; break; case 0x38: /*SAR w,CL*/ tempw2=tempw&0x8000; if ((tempw>>(c-1))&1) flags|=C_FLAG; else flags&=~C_FLAG; while (c>0) { tempw=(tempw>>1)|tempw2; c--; cycles-=4; } seteaw(tempw); setznp16(tempw); cycles-=((cpu_mod==3)?8:28); flags|=A_FLAG; break; // default: // printf("Bad D3 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0xD4: /*AAM*/ tempws=FETCH(); AH=AL/tempws; AL%=tempws; setznp16(AX); cycles-=83; break; case 0xD5: /*AAD*/ tempws=FETCH(); AL=(AH*tempws)+AL; AH=0; setznp16(AX); cycles-=60; break; case 0xD6: /*SETALC*/ AL = (flags & C_FLAG) ? 0xff : 0; cycles -= 4; break; case 0xD7: /*XLAT*/ addr=BX+AL; cpu_state.last_ea = addr; AL=readmemb(ds+addr); cycles-=11; break; case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/ case 0xDC: case 0xDE: case 0xDF: case 0xD8: fetchea(); geteab(); break; case 0xE0: /*LOOPNE*/ offset=(int8_t)FETCH(); CX--; if (CX && !(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=6; break; case 0xE1: /*LOOPE*/ offset=(int8_t)FETCH(); CX--; if (CX && (flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=6; break; case 0xE2: /*LOOP*/ // printf("LOOP start\n"); offset=(int8_t)FETCH(); CX--; if (CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=5; // printf("LOOP end!\n"); break; case 0xE3: /*JCXZ*/ offset=(int8_t)FETCH(); if (!CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } cycles-=6; break; case 0xE4: /*IN AL*/ temp=FETCH(); AL=inb(temp); cycles-=14; break; case 0xE5: /*IN AX*/ temp=FETCH(); AL=inb(temp); AH=inb(temp+1); cycles-=14; break; case 0xE6: /*OUT AL*/ temp=FETCH(); outb(temp,AL); cycles-=14; break; case 0xE7: /*OUT AX*/ temp=FETCH(); outb(temp,AL); outb(temp+1,AH); cycles-=14; break; case 0xE8: /*CALL rel 16*/ tempw=getword(); if (ssegs) ss=oldss; // writememb(ss+((SP-1)&0xFFFF),pc>>8); writememw(ss,((SP-2)&0xFFFF),cpu_state.pc); SP-=2; cpu_state.last_ea = SP; cpu_state.pc+=tempw; cycles-=23; FETCHCLEAR(); break; case 0xE9: /*JMP rel 16*/ // pclog("PC was %04X\n",cpu_state.pc); tempw = getword(); cpu_state.pc += tempw; // pclog("PC now %04X\n",cpu_state.pc); cycles-=15; FETCHCLEAR(); break; case 0xEA: /*JMP far*/ addr=getword(); tempw=getword(); cpu_state.pc=addr; // printf("EA\n"); loadcs(tempw); // cs=loadcs(CS); // cs=CS<<4; cycles-=15; FETCHCLEAR(); break; case 0xEB: /*JMP rel*/ offset=(int8_t)FETCH(); cpu_state.pc+=offset; cycles-=15; FETCHCLEAR(); break; case 0xEC: /*IN AL,DX*/ AL=inb(DX); cycles-=12; break; case 0xED: /*IN AX,DX*/ AL=inb(DX); AH=inb(DX+1); cycles-=12; break; case 0xEE: /*OUT DX,AL*/ outb(DX,AL); cycles-=12; break; case 0xEF: /*OUT DX,AX*/ outb(DX,AL); outb(DX+1,AH); cycles-=12; break; case 0xF0: /*LOCK*/ case 0xF1: /*LOCK alias*/ cycles-=4; break; case 0xF2: /*REPNE*/ rep(0); break; case 0xF3: /*REPE*/ rep(1); break; case 0xF4: /*HLT*/ // printf("IN HLT!!!! %04X:%04X %08X %08X %08X\n",oldcs,oldpc,old8,old82,old83); /* if (!(flags & I_FLAG)) { pclog("HLT\n"); dumpregs(); exit(-1); }*/ inhlt=1; cpu_state.pc--; FETCHCLEAR(); cycles-=2; break; case 0xF5: /*CMC*/ flags^=C_FLAG; cycles-=2; break; case 0xF6: fetchea(); temp=geteab(); switch (rmdat&0x38) { case 0x00: /*TEST b,#8*/ temp2=FETCH(); temp&=temp2; setznp8(temp); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?5:11); break; case 0x10: /*NOT b*/ temp=~temp; seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x18: /*NEG b*/ setsub8(0,temp); temp=0-temp; seteab(temp); cycles-=((cpu_mod==3)?3:24); break; case 0x20: /*MUL AL,b*/ setznp8(AL); AX=AL*temp; if (AX) flags&=~Z_FLAG; else flags|=Z_FLAG; if (AH) flags|=(C_FLAG|V_FLAG); else flags&=~(C_FLAG|V_FLAG); cycles-=70; break; case 0x28: /*IMUL AL,b*/ setznp8(AL); tempws=(int)((int8_t)AL)*(int)((int8_t)temp); AX=tempws&0xFFFF; if (AX) flags&=~Z_FLAG; else flags|=Z_FLAG; if (AH) flags|=(C_FLAG|V_FLAG); else flags&=~(C_FLAG|V_FLAG); cycles-=80; break; case 0x30: /*DIV AL,b*/ tempw=AX; if (temp) { tempw2=tempw%temp; /* if (!tempw) { writememw((ss+SP)-2,flags|0xF000); writememw((ss+SP)-4,cs>>4); writememw((ss+SP)-6,pc); SP-=6; flags&=~I_FLAG; pc=readmemw(0); cs=readmemw(2)<<4; printf("Div by zero %04X:%04X\n",cs>>4,pc); // dumpregs(); // exit(-1); } else {*/ AH=tempw2; tempw/=temp; AL=tempw&0xFF; // } } else { printf("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; flags&=~I_FLAG; flags&=~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F6 30\n"); loadcs(readmemw(0,2)); FETCHCLEAR(); // cs=loadcs(CS); // cs=CS<<4; // printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x30); // dumpregs(); // exit(-1); } cycles-=80; break; case 0x38: /*IDIV AL,b*/ tempws=(int)AX; if (temp) { tempw2=tempws%(int)((int8_t)temp); /* if (!tempw) { writememw((ss+SP)-2,flags|0xF000); writememw((ss+SP)-4,cs>>4); writememw((ss+SP)-6,pc); SP-=6; flags&=~I_FLAG; pc=readmemw(0); cs=readmemw(2)<<4; printf("Div by zero %04X:%04X\n",cs>>4,pc); } else {*/ AH=tempw2&0xFF; tempws/=(int)((int8_t)temp); AL=tempws&0xFF; // } } else { printf("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; flags&=~I_FLAG; flags&=~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F6 38\n"); loadcs(readmemw(0,2)); FETCHCLEAR(); // cs=loadcs(CS); // cs=CS<<4; // printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38); } cycles-=101; break; // default: // printf("Bad F6 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0xF7: fetchea(); tempw=geteaw(); switch (rmdat&0x38) { case 0x00: /*TEST w*/ tempw2=getword(); setznp16(tempw&tempw2); flags&=~(C_FLAG|V_FLAG|A_FLAG); cycles-=((cpu_mod==3)?5:11); break; case 0x10: /*NOT w*/ seteaw(~tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x18: /*NEG w*/ setsub16(0,tempw); tempw=0-tempw; seteaw(tempw); cycles-=((cpu_mod==3)?3:24); break; case 0x20: /*MUL AX,w*/ setznp16(AX); templ=AX*tempw; // if (output) printf("%04X*%04X=%08X\n",AX,tempw,templ); AX=templ&0xFFFF; DX=templ>>16; if (AX|DX) flags&=~Z_FLAG; else flags|=Z_FLAG; if (DX) flags|=(C_FLAG|V_FLAG); else flags&=~(C_FLAG|V_FLAG); cycles-=118; break; case 0x28: /*IMUL AX,w*/ setznp16(AX); // printf("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw)); tempws=(int)((int16_t)AX)*(int)((int16_t)tempw); if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG); else flags&=~(C_FLAG|V_FLAG); // printf("%i ",tempws); AX=tempws&0xFFFF; tempws=(uint16_t)(tempws>>16); DX=tempws&0xFFFF; // printf("%04X %04X\n",AX,DX); // dumpregs(); // exit(-1); if (AX|DX) flags&=~Z_FLAG; else flags|=Z_FLAG; cycles-=128; break; case 0x30: /*DIV AX,w*/ templ=(DX<<16)|AX; // printf("DIV %08X/%04X\n",templ,tempw); if (tempw) { tempw2=templ%tempw; DX=tempw2; templ/=tempw; AX=templ&0xFFFF; } else { printf("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; flags&=~I_FLAG; flags&=~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F7 30\n"); loadcs(readmemw(0,2)); FETCHCLEAR(); } cycles-=144; break; case 0x38: /*IDIV AX,w*/ tempws=(int)((DX<<16)|AX); // printf("IDIV %i %i ",tempws,tempw); if (tempw) { tempw2=tempws%(int)((int16_t)tempw); // printf("%04X ",tempw2); DX=tempw2; tempws/=(int)((int16_t)tempw); AX=tempws&0xFFFF; } else { printf("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); writememw(ss,(SP-2)&0xFFFF,flags|0xF000); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); SP-=6; flags&=~I_FLAG; flags&=~T_FLAG; cpu_state.pc=readmemw(0,0); // printf("F7 38\n"); loadcs(readmemw(0,2)); FETCHCLEAR(); } cycles-=165; break; // default: // printf("Bad F7 opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; case 0xF8: /*CLC*/ flags&=~C_FLAG; cycles-=2; break; case 0xF9: /*STC*/ // printf("STC %04X\n",pc); flags|=C_FLAG; cycles-=2; break; case 0xFA: /*CLI*/ flags&=~I_FLAG; // printf("CLI at %04X:%04X\n",cs>>4,pc); cycles-=3; break; case 0xFB: /*STI*/ flags|=I_FLAG; // printf("STI at %04X:%04X\n",cs>>4,pc); cycles-=2; break; case 0xFC: /*CLD*/ flags&=~D_FLAG; cycles-=2; break; case 0xFD: /*STD*/ flags|=D_FLAG; cycles-=2; break; case 0xFE: /*INC/DEC b*/ fetchea(); temp=geteab(); flags&=~V_FLAG; if (rmdat&0x38) { setsub8nc(temp,1); temp2=temp-1; if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG; } else { setadd8nc(temp,1); temp2=temp+1; if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG; } // setznp8(temp2); seteab(temp2); cycles-=((cpu_mod==3)?3:23); break; case 0xFF: fetchea(); switch (rmdat&0x38) { case 0x00: /*INC w*/ tempw=geteaw(); setadd16nc(tempw,1); // setznp16(tempw+1); seteaw(tempw+1); cycles-=((cpu_mod==3)?3:23); break; case 0x08: /*DEC w*/ tempw=geteaw(); // setsub16(tempw,1); setsub16nc(tempw,1); // setznp16(tempw-1); seteaw(tempw-1); // if (output) printf("DEC - %04X\n",tempw); cycles-=((cpu_mod==3)?3:23); break; case 0x10: /*CALL*/ tempw=geteaw(); if (ssegs) ss=oldss; writememw(ss,(SP-2)&0xFFFF,cpu_state.pc); SP-=2; cpu_state.last_ea = SP; cpu_state.pc=tempw; // printf("FF 10\n"); cycles-=((cpu_mod==3)?20:29); FETCHCLEAR(); break; case 0x18: /*CALL far*/ tempw=readmemw(easeg,eaaddr); tempw2=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2(); tempw3=CS; tempw4=cpu_state.pc; if (ssegs) ss=oldss; cpu_state.pc=tempw; // printf("FF 18\n"); loadcs(tempw2); writememw(ss,(SP-2)&0xFFFF,tempw3); writememw(ss,((SP-4)&0xFFFF),tempw4); SP-=4; cpu_state.last_ea = SP; cycles-=53; FETCHCLEAR(); break; case 0x20: /*JMP*/ cpu_state.pc=geteaw(); // printf("FF 20\n"); cycles-=((cpu_mod==3)?11:18); FETCHCLEAR(); break; case 0x28: /*JMP far*/ cpu_state.pc=readmemw(easeg,eaaddr); //geteaw(); // printf("FF 28\n"); loadcs(readmemw(easeg,(eaaddr+2)&0xFFFF)); //geteaw2(); // cs=loadcs(CS); // cs=CS<<4; cycles-=24; FETCHCLEAR(); break; case 0x30: /*PUSH w*/ case 0x38: /*PUSH w alias, reported by reenigne*/ tempw=geteaw(); // if (output) printf("PUSH %04X %i %02X %04X %04X %02X %02X\n",tempw,rm,rmdat,easeg,eaaddr,ram[0x22340+0x5638],ram[0x22340+0x5639]); if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),tempw); SP-=2; cpu_state.last_ea = SP; cycles-=((cpu_mod==3)?15:24); break; // default: // printf("Bad FF opcode %02X\n",rmdat&0x38); // dumpregs(); // exit(-1); } break; default: FETCH(); cycles-=8; break; /* printf("Bad opcode %02X at %04X:%04X from %04X:%04X %08X\n",opcode,cs>>4,pc,old8>>16,old8&0xFFFF,old82); dumpregs(); exit(-1);*/ } cpu_state.pc&=0xFFFF; /* if ((CS & 0xf000) == 0xa000) { dumpregs(); exit(-1); }*/ // output = 3; /* if (CS == 0xf000) { dumpregs(); exit(-1); } output = 3;*/ if (ssegs) { ds=oldds; ss=oldss; ssegs=0; } // output = 3; // if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks); FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks); if ((cycdiff-cycles)