pcem/src/808x.c

3641 lines
159 KiB
C
Raw Blame History

//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 <unistd.h>
#include <stdio.h>
#include "ibm.h"
#include "x86_ops.h"
#include "codegen.h"
#include "cpu.h"
#include "keyboard.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "timer.h"
#include "x86.h"
#include "x87.h"
#include "paths.h"
uint64_t xt_cpu_multi;
int nmi = 0;
int nmi_auto_clear = 0;
int oldcpl;
int tempc;
static int noint=0;
int output=0;
int timetolive=0;
int ins=0;
int is8086=0;
static uint32_t oldds;
uint32_t oldss;
static int nextcyc=0;
static int memcycs;
static int cycdiff;
static void FETCHCOMPLETE();
#define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint)
static 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));
}
static uint8_t readmembf(uint32_t a)
{
if (readlookup2[(a)>>12]==-1) return readmembl(a);
else return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}
static 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(); }
static 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;
}
static 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;
}
//#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a))
static int fetchcycles=0,fetchclocks;
static uint8_t prefetchqueue[6];
static uint16_t prefetchpc;
static int prefetchw=0;
static 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;
}
static 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;
}
static 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));
}
static 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
<20><><EFBFBD><EFBFBD>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.
<20>Ŀ <20>Mod R/M<> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ModR/M Values in Hexadecimal<61><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
[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
*/
uint32_t easeg;
uint32_t rmdat;
static 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) { cpu_state.eaaddr=getword(); easeg=ds; FETCHADD(6); }
else
{
switch (cpu_mod)
{
case 0:
cpu_state.eaaddr=0;
if (cpu_rm&4) FETCHADD(5);
else FETCHADD(7+slowrm[cpu_rm]);
break;
case 1:
cpu_state.eaaddr=(uint16_t)(int8_t)FETCH();
if (cpu_rm&4) FETCHADD(9);
else FETCHADD(11+slowrm[cpu_rm]);
break;
case 2:
cpu_state.eaaddr=getword();
if (cpu_rm&4) FETCHADD(9);
else FETCHADD(11+slowrm[cpu_rm]);
break;
}
cpu_state.eaaddr+=(*mod1add[0][cpu_rm])+(*mod1add[1][cpu_rm]);
easeg=*mod1seg[cpu_rm];
cpu_state.eaaddr&=0xFFFF;
}
}
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+cpu_state.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,cpu_state.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,(cpu_state.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+cpu_state.eaaddr,val);
}
}
static inline void seteaw(uint16_t val)
{
if (cpu_mod == 3)
cpu_state.regs[cpu_rm].w = val;
else
{
writememw(easeg,cpu_state.eaaddr,val);
// writememb(easeg+eaaddr+1,val>>8);
}
}
/*Flags*/
uint8_t znptable8[256];
static 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 indump = 0;
void dumpregs()
{
int c,d=0,e=0;
#ifndef RELEASE_BUILD
FILE *f;
if (indump) return;
indump = 1;
// return;
output=0;
// return;
// savenvr();
// return;
chdir(logs_path);
/* 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++)
{
cpu_state.abrt = 0;
putc(readmembl(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,cpu_state.flags);
printf("%04X\n",cpu_state.oldpc);
printf("%i ins\n",ins);
if (is386)
printf("In %s mode\n",(msw&1)?((cpu_state.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,cpu_state.seg_cs.limit,cpu_state.seg_cs.access, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high);
printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,cpu_state.seg_ds.limit,cpu_state.seg_ds.access, cpu_state.seg_ds.limit_low, cpu_state.seg_ds.limit_high);
printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,cpu_state.seg_es.limit,cpu_state.seg_es.access, cpu_state.seg_es.limit_low, cpu_state.seg_es.limit_high);
if (is386)
{
printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cpu_state.seg_fs.base,cpu_state.seg_fs.limit,cpu_state.seg_fs.access, cpu_state.seg_fs.limit_low, cpu_state.seg_fs.limit_high);
printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,cpu_state.seg_gs.limit,cpu_state.seg_gs.access, cpu_state.seg_gs.limit_low, cpu_state.seg_gs.limit_high);
}
printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,cpu_state.seg_ss.limit,cpu_state.seg_ss.access, cpu_state.seg_ss.limit_low, cpu_state.seg_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 CR4=%08x\n",cr0,cr2,cr3, cr4);
}
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 x86_was_reset = 0;
void resetx86()
{
pclog("x86 reset\n");
ins = 0;
use32=0;
cpu_cur_status = 0;
stack32=0;
// i86_Reset();
// cs=0xFFFF0;
msw=0;
if (is486)
cr0 = 1 << 30;
else
cr0 = 0;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
cr4 = 0;
cpu_state.eflags=0;
cgate32=0;
if (AT)
{
loadcs(0xF000);
cpu_state.pc = 0xFFF0;
rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
}
else
{
loadcs(0xFFFF);
cpu_state.pc = 0;
rammask = 0xfffff;
}
idt.base = 0;
idt.limit = is386 ? 0x03FF : 0xFFFF;
cpu_state.flags=2;
EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
makeznptable();
resetreadlookup();
makemod1table();
FETCHCLEAR();
x87_reset();
cpu_set_edx();
mmu_perm=4;
x86seg_reset();
codegen_reset();
x86_was_reset = 1;
}
void softresetx86()
{
// dumpregs();
// exit(-1);
use32=0;
stack32=0;
cpu_cur_status = 0;
// i86_Reset();
// cs=0xFFFF0;
msw=0;
if (is486)
cr0 = 1 << 30;
else
cr0 = 0;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
cr4 = 0;
cpu_state.eflags=0;
cgate32=0;
if (AT)
{
loadcs(0xF000);
cpu_state.pc = 0xFFF0;
rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
}
else
{
loadcs(0xFFFF);
cpu_state.pc = 0;
rammask = 0xfffff;
}
//rammask=0xFFFFFFFF;
cpu_state.flags=2;
idt.base = 0;
if (is386)
{
idt.limit = 0x03FF;
EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
}
else
{
idt.limit = 0xFFFF;
}
x86seg_reset();
flushmmucache();
x86_was_reset = 1;
}
static void setznp8(uint8_t val)
{
cpu_state.flags &= ~0xC4;
cpu_state.flags |= znptable8[val];
}
static void setznp16(uint16_t val)
{
cpu_state.flags &= ~0xC4;
cpu_state.flags |= znptable16[val];
}
static void setadd8(uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t)a + (uint16_t)b;
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= znptable8[c&0xFF];
if (c & 0x100)
cpu_state.flags |= C_FLAG;
if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
cpu_state.flags |= V_FLAG;
if (((a & 0xF) + (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setadd8nc(uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t)a + (uint16_t)b;
cpu_state.flags &= ~0x8D4;
cpu_state.flags |= znptable8[c&0xFF];
if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
cpu_state.flags |= V_FLAG;
if (((a & 0xF) + (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setadc8(uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t)a + (uint16_t)b+tempc;
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= znptable8[c&0xFF];
if (c & 0x100)
cpu_state.flags |= C_FLAG;
if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
cpu_state.flags |= V_FLAG;
if (((a & 0xF) + (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setadd16(uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t)a + (uint32_t)b;
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= znptable16[c&0xFFFF];
if (c & 0x10000)
cpu_state.flags |= C_FLAG;
if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
cpu_state.flags |= V_FLAG;
if (((a & 0xF) + (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setadd16nc(uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t)a + (uint32_t)b;
cpu_state.flags &= ~0x8D4;
cpu_state.flags |= znptable16[c&0xFFFF];
if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
cpu_state.flags |= V_FLAG;
if (((a & 0xF) + (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setadc16(uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t)a + (uint32_t)b+tempc;
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= znptable16[c&0xFFFF];
if (c & 0x10000)
cpu_state.flags |= C_FLAG;
if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
cpu_state.flags |= V_FLAG;
if (((a & 0xF) + (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setsub8(uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t)a - (uint16_t)b;
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= znptable8[c&0xFF];
if (c & 0x100)
cpu_state.flags |= C_FLAG;
if ((a ^ b) & (a ^ c) & 0x80)
cpu_state.flags |= V_FLAG;
if (((a & 0xF) - (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setsub8nc(uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t)a - (uint16_t)b;
cpu_state.flags &= ~0x8D4;
cpu_state.flags |= znptable8[c&0xFF];
if ((a ^ b) & (a ^ c) & 0x80)
cpu_state.flags |= V_FLAG;
if (((a & 0xF) - (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setsbc8(uint8_t a, uint8_t b)
{
uint16_t c = (uint16_t)a - (((uint16_t)b) + tempc);
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= znptable8[c&0xFF];
if (c & 0x100)
cpu_state.flags |= C_FLAG;
if ((a ^ b) & (a ^ c) & 0x80)
cpu_state.flags |= V_FLAG;
if (((a & 0xF) - (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setsub16(uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t)a - (uint32_t)b;
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= znptable16[c&0xFFFF];
if (c & 0x10000)
cpu_state.flags |= C_FLAG;
if ((a ^ b) & (a ^ c) & 0x8000)
cpu_state.flags |= V_FLAG;
if (((a & 0xF) - (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setsub16nc(uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t)a - (uint32_t)b;
cpu_state.flags &= ~0x8D4;
cpu_state.flags |= (znptable16[c&0xFFFF]&~4);
cpu_state.flags |= (znptable8[c&0xFF]&4);
if ((a ^ b) & (a ^ c) & 0x8000)
cpu_state.flags |= V_FLAG;
if (((a & 0xF) - (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
static void setsbc16(uint16_t a, uint16_t b)
{
uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc);
cpu_state.flags &= ~0x8D5;
cpu_state.flags |= (znptable16[c&0xFFFF]&~4);
cpu_state.flags |= (znptable8[c&0xFF]&4);
if (c & 0x10000)
cpu_state.flags |= C_FLAG;
if ((a ^ b) & (a ^ c) & 0x8000)
cpu_state.flags |= V_FLAG;
if (((a & 0xF) - (b & 0xF)) & 0x10)
cpu_state.flags |= A_FLAG;
}
int current_diff = 0;
/*XT systems use the XT master oscillator (14.318 MHz) rather than the CPU clock
at the base timer frequency. Because there isn't an integer relationship
between the two frequencies, use fixed point arithmetic when updating TSC.*/
static uint64_t tsc_frac = 0;
static void clockhardware()
{
int diff = cycdiff - cycles - current_diff;
current_diff += diff;
tsc_frac += (uint64_t)diff * xt_cpu_multi;
tsc += (tsc_frac >> 32);
tsc_frac &= 0xffffffff;
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
}
static int takeint = 0;
int firstrepcycle=1;
static void rep(int fv)
{
uint8_t temp;
int c=CX;
uint8_t temp2;
uint16_t tempw,tempw2;
uint16_t ipc = cpu_state.oldpc;//pc-1;
int changeds=0;
uint32_t oldds = ds;
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 (cpu_state.flags & D_FLAG) SI--;
else SI++;
c--;
cycles-=5;
}
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.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 (cpu_state.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 (cpu_state.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) cpu_state.flags |= Z_FLAG;
else cpu_state.flags &= ~Z_FLAG;
while ((c>0) && (fv==((cpu_state.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 (cpu_state.flags & D_FLAG) { DI--; SI--; }
else { DI++; SI++; }
c--;
cycles -= 30;
setsub8(temp,temp2);
clockhardware();
FETCHADD(30 - memcycs);
}
if (IRQTEST && c>0 && (fv==((cpu_state.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) cpu_state.flags |= Z_FLAG;
else cpu_state.flags &= ~Z_FLAG;
while ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)) && !IRQTEST)
{
memcycs=0;
tempw=readmemw(ds,SI);
tempw2=readmemw(es,DI);
if (cpu_state.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==((cpu_state.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 (cpu_state.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 (cpu_state.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 (cpu_state.flags & D_FLAG) SI--;
else SI++;
c--;
cycles-=4;
}
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); }
else firstrepcycle=1;
break;
case 0xAD: /*REP LODSW*/
if (c>0)
{
tempw2=readmemw(ds,SI);
if (cpu_state.flags & D_FLAG) SI -= 2;
else SI += 2;
c--;
cycles-=4;
}
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); }
else firstrepcycle=1;
break;
case 0xAE: /*REP SCASB*/
if (fv) cpu_state.flags |= Z_FLAG;
else cpu_state.flags &= ~Z_FLAG;
if ((c>0) && (fv==((cpu_state.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 (cpu_state.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==((cpu_state.flags & Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); }
else firstrepcycle=1;
// cycles-=120;
break;
case 0xAF: /*REP SCASW*/
if (fv) cpu_state.flags |= Z_FLAG;
else cpu_state.flags &= ~Z_FLAG;
if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)))
{
tempw=readmemw(es,DI);
setsub16(AX,tempw);
if (cpu_state.flags & D_FLAG) DI -= 2;
else DI += 2;
c--;
cycles -= 15;
}
if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.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();
}
static int inhlt=0;
static int skipnextprint=0;
#include "8087.h"
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)
{
uint8_t opcode;
cycdiff=cycles;
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;
cpu_state.oldpc = cpu_state.pc;
opcodestart:
opcode=FETCH();
tempc = cpu_state.flags & C_FLAG;
trap = cpu_state.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,cpu_state.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 (cpu_state.ssegs) ss=oldss;
writememw(ss,((SP-2)&0xFFFF),ES);
SP-=2;
cycles-=14;
break;
case 0x07: /*POP ES*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
loadseg(tempw,&cpu_state.seg_es);
SP+=2;
cycles-=12;
break;
case 0x08: /*OR 8,reg*/
fetchea();
temp=geteab();
temp|=getr8(cpu_reg);
setznp8(temp);
cpu_state.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);
cpu_state.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);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
setr8(cpu_reg,temp);
cycles-=((cpu_mod==3)?3:13);
break;
case 0x0B: /*OR cpu_reg,16*/
fetchea();
tempw=geteaw();
tempw|=cpu_state.regs[cpu_reg].w;
setznp16(tempw);
cpu_state.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);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x0D: /*OR AX,#16*/
AX|=getword();
setznp16(AX);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x0E: /*PUSH CS*/
if (cpu_state.ssegs) ss=oldss;
writememw(ss,((SP-2)&0xFFFF),CS);
SP-=2;
cycles-=14;
break;
case 0x0F: /*POP CS - 8088/8086 only*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
loadseg(tempw,&cpu_state.seg_cs);
SP+=2;
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 (cpu_state.ssegs) ss=oldss;
writememw(ss,((SP-2)&0xFFFF),SS);
SP-=2;
cycles-=14;
break;
case 0x17: /*POP SS*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
loadseg(tempw,&cpu_state.seg_ss);
SP+=2;
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 (cpu_state.ssegs) ss=oldss;
writememw(ss,((SP-2)&0xFFFF),DS);
SP-=2;
cycles-=14;
break;
case 0x1F: /*POP DS*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
loadseg(tempw,&cpu_state.seg_ds);
if (cpu_state.ssegs) oldds=ds;
SP+=2;
cycles-=12;
break;
case 0x20: /*AND 8,reg*/
fetchea();
temp=geteab();
temp&=getr8(cpu_reg);
setznp8(temp);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x25: /*AND AX,#16*/
AX&=getword();
setznp16(AX);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x26: /*ES:*/
oldss=ss;
oldds=ds;
ds=ss=es;
cpu_state.ssegs=2;
cycles-=4;
goto opcodestart;
// break;
case 0x27: /*DAA*/
if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
tempi = ((uint16_t)AL) + 6;
AL += 6;
cpu_state.flags |= A_FLAG;
if (tempi & 0x100)
cpu_state.flags |= C_FLAG;
}
// else
// flags&=~A_FLAG;
if ((cpu_state.flags & C_FLAG) || (AL > 0x9F))
{
AL += 0x60;
cpu_state.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;
cpu_state.ssegs=2;
cycles-=4;
goto opcodestart;
case 0x2F: /*DAS*/
if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
tempi = ((uint16_t)AL) - 6;
AL -= 6;
cpu_state.flags |= A_FLAG;
if (tempi & 0x100)
cpu_state.flags |= C_FLAG;
}
// else
// flags&=~A_FLAG;
if ((cpu_state.flags & C_FLAG) || (AL > 0x9F))
{
AL -= 0x60;
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x35: /*XOR AX,#16*/
AX^=getword();
setznp16(AX);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x36: /*SS:*/
oldss=ss;
oldds=ds;
ds=ss=ss;
cpu_state.ssegs=2;
cycles-=4;
goto opcodestart;
// break;
case 0x37: /*AAA*/
if ((cpu_state.flags & A_FLAG)||((AL & 0xF) > 9))
{
AL += 6;
AH++;
cpu_state.flags |= (A_FLAG|C_FLAG);
}
else
cpu_state.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;
cpu_state.ssegs=2;
cycles-=4;
goto opcodestart;
// break;
case 0x3F: /*AAS*/
if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
AL -= 6;
AH--;
cpu_state.flags |= (A_FLAG|C_FLAG);
}
else
cpu_state.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 (cpu_state.ssegs) ss=oldss;
SP-=2;
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 (cpu_state.ssegs) ss=oldss;
SP+=2;
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 (cpu_state.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 (!(cpu_state.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 (cpu_state.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 (!(cpu_state.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 (cpu_state.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 (!(cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
break;
case 0x66: /*JBE alias*/
case 0x76: /*JBE*/
offset=(int8_t)FETCH();
if (cpu_state.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 (!(cpu_state.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 (cpu_state.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 (!(cpu_state.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 (cpu_state.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 (!(cpu_state.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=(cpu_state.flags & N_FLAG)?1:0;
temp2=(cpu_state.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=(cpu_state.flags & N_FLAG)?1:0;
temp2=(cpu_state.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=(cpu_state.flags & N_FLAG)?1:0;
temp2=(cpu_state.flags & V_FLAG)?1:0;
if ((cpu_state.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=(cpu_state.flags & N_FLAG)?1:0;
temp2=(cpu_state.flags & V_FLAG)?1:0;
if (!((cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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);
cpu_state.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 (cpu_state.ssegs) ds=oldds;
seteaw(DS);
break;
case 0x10: /*SS*/
if (cpu_state.ssegs) ss=oldss;
seteaw(SS);
break;
}
cycles-=((cpu_mod==3)?2:13);
break;
case 0x8D: /*LEA*/
fetchea();
cpu_state.regs[cpu_reg].w=cpu_state.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,&cpu_state.seg_es);
break;
case 0x08: /*CS - 8088/8086 only*/
tempw=geteaw();
loadseg(tempw,&cpu_state.seg_cs);
break;
case 0x18: /*DS*/
tempw=geteaw();
loadseg(tempw,&cpu_state.seg_ds);
if (cpu_state.ssegs) oldds=ds;
break;
case 0x10: /*SS*/
tempw=geteaw();
loadseg(tempw,&cpu_state.seg_ss);
if (cpu_state.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 (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
SP+=2;
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 (cpu_state.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;
cycles-=36;
FETCHCLEAR();
break;
case 0x9B: /*WAIT*/
cycles-=4;
break;
case 0x9C: /*PUSHF*/
if (cpu_state.ssegs) ss=oldss;
writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000);
SP-=2;
cycles-=14;
break;
case 0x9D: /*POPF*/
if (cpu_state.ssegs) ss=oldss;
cpu_state.flags = readmemw(ss,SP) & 0xFFF;
SP+=2;
cycles-=12;
break;
case 0x9E: /*SAHF*/
cpu_state.flags = (cpu_state.flags & 0xFF00) | AH;
cycles-=4;
break;
case 0x9F: /*LAHF*/
AH = cpu_state.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-=14;
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 (cpu_state.flags & D_FLAG) { DI--; SI--; }
else { DI++; SI++; }
cycles-=18;
break;
case 0xA5: /*MOVSW*/
tempw=readmemw(ds,SI);
writememw(es,DI,tempw);
if (cpu_state.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 (cpu_state.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 (cpu_state.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);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=5;
break;
case 0xA9: /*TEST AX,#16*/
tempw=getword();
setznp16(AX&tempw);
cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=5;
break;
case 0xAA: /*STOSB*/
writememb(es+DI,AL);
if (cpu_state.flags & D_FLAG) DI--;
else DI++;
cycles-=11;
break;
case 0xAB: /*STOSW*/
writememw(es,DI,AX);
if (cpu_state.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 (cpu_state.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 (cpu_state.flags & D_FLAG) SI -= 2;
else SI += 2;
cycles-=16;
break;
case 0xAE: /*SCASB*/
temp=readmemb(es+DI);
setsub8(AL,temp);
if (cpu_state.flags & D_FLAG) DI--;
else DI++;
cycles-=19;
break;
case 0xAF: /*SCASW*/
tempw=readmemw(es,DI);
setsub16(AX,tempw);
if (cpu_state.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 (cpu_state.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 (cpu_state.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,cpu_state.eaaddr); //geteaw();
tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); //geteaw2();
loadseg(tempw,&cpu_state.seg_es);
cycles-=24;
break;
case 0xC5: /*LDS*/
fetchea();
cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr);
tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF);
loadseg(tempw,&cpu_state.seg_ds);
if (cpu_state.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 (cpu_state.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 (cpu_state.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 (cpu_state.ssegs) ss=oldss;
writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000);
writememw(ss, ((SP-4)&0xFFFF), CS);
writememw(ss, ((SP-6)&0xFFFF), cpu_state.pc);
SP-=6;
addr=3<<2;
cpu_state.flags &= ~I_FLAG;
cpu_state.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*/
temp=FETCH();
if (cpu_state.ssegs) ss=oldss;
writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000);
writememw(ss, ((SP-4)&0xFFFF), CS);
writememw(ss, ((SP-6)&0xFFFF), cpu_state.pc);
cpu_state.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 (cpu_state.ssegs) ss=oldss;
tempw=CS;
tempw2=cpu_state.pc;
cpu_state.pc=readmemw(ss,SP);
// printf("CF\n");
loadcs(readmemw(ss,((SP+2)&0xFFFF)));
cpu_state.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) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
temp<<=1;
if (cpu_state.flags & C_FLAG)
temp |= 1;
seteab(temp);
// setznp8(temp);
if ((cpu_state.flags&C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x08: /*ROR b,1*/
if (temp&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
temp>>=1;
if (cpu_state.flags & C_FLAG)
temp |= 0x80;
seteab(temp);
// setznp8(temp);
if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x10: /*RCL b,1*/
temp2 = cpu_state.flags & C_FLAG;
if (temp&0x80) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
temp<<=1;
if (temp2) temp|=1;
seteab(temp);
// setznp8(temp);
if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x18: /*RCR b,1*/
temp2 = cpu_state.flags & C_FLAG;
if (temp&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
temp>>=1;
if (temp2) temp|=0x80;
seteab(temp);
// setznp8(temp);
if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x20: case 0x30: /*SHL b,1*/
if (temp&0x80) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
if ((temp^(temp<<1))&0x80) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
temp<<=1;
seteab(temp);
setznp8(temp);
cycles-=((cpu_mod==3)?2:23);
cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR b,1*/
if (temp&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
if (temp&0x80) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
temp>>=1;
seteab(temp);
setznp8(temp);
cycles-=((cpu_mod==3)?2:23);
cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR b,1*/
if (temp&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
temp>>=1;
if (temp&0x40) temp|=0x80;
seteab(temp);
setznp8(temp);
cycles-=((cpu_mod==3)?2:23);
cpu_state.flags |= A_FLAG;
cpu_state.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) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw<<=1;
if (cpu_state.flags & C_FLAG) tempw|=1;
seteaw(tempw);
// setznp16(tempw);
if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x08: /*ROR w,1*/
if (tempw&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw>>=1;
if (cpu_state.flags & C_FLAG) tempw|=0x8000;
seteaw(tempw);
// setznp16(tempw);
if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x10: /*RCL w,1*/
temp2 = cpu_state.flags & C_FLAG;
if (tempw&0x8000) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw<<=1;
if (temp2) tempw|=1;
seteaw(tempw);
if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x18: /*RCR w,1*/
temp2 = cpu_state.flags & C_FLAG;
if (tempw&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw>>=1;
if (temp2) tempw|=0x8000;
seteaw(tempw);
// setznp16(tempw);
if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x20: case 0x30: /*SHL w,1*/
if (tempw&0x8000) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
if ((tempw^(tempw<<1))&0x8000) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
tempw<<=1;
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?2:23);
cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR w,1*/
if (tempw&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
if (tempw&0x8000) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
tempw>>=1;
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?2:23);
cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR w,1*/
if (tempw&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw>>=1;
if (tempw&0x4000) tempw|=0x8000;
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?2:23);
cpu_state.flags |= A_FLAG;
cpu_state.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) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
seteab(temp);
// setznp8(temp);
if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG;
else cpu_state.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) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
seteab(temp);
if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG;
else cpu_state.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=cpu_state.flags & C_FLAG;
temp2=temp&0x80;
temp<<=1;
if (temp2) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
if (templ) temp|=1;
c--;
cycles-=4;
}
// printf("Now %02X\n",temp);
seteab(temp);
if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x18: /*RCR b,CL*/
while (c>0)
{
templ=cpu_state.flags & C_FLAG;
temp2=temp&1;
temp>>=1;
if (temp2) cpu_state.flags |= C_FLAG;
else cpu_state.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) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x20: case 0x30: /*SHL b,CL*/
if (c > 8)
{
temp = 0;
cpu_state.flags &= ~C_FLAG;
}
else
{
if ((temp<<(c-1))&0x80) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
temp<<=c;
}
seteab(temp);
setznp8(temp);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR b,CL*/
if (c > 8)
{
temp = 0;
cpu_state.flags &= ~C_FLAG;
}
else
{
if ((temp>>(c-1))&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
temp>>=c;
}
seteab(temp);
setznp8(temp);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR b,CL*/
if ((temp>>(c-1))&1) cpu_state.flags |= C_FLAG;
else cpu_state.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);
cpu_state.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) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
else cpu_state.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) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x10: /*RCL w,CL*/
while (c>0)
{
templ = cpu_state.flags & C_FLAG;
if (tempw&0x8000) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw=(tempw<<1)|templ;
c--;
cycles-=4;
}
if (templ) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x18: /*RCR w,CL*/
while (c>0)
{
templ = cpu_state.flags & C_FLAG;
tempw2=(templ&1)?0x8000:0;
if (tempw&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw=(tempw>>1)|tempw2;
c--;
cycles-=4;
}
if (tempw2) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x20: case 0x30: /*SHL w,CL*/
if (c>16)
{
tempw=0;
cpu_state.flags &= ~C_FLAG;
}
else
{
if ((tempw<<(c-1))&0x8000) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw<<=c;
}
seteaw(tempw);
setznp16(tempw);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR w,CL*/
if (c > 16)
{
tempw = 0;
cpu_state.flags &= ~C_FLAG;
}
else
{
if ((tempw>>(c-1))&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
tempw>>=c;
}
seteaw(tempw);
setznp16(tempw);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR w,CL*/
tempw2=tempw&0x8000;
if ((tempw>>(c-1))&1) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
while (c>0)
{
tempw=(tempw>>1)|tempw2;
c--;
cycles-=4;
}
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?8:28);
cpu_state.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 = (cpu_state.flags & C_FLAG) ? 0xff : 0;
cycles -= 4;
break;
case 0xD7: /*XLAT*/
addr=BX+AL;
AL=readmemb(ds+addr);
cycles-=11;
break;
case 0xd8:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_d8_a16[rmdat >> 3](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xd9:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_d9_a16[rmdat](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xda:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_da_a16[rmdat](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xdb:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_db_a16[rmdat](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xdc:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_dc_a16[rmdat >> 3](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xdd:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_dd_a16[rmdat](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xde:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_de_a16[rmdat](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xdf:
fetchea();
if (hasfpu)
{
uint16_t save_pc = cpu_state.pc;
ops_808x_fpu_df_a16[rmdat](rmdat);
cpu_state.pc = save_pc;
}
break;
case 0xE0: /*LOOPNE*/
offset=(int8_t)FETCH();
CX--;
if (CX && !(cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=6;
break;
case 0xE1: /*LOOPE*/
offset=(int8_t)FETCH();
CX--;
if (CX && (cpu_state.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 (cpu_state.ssegs) ss=oldss;
// writememb(ss+((SP-1)&0xFFFF),pc>>8);
writememw(ss,((SP-2)&0xFFFF),cpu_state.pc);
SP-=2;
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 %08X %08X %08X\n",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*/
cpu_state.flags ^= C_FLAG;
cycles-=2;
break;
case 0xF6:
fetchea();
temp=geteab();
switch (rmdat&0x38)
{
case 0x00: /*TEST b,#8*/
case 0x08:
temp2=FETCH();
temp&=temp2;
setznp8(temp);
cpu_state.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) cpu_state.flags &= ~Z_FLAG;
else cpu_state.flags |= Z_FLAG;
if (AH) cpu_state.flags |= (C_FLAG|V_FLAG);
else cpu_state.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) cpu_state.flags &= ~Z_FLAG;
else cpu_state.flags |= Z_FLAG;
if (AH) cpu_state.flags |= (C_FLAG|V_FLAG);
else cpu_state.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,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
cpu_state.flags &= ~I_FLAG;
cpu_state.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,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
cpu_state.flags &= ~I_FLAG;
cpu_state.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*/
case 0x08:
tempw2=getword();
setznp16(tempw&tempw2);
cpu_state.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) cpu_state.flags &= ~Z_FLAG;
else cpu_state.flags |= Z_FLAG;
if (DX) cpu_state.flags |= (C_FLAG|V_FLAG);
else cpu_state.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)) cpu_state.flags |= (C_FLAG|V_FLAG);
else cpu_state.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) cpu_state.flags &= ~Z_FLAG;
else cpu_state.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,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
cpu_state.flags &= ~I_FLAG;
cpu_state.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,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
cpu_state.flags &= ~I_FLAG;
cpu_state.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*/
cpu_state.flags &= ~C_FLAG;
cycles-=2;
break;
case 0xF9: /*STC*/
// printf("STC %04X\n",pc);
cpu_state.flags |= C_FLAG;
cycles-=2;
break;
case 0xFA: /*CLI*/
cpu_state.flags &= ~I_FLAG;
// printf("CLI at %04X:%04X\n",cs>>4,pc);
cycles-=3;
break;
case 0xFB: /*STI*/
cpu_state.flags |= I_FLAG;
// printf("STI at %04X:%04X\n",cs>>4,pc);
cycles-=2;
break;
case 0xFC: /*CLD*/
cpu_state.flags &= ~D_FLAG;
cycles-=2;
break;
case 0xFD: /*STD*/
cpu_state.flags |= D_FLAG;
cycles-=2;
break;
case 0xFE: /*INC/DEC b*/
fetchea();
temp=geteab();
cpu_state.flags &= ~V_FLAG;
if (rmdat&0x38)
{
setsub8nc(temp,1);
temp2=temp-1;
if ((temp&0x80) && !(temp2&0x80)) cpu_state.flags |= V_FLAG;
}
else
{
setadd8nc(temp,1);
temp2=temp+1;
if ((temp2&0x80) && !(temp&0x80)) cpu_state.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 (cpu_state.ssegs) ss=oldss;
writememw(ss,(SP-2)&0xFFFF,cpu_state.pc);
SP-=2;
cpu_state.pc=tempw;
// printf("FF 10\n");
cycles-=((cpu_mod==3)?20:29);
FETCHCLEAR();
break;
case 0x18: /*CALL far*/
tempw=readmemw(easeg,cpu_state.eaaddr);
tempw2=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); //geteaw2();
tempw3=CS;
tempw4=cpu_state.pc;
if (cpu_state.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;
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,cpu_state.eaaddr); //geteaw();
// printf("FF 28\n");
loadcs(readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF)); //geteaw2();
// cs=loadcs(CS);
// cs=CS<<4;
cycles-=24;
FETCHCLEAR();
break;
case 0x30: /*PUSH w*/
tempw=geteaw();
// if (output) printf("PUSH %04X %i %02X %04X %04X %02X %02X\n",tempw,cpu_rm,rmdat,easeg,eaaddr,ram[0x22340+0x5638],ram[0x22340+0x5639]);
if (cpu_state.ssegs) ss=oldss;
writememw(ss,((SP-2)&0xFFFF),tempw);
SP-=2;
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 (cpu_state.ssegs)
{
ds=oldds;
ss=oldss;
cpu_state.ssegs=0;
}
// output = 3;
// if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks);
FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks);
if ((cycdiff-cycles)<memcycs) cycles-=(memcycs-(cycdiff-cycles));
memcycs=0;
insc++;
// output=(CS==0xEB9);
clockhardware();
if (trap && (cpu_state.flags & T_FLAG) && !noint)
{
// printf("TRAP!!! %04X:%04X\n",CS,pc);
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr=1<<2;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
FETCHCLEAR();
}
else if (nmi && nmi_enable && nmi_mask)
{
// output = 3;
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr=2<<2;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
FETCHCLEAR();
nmi_enable = 0;
}
else if (takeint && !cpu_state.ssegs && !noint)
{
temp=picinterrupt();
if (temp!=0xFF)
{
if (inhlt) cpu_state.pc++;
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr=temp<<2;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
// printf("INT INT INT\n");
loadcs(readmemw(0,addr+2));
FETCHCLEAR();
// printf("INTERRUPT\n");
}
}
takeint = (cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask);
if (noint) noint=0;
ins++;
/* if (timetolive)
{
timetolive--;
if (!timetolive) exit(-1); //output=0;
}*/
}
}