summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/i86
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2011-06-16 05:38:49 +0000
committer Miodrag Milanovic <mmicko@gmail.com>2011-06-16 05:38:49 +0000
commit2d60c3dba0f21894ab5f36d28d2a4ed9773ce546 (patch)
tree4363c2a85848689a22c00ff0523e48adf7ea0bfe /src/emu/cpu/i86
parentb6012aaa603334edc988f23ab0c87f3c09a47d75 (diff)
i286 - Fix bunch of fault restarts [Carl]
Diffstat (limited to 'src/emu/cpu/i86')
-rw-r--r--src/emu/cpu/i86/i86priv.h14
-rw-r--r--src/emu/cpu/i86/instr186.c34
-rw-r--r--src/emu/cpu/i86/instr286.c31
-rw-r--r--src/emu/cpu/i86/instr286.h8
-rw-r--r--src/emu/cpu/i86/instr86.c138
5 files changed, 153 insertions, 72 deletions
diff --git a/src/emu/cpu/i86/i86priv.h b/src/emu/cpu/i86/i86priv.h
index d62fe70d86d..a2c2f3ae42c 100644
--- a/src/emu/cpu/i86/i86priv.h
+++ b/src/emu/cpu/i86/i86priv.h
@@ -65,6 +65,13 @@ typedef enum {
#define SUBB(dst,src) { unsigned res=dst-src; SetCFB(res); SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
#define SUBW(dst,src) { unsigned res=dst-src; SetCFW(res); SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+// don't modify CF in case fault occurs
+#define ADCB(dst,src,tmpcf) { unsigned res=dst+src; tmpcf = res & 0x100; SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define ADCW(dst,src,tmpcf) { unsigned res=dst+src; tmpcf = res & 0x10000; SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
+#define SBBB(dst,src,tmpcf) { unsigned res=dst-src; tmpcf = res & 0x100; SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define SBBW(dst,src,tmpcf) { unsigned res=dst-src; tmpcf = res & 0x10000; SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
#define ORB(dst,src) dst |= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Byte(dst)
#define ORW(dst,src) dst |= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Word(dst)
@@ -101,10 +108,17 @@ typedef enum {
#define DefaultSeg(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->prefix_seg : Seg)
#define DefaultBase(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->base[cpustate->prefix_seg] : cpustate->base[Seg])
+#ifdef I80286
+#define GetMemB(Seg,Off) (read_mem_byte(GetMemAddr(cpustate,Seg,Off,1,I80286_READ)))
+#define GetMemW(Seg,Off) (read_mem_word(GetMemAddr(cpustate,Seg,Off,2,I80286_READ)))
+#define PutMemB(Seg,Off,x) write_mem_byte(GetMemAddr(cpustate,Seg,Off,1,I80286_WRITE), (x))
+#define PutMemW(Seg,Off,x) write_mem_word(GetMemAddr(cpustate,Seg,Off,2,I80286_WRITE), (x))
+#else
#define GetMemB(Seg,Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK))
#define GetMemW(Seg,Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK))
#define PutMemB(Seg,Off,x) write_mem_byte((DefaultBase(Seg) + (Off)) & AMASK, (x))
#define PutMemW(Seg,Off,x) write_mem_word((DefaultBase(Seg) + (Off)) & AMASK, (x))
+#endif
#define PEEKBYTE(ea) (read_mem_byte((ea) & AMASK))
#define ReadByte(ea) (read_mem_byte((ea) & AMASK))
diff --git a/src/emu/cpu/i86/instr186.c b/src/emu/cpu/i86/instr186.c
index cc0fea3d299..8cc7e213834 100644
--- a/src/emu/cpu/i86/instr186.c
+++ b/src/emu/cpu/i86/instr186.c
@@ -16,6 +16,9 @@ static void PREFIX186(_pusha)(i8086_state *cpustate) /* Opcode 0x60 */
{
unsigned tmp=cpustate->regs.w[SP];
+#ifdef I80286
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-16, 16, I80286_WRITE);
+#endif
ICOUNT -= timing.pusha;
PUSH(cpustate->regs.w[AX]);
PUSH(cpustate->regs.w[CX]);
@@ -31,6 +34,9 @@ static unsigned i186_popa_tmp; // hack around GCC 4.6 error because we need the
static void PREFIX186(_popa)(i8086_state *cpustate) /* Opcode 0x61 */
{
+#ifdef I80286
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP], 16, I80286_READ);
+#endif
ICOUNT -= timing.popa;
POP(cpustate->regs.w[DI]);
POP(cpustate->regs.w[SI]);
@@ -100,6 +106,9 @@ static void PREFIX186(_imul_d8)(i8086_state *cpustate) /* Opcode 0x6b */
static void PREFIX186(_insb)(i8086_state *cpustate) /* Opcode 0x6c */
{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
ICOUNT -= timing.ins8;
PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));
cpustate->regs.w[DI] += cpustate->DirVal;
@@ -107,6 +116,9 @@ static void PREFIX186(_insb)(i8086_state *cpustate) /* Opcode 0x6c */
static void PREFIX186(_insw)(i8086_state *cpustate) /* Opcode 0x6d */
{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
ICOUNT -= timing.ins16;
PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));
cpustate->regs.w[DI] += 2 * cpustate->DirVal;
@@ -114,6 +126,9 @@ static void PREFIX186(_insw)(i8086_state *cpustate) /* Opcode 0x6d */
static void PREFIX186(_outsb)(i8086_state *cpustate) /* Opcode 0x6e */
{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
ICOUNT -= timing.outs8;
write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));
cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */
@@ -121,6 +136,9 @@ static void PREFIX186(_outsb)(i8086_state *cpustate) /* Opcode 0x6e */
static void PREFIX186(_outsw)(i8086_state *cpustate) /* Opcode 0x6f */
{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
ICOUNT -= timing.outs16;
write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));
cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */
@@ -146,17 +164,25 @@ static void PREFIX186(_rotshft_wd8)(i8086_state *cpustate) /* Opcode 0xc1 */
static void PREFIX186(_enter)(i8086_state *cpustate) /* Opcode 0xc8 */
{
- unsigned nb = FETCH; unsigned i,level;
+ unsigned nb = FETCH;
+ unsigned i,level;
+ UINT16 fp;
nb += FETCH << 8;
+#ifdef I80286
+ level = FETCH & 0x1f;
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-2-(level*2), 2+(level*2), I80286_WRITE);
+#else
level = FETCH;
+#endif
ICOUNT -= (level == 0) ? timing.enter0 : (level == 1) ? timing.enter1 : timing.enter_base + level * timing.enter_count;
PUSH(cpustate->regs.w[BP]);
- cpustate->regs.w[BP]=cpustate->regs.w[SP];
- cpustate->regs.w[SP] -= nb;
+ fp = cpustate->regs.w[SP];
for (i=1;i<level;i++)
PUSH(GetMemW(SS,cpustate->regs.w[BP]-i*2));
- if (level) PUSH(cpustate->regs.w[BP]);
+ if (level) PUSH(fp);
+ cpustate->regs.w[BP] = fp;
+ cpustate->regs.w[SP] -= nb;
}
static void PREFIX186(_leave)(i8086_state *cpustate) /* Opcode 0xc9 */
diff --git a/src/emu/cpu/i86/instr286.c b/src/emu/cpu/i86/instr286.c
index e09396eaf47..6f6a9f1ffcc 100644
--- a/src/emu/cpu/i86/instr286.c
+++ b/src/emu/cpu/i86/instr286.c
@@ -152,7 +152,7 @@ static void i80286_pop_seg(i80286_state *cpustate, int reg)
cpustate->regs.w[SP] += 2;
}
-static void i80286_data_descriptor_full(i80286_state *cpustate,int reg, UINT16 selector, int cpl, UINT32 trap)
+static void i80286_data_descriptor_full(i80286_state *cpustate, int reg, UINT16 selector, int cpl, UINT32 trap, UINT16 offset, int size)
{
if (PM) {
UINT16 desc[3];
@@ -189,6 +189,10 @@ static void i80286_data_descriptor_full(i80286_state *cpustate,int reg, UINT16 s
if (CODE(r) && !READ(r)) throw trap;
if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(IDXTBL(selector)+(trap&1)));
}
+ if (offset+size) {
+ if ((CODE(r) || !EXPDOWN(r)) && ((offset+size-1) > LIMIT(desc))) throw (reg==SS)?TRAP(STACK_FAULT,(trap&1)):trap;
+ if (!CODE(r) && EXPDOWN(r) && ((offset <= LIMIT(desc)) || ((offset+size) > 0xffff))) throw (reg==SS)?TRAP(STACK_FAULT,(trap&1)):trap;
+ }
SET_ACC(desc);
WriteWord(addr+4, desc[2]);
@@ -204,7 +208,7 @@ static void i80286_data_descriptor_full(i80286_state *cpustate,int reg, UINT16 s
static void i80286_data_descriptor(i80286_state *cpustate, int reg, UINT16 selector)
{
- i80286_data_descriptor_full(cpustate, reg, selector, CPL, TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)));
+ i80286_data_descriptor_full(cpustate, reg, selector, CPL, TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)), 0, 0);
}
static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type)
@@ -296,7 +300,7 @@ static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type)
if (type == CALL) cpustate->flags |= 0x4000;
cpustate->msw |= 8;
- i80286_data_descriptor_full(cpustate, SS, ntss[TSS_SS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_SS])));
+ i80286_data_descriptor_full(cpustate, SS, ntss[TSS_SS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_SS])), 0, 0);
cpustate->sregs[CS] = IDXTBL(cpustate->sregs[CS]) | RPL(ntss[TSS_CS]); // fixme
try {
@@ -307,8 +311,8 @@ static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type)
throw e;
}
- i80286_data_descriptor_full(cpustate, ES, ntss[TSS_ES], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_ES])));
- i80286_data_descriptor_full(cpustate, DS, ntss[TSS_DS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_DS])));
+ i80286_data_descriptor_full(cpustate, ES, ntss[TSS_ES], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_ES])), 0, 0);
+ i80286_data_descriptor_full(cpustate, DS, ntss[TSS_DS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_DS])), 0, 0);
}
static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT16 offset, int gate)
@@ -360,7 +364,7 @@ static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT
if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(gatesel));
- if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
+ if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
if (!CONF(r)&&(DPL(r)<CPL)) { // inner call
UINT16 tss_ss, tss_sp, oldss, oldsp;
@@ -373,13 +377,13 @@ static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT
oldss = cpustate->sregs[SS];
oldsp = cpustate->regs.w[SP];
oldstk = cpustate->base[SS] + oldsp;
- i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,IDXTBL(tss_ss)));
+ i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,IDXTBL(tss_ss)), tss_sp-8-(GATECNT(desc)*2), 8+(GATECNT(desc)*2));
cpustate->regs.w[SP] = tss_sp;
PUSH(oldss);
PUSH(oldsp);
for (i = GATECNT(desc)-1; i >= 0; i--)
PUSH(ReadWord(oldstk+(i*2)));
- }
+ } else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-4, 4, I80286_READ);
SET_ACC(gatedesc);
WriteWord(addr+4, gatedesc[2]);
cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r);
@@ -448,7 +452,7 @@ static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, in
if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(IDXTBL(gatesel)+(hwint&&1)));
- if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
+ if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,(hwint&&1));
if (!CONF(r)&&(DPL(r)<CPL)) { // inner call
UINT16 tss_ss, tss_sp, oldss, oldsp;
@@ -457,11 +461,11 @@ static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, in
oldss = cpustate->sregs[SS];
oldsp = cpustate->regs.w[SP];
- i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,(IDXTBL(tss_ss)+(hwint&&1))));
+ i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,(IDXTBL(tss_ss)+(hwint&&1))), tss_sp-((error != -1)?12:10), (error != -1)?12:10);
cpustate->regs.w[SP] = tss_sp;
PUSH(oldss);
PUSH(oldsp);
- }
+ } else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-((error != -1)?8:6), (error != -1)?8:6, I80286_READ);
SET_ACC(gatedesc);
WriteWord(addr+4, gatedesc[2]);
PREFIX(_pushf(cpustate));
@@ -776,9 +780,10 @@ static UINT16 i80286_far_return(i8086_state *cpustate, int iret, int bytes)
if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel));
if (off > LIMIT(desc)) throw TRAP(GENERAL_PROTECTION_FAULT, IDXTBL(sel));
if (CPL<RPL(sel)) {
+ i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]+(iret?6:4)+bytes, 4, I80286_READ);
newsp = ReadWord(spaddr+((iret?6:4)+bytes));
newss = ReadWord(spaddr+((iret?8:6)+bytes));
- i80286_data_descriptor_full(cpustate, SS, newss, RPL(sel), TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(newss)));
+ i80286_data_descriptor_full(cpustate, SS, newss, RPL(sel), TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(newss)), 0, 0);
cpustate->regs.w[SP] = newsp + bytes;
} else cpustate->regs.w[SP] += (iret?6:4) + bytes;
SET_ACC(desc);
@@ -855,7 +860,7 @@ static void i80286_check_permission(i8086_state *cpustate, UINT8 check_seg, UINT
rights = cpustate->rights[check_seg];
trap = i80286_verify(cpustate, cpustate->sregs[check_seg], operation, rights);
if ((CODE(rights) || !EXPDOWN(rights)) && ((offset+size-1) > cpustate->limit[check_seg])) trap = GENERAL_PROTECTION_FAULT;
- if (!CODE(rights) && EXPDOWN(rights) && (offset <= cpustate->limit[check_seg]) && ((offset+size) > 0xffff)) trap = GENERAL_PROTECTION_FAULT;
+ if (!CODE(rights) && EXPDOWN(rights) && ((offset <= cpustate->limit[check_seg]) || ((offset+size) > 0xffff))) trap = GENERAL_PROTECTION_FAULT;
if ((trap == GENERAL_PROTECTION_FAULT) && (check_seg == SS)) trap = STACK_FAULT;
if (trap) throw TRAP(trap, 0);
diff --git a/src/emu/cpu/i86/instr286.h b/src/emu/cpu/i86/instr286.h
index 814e2b7106e..f4dc0f7ffda 100644
--- a/src/emu/cpu/i86/instr286.h
+++ b/src/emu/cpu/i86/instr286.h
@@ -13,8 +13,8 @@
#define STACK_FAULT 12
#define GENERAL_PROTECTION_FAULT 13
-#define PM (cpustate->msw&1)
#define CPL (cpustate->sregs[CS]&3)
+#define PM (cpustate->msw&1)
static void i80286_trap2(i80286_state *cpustate,UINT32 error);
static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, int trap, int error);
@@ -40,3 +40,9 @@ enum i80286_operation
};
static void i80286_check_permission(i8086_state *cpustate, UINT8 check_seg, UINT32 offset, int size, i80286_operation operation);
+
+static inline UINT32 GetMemAddr(i80286_state *cpustate, UINT16 seg, UINT16 off, UINT8 size, i80286_operation op) {
+ seg = DefaultSeg(seg);
+ if(PM) i80286_check_permission(cpustate, seg, off, size, op);
+ return (cpustate->base[seg] + off) & AMASK;
+}
diff --git a/src/emu/cpu/i86/instr86.c b/src/emu/cpu/i86/instr86.c
index d5f137e7461..9c94ff6ca78 100644
--- a/src/emu/cpu/i86/instr86.c
+++ b/src/emu/cpu/i86/instr86.c
@@ -138,6 +138,7 @@ static void PREFIX86(_rotate_shift_Byte)(i8086_state *cpustate, unsigned ModRM,
}
else
{
+ int tmpcf = CF;
ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m8_bit;
switch (ModRM & 0x38)
@@ -161,19 +162,21 @@ static void PREFIX86(_rotate_shift_Byte)(i8086_state *cpustate, unsigned ModRM,
case 0x10: /* RCL eb,count */
for (; count > 0; count--)
{
- dst = (dst << 1) + CF;
- SetCFB(dst);
+ dst = (dst << 1) + tmpcf;
+ tmpcf = (int)((dst & 0x100) != 0);
}
PutbackRMByte(ModRM,(BYTE)dst);
+ cpustate->CarryVal = tmpcf;
break;
case 0x18: /* RCR eb,count */
for (; count > 0; count--)
{
- dst = (CF<<8)+dst;
- cpustate->CarryVal = dst & 0x01;
+ dst = (tmpcf<<8)+dst;
+ tmpcf = dst & 0x01;
dst >>= 1;
}
PutbackRMByte(ModRM,(BYTE)dst);
+ cpustate->CarryVal = tmpcf;
break;
case 0x20:
case 0x30: /* SHL eb,count */
@@ -329,6 +332,7 @@ static void PREFIX86(_rotate_shift_Word)(i8086_state *cpustate, unsigned ModRM,
}
else
{
+ int tmpcf = CF;
ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m16_bit;
switch (ModRM & 0x38)
@@ -352,19 +356,21 @@ static void PREFIX86(_rotate_shift_Word)(i8086_state *cpustate, unsigned ModRM,
case 0x10: /* RCL ew,count */
for (; count > 0; count--)
{
- dst = (dst << 1) + CF;
- SetCFW(dst);
+ dst = (dst << 1) + tmpcf;
+ tmpcf = (int)((dst & 0x10000) != 0);
}
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
break;
case 0x18: /* RCR ew,count */
for (; count > 0; count--)
{
- dst = dst + (CF << 16);
- cpustate->CarryVal = dst & 0x01;
+ dst = dst + (tmpcf << 16);
+ tmpcf = dst & 0x01;
dst >>= 1;
}
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
break;
case 0x20:
case 0x30: /* SHL ew,count */
@@ -401,7 +407,6 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
loop to continue for CMPS and SCAS instructions. */
unsigned next = FETCHOP;
- unsigned count = cpustate->regs.w[CX];
switch(next)
{
@@ -441,14 +446,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_ins8_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += cpustate->DirVal;
ICOUNT -= timing.rep_ins8_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0x6d: /* REP INSW */
#ifdef I80286
@@ -457,14 +462,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_ins16_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_ins16_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0x6e: /* REP OUTSB */
#ifdef I80286
@@ -473,14 +478,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_outs8_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[CX]--;
cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */
ICOUNT -= timing.rep_outs8_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0x6f: /* REP OUTSW */
#ifdef I80286
@@ -489,55 +494,56 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_outs16_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[CX]--;
cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */
ICOUNT -= timing.rep_outs16_count;
}
- cpustate->regs.w[CX]=count;
break;
#endif
case 0xa4: /* REP MOVSB */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_movs8_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
BYTE tmp;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
tmp = GetMemB(DS,cpustate->regs.w[SI]);
PutMemB(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += cpustate->DirVal;
cpustate->regs.w[SI] += cpustate->DirVal;
ICOUNT -= timing.rep_movs8_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xa5: /* REP MOVSW */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_movs16_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
WORD tmp;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
tmp = GetMemW(DS,cpustate->regs.w[SI]);
PutMemW(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += 2 * cpustate->DirVal;
cpustate->regs.w[SI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_movs16_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xa6: /* REP(N)E CMPSB */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_cmps8_base;
cpustate->rep_in_progress = FALSE;
- for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
{
unsigned dst, src;
@@ -545,17 +551,18 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
dst = GetMemB(ES, cpustate->regs.w[DI]);
src = GetMemB(DS, cpustate->regs.w[SI]);
SUBB(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += cpustate->DirVal;
cpustate->regs.w[SI] += cpustate->DirVal;
ICOUNT -= timing.rep_cmps8_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xa7: /* REP(N)E CMPSW */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_cmps16_base;
cpustate->rep_in_progress = FALSE;
- for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
{
unsigned dst, src;
@@ -563,69 +570,70 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
dst = GetMemW(ES, cpustate->regs.w[DI]);
src = GetMemW(DS, cpustate->regs.w[SI]);
SUBW(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += 2 * cpustate->DirVal;
cpustate->regs.w[SI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_cmps16_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xaa: /* REP STOSB */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_stos8_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += cpustate->DirVal;
ICOUNT -= timing.rep_stos8_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xab: /* REP STOSW */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_stos16_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_stos16_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xac: /* REP LODSB */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_lods8_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[SI] += cpustate->DirVal;
ICOUNT -= timing.rep_lods8_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xad: /* REP LODSW */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_lods16_base;
cpustate->rep_in_progress = FALSE;
- for (; count > 0; count--)
+ while(cpustate->regs.w[CX])
{
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[SI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_lods16_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xae: /* REP(N)E SCASB */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_scas8_base;
cpustate->rep_in_progress = FALSE;
- for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
{
unsigned src, dst;
@@ -633,16 +641,17 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
src = GetMemB(ES, cpustate->regs.w[DI]);
dst = cpustate->regs.b[AL];
SUBB(dst,src);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += cpustate->DirVal;
ICOUNT -= timing.rep_scas8_count;
}
- cpustate->regs.w[CX]=count;
break;
case 0xaf: /* REP(N)E SCASW */
if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_scas16_base;
cpustate->rep_in_progress = FALSE;
- for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
{
unsigned src, dst;
@@ -650,10 +659,10 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
src = GetMemW(ES, cpustate->regs.w[DI]);
dst = cpustate->regs.w[AX];
SUBW(dst,src);
+ cpustate->regs.w[CX]--;
cpustate->regs.w[DI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_scas16_count;
}
- cpustate->regs.w[CX]=count;
break;
default:
PREFIX(_instruction)[next](cpustate);
@@ -798,20 +807,24 @@ static void PREFIX86(_pop_cs)(i8086_state *cpustate) /* Opcode 0x0f */
static void PREFIX86(_adc_br8)(i8086_state *cpustate) /* Opcode 0x10 */
{
- DEF_br8(dst,src);
+ int tmpcf;
+ DEF_br8(dst,src);
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
src+=CF;
- ADDB(dst,src);
+ ADCB(dst,src,tmpcf);
PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
}
static void PREFIX86(_adc_wr16)(i8086_state *cpustate) /* Opcode 0x11 */
{
- DEF_wr16(dst,src);
+ int tmpcf;
+ DEF_wr16(dst,src);
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
src+=CF;
- ADDW(dst,src);
+ ADCW(dst,src,tmpcf);
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
}
static void PREFIX86(_adc_r8b)(i8086_state *cpustate) /* Opcode 0x12 */
@@ -858,20 +871,24 @@ static void PREFIX86(_push_ss)(i8086_state *cpustate) /* Opcode 0x16 */
static void PREFIX86(_sbb_br8)(i8086_state *cpustate) /* Opcode 0x18 */
{
- DEF_br8(dst,src);
+ int tmpcf;
+ DEF_br8(dst,src);
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
src+=CF;
- SUBB(dst,src);
+ SBBB(dst,src,tmpcf);
PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
}
static void PREFIX86(_sbb_wr16)(i8086_state *cpustate) /* Opcode 0x19 */
{
+ int tmpcf;
DEF_wr16(dst,src);
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
src+=CF;
- SUBW(dst,src);
+ SBBW(dst,src,tmpcf);
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
}
static void PREFIX86(_sbb_r8b)(i8086_state *cpustate) /* Opcode 0x1a */
@@ -1581,6 +1598,7 @@ static void PREFIX86(_80pre)(i8086_state *cpustate) /* Opcode 0x80 */
unsigned ModRM = FETCHOP;
unsigned dst = GetRMByte(ModRM);
unsigned src = FETCH;
+ int tmpcf;
switch (ModRM & 0x38)
{
@@ -1596,14 +1614,16 @@ static void PREFIX86(_80pre)(i8086_state *cpustate) /* Opcode 0x80 */
break;
case 0x10: /* ADC eb,d8 */
src+=CF;
- ADDB(dst,src);
+ ADCB(dst,src,tmpcf);
PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
break;
case 0x18: /* SBB eb,b8 */
src+=CF;
- SUBB(dst,src);
+ SBBB(dst,src,tmpcf);
PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
break;
case 0x20: /* AND eb,d8 */
@@ -1634,6 +1654,7 @@ static void PREFIX86(_81pre)(i8086_state *cpustate) /* Opcode 0x81 */
unsigned ModRM = FETCH;
unsigned dst = GetRMWord(ModRM);
unsigned src = FETCH;
+ int tmpcf;
src+= (FETCH << 8);
switch (ModRM & 0x38)
@@ -1650,14 +1671,16 @@ static void PREFIX86(_81pre)(i8086_state *cpustate) /* Opcode 0x81 */
break;
case 0x10: /* ADC ew,d16 */
src+=CF;
- ADDW(dst,src);
+ ADCW(dst,src,tmpcf);
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
break;
case 0x18: /* SBB ew,d16 */
src+=CF;
- SUBW(dst,src);
+ SBBW(dst,src,tmpcf);
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
break;
case 0x20: /* AND ew,d16 */
@@ -1687,6 +1710,7 @@ static void PREFIX86(_82pre)(i8086_state *cpustate) /* Opcode 0x82 */
unsigned ModRM = FETCH;
unsigned dst = GetRMByte(ModRM);
unsigned src = FETCH;
+ int tmpcf;
switch (ModRM & 0x38)
{
@@ -1702,14 +1726,16 @@ static void PREFIX86(_82pre)(i8086_state *cpustate) /* Opcode 0x82 */
break;
case 0x10: /* ADC eb,d8 */
src+=CF;
- ADDB(dst,src);
+ ADCB(dst,src,tmpcf);
PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
break;
case 0x18: /* SBB eb,d8 */
src+=CF;
- SUBB(dst,src);
+ SBBB(dst,src,tmpcf);
PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
break;
case 0x20: /* AND eb,d8 */
@@ -1739,6 +1765,7 @@ static void PREFIX86(_83pre)(i8086_state *cpustate) /* Opcode 0x83 */
unsigned ModRM = FETCH;
unsigned dst = GetRMWord(ModRM);
unsigned src = (WORD)((INT16)((INT8)FETCH));
+ int tmpcf;
switch (ModRM & 0x38)
{
@@ -1754,14 +1781,16 @@ static void PREFIX86(_83pre)(i8086_state *cpustate) /* Opcode 0x83 */
break;
case 0x10: /* ADC ew,d16 */
src+=CF;
- ADDW(dst,src);
+ ADCW(dst,src,tmpcf);
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
break;
case 0x18: /* SBB ew,d16 */
src+=CF;
- SUBW(dst,src);
+ SBBW(dst,src,tmpcf);
PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
break;
case 0x20: /* AND ew,d16 */
@@ -1804,16 +1833,16 @@ static void PREFIX86(_xchg_br8)(i8086_state *cpustate) /* Opcode 0x86 */
{
DEF_br8(dst,src);
ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
- RegByte(ModRM)=dst;
PutbackRMByte(ModRM,src);
+ RegByte(ModRM)=dst;
}
static void PREFIX86(_xchg_wr16)(i8086_state *cpustate) /* Opcode 0x87 */
{
DEF_wr16(dst,src);
ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
- RegWord(ModRM)=dst;
PutbackRMWord(ModRM,src);
+ RegWord(ModRM)=dst;
}
static void PREFIX86(_mov_br8)(i8086_state *cpustate) /* Opcode 0x88 */
@@ -2754,6 +2783,7 @@ static void PREFIX(_mov_sregw)(i8086_state *cpustate) /* Opcode 0x8e */
PREFIX(_instruction)[FETCHOP](cpustate);
break;
case 0x08: /* mov cs,ew */
+ PREFIX(_invalid)(cpustate);
break; /* doesn't do a jump far */
}
#else