REP instructions with high interleave would never complete.

Also fixed cpu.mak dependencies for i286.
This commit is contained in:
Aaron Giles 2008-12-30 22:00:54 +00:00
parent 7416f961fa
commit 3d7b496183
4 changed files with 71 additions and 32 deletions

View File

@ -748,6 +748,8 @@ $(CPUOBJ)/i86/i86.o: $(CPUSRC)/i86/i86.c \
$(CPUOBJ)/i86/i286.o: $(CPUSRC)/i86/i286.c \ $(CPUOBJ)/i86/i286.o: $(CPUSRC)/i86/i286.c \
$(CPUSRC)/i86/i286.h \ $(CPUSRC)/i86/i286.h \
$(CPUSRC)/i86/instr86.c \
$(CPUSRC)/i86/instr186.c \
$(CPUSRC)/i86/instr286.c \ $(CPUSRC)/i86/instr286.c \
$(I86DEPS) $(I86DEPS)

View File

@ -67,6 +67,7 @@ struct _i80286_state
INT8 nmi_state; INT8 nmi_state;
INT8 irq_state; INT8 irq_state;
INT8 test_state; /* PJB 03/05 */ INT8 test_state; /* PJB 03/05 */
UINT8 rep_in_progress;
INT32 extra_cycles; /* extra cycles for interrupts */ INT32 extra_cycles; /* extra cycles for interrupts */
memory_interface mem; memory_interface mem;
@ -159,6 +160,7 @@ static CPU_RESET( i80286 )
cpustate->flags=2; cpustate->flags=2;
ExpandFlags(cpustate->flags); ExpandFlags(cpustate->flags);
cpustate->idtr.base=0;cpustate->idtr.limit=0x3ff; cpustate->idtr.base=0;cpustate->idtr.limit=0x3ff;
cpustate->rep_in_progress = FALSE;
CHANGE_PC(cpustate->pc); CHANGE_PC(cpustate->pc);
@ -267,6 +269,7 @@ static CPU_INIT( i80286 )
state_save_register_device_item(device, 0, cpustate->nmi_state); state_save_register_device_item(device, 0, cpustate->nmi_state);
state_save_register_device_item(device, 0, cpustate->irq_state); state_save_register_device_item(device, 0, cpustate->irq_state);
state_save_register_device_item(device, 0, cpustate->extra_cycles); state_save_register_device_item(device, 0, cpustate->extra_cycles);
state_save_register_device_item(device, 0, cpustate->rep_in_progress);
cpustate->irq_callback = irqcallback; cpustate->irq_callback = irqcallback;
cpustate->device = device; cpustate->device = device;

View File

@ -49,6 +49,7 @@ struct _i8086_state
INT8 nmi_state; INT8 nmi_state;
INT8 irq_state; INT8 irq_state;
INT8 test_state; /* PJB 03/05 */ INT8 test_state; /* PJB 03/05 */
UINT8 rep_in_progress;
INT32 extra_cycles; /* extra cycles for interrupts */ INT32 extra_cycles; /* extra cycles for interrupts */
UINT16 ip; UINT16 ip;
@ -172,6 +173,7 @@ static void i8086_state_register(const device_config *device)
state_save_register_device_item(device, 0, cpustate->irq_state); state_save_register_device_item(device, 0, cpustate->irq_state);
state_save_register_device_item(device, 0, cpustate->extra_cycles); state_save_register_device_item(device, 0, cpustate->extra_cycles);
state_save_register_device_item(device, 0, cpustate->test_state); /* PJB 03/05 */ state_save_register_device_item(device, 0, cpustate->test_state); /* PJB 03/05 */
state_save_register_device_item(device, 0, cpustate->rep_in_progress); /* PJB 03/05 */
} }
static CPU_INIT( i8086 ) static CPU_INIT( i8086 )

View File

@ -393,33 +393,39 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
case 0x26: /* ES: */ case 0x26: /* ES: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix=TRUE;
cpustate->prefix_base=cpustate->base[ES]; cpustate->prefix_base=cpustate->base[ES];
ICOUNT -= timing.override; if (!cpustate->rep_in_progress)
ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); PREFIX(rep)(cpustate, flagval);
break; break;
case 0x2e: /* CS: */ case 0x2e: /* CS: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix=TRUE;
cpustate->prefix_base=cpustate->base[CS]; cpustate->prefix_base=cpustate->base[CS];
ICOUNT -= timing.override; if (!cpustate->rep_in_progress)
ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); PREFIX(rep)(cpustate, flagval);
break; break;
case 0x36: /* SS: */ case 0x36: /* SS: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix=TRUE;
cpustate->prefix_base=cpustate->base[SS]; cpustate->prefix_base=cpustate->base[SS];
ICOUNT -= timing.override; if (!cpustate->rep_in_progress)
ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); PREFIX(rep)(cpustate, flagval);
break; break;
case 0x3e: /* DS: */ case 0x3e: /* DS: */
cpustate->seg_prefix=TRUE; cpustate->seg_prefix=TRUE;
cpustate->prefix_base=cpustate->base[DS]; cpustate->prefix_base=cpustate->base[DS];
ICOUNT -= timing.override; if (!cpustate->rep_in_progress)
ICOUNT -= timing.override;
PREFIX(rep)(cpustate, flagval); PREFIX(rep)(cpustate, flagval);
break; break;
#ifndef I8086 #ifndef I8086
case 0x6c: /* REP INSB */ case 0x6c: /* REP INSB */
ICOUNT -= timing.rep_ins8_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_ins8_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } 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])); PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));
cpustate->regs.w[DI] += cpustate->DirVal; cpustate->regs.w[DI] += cpustate->DirVal;
ICOUNT -= timing.rep_ins8_count; ICOUNT -= timing.rep_ins8_count;
@ -427,10 +433,12 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0x6d: /* REP INSW */ case 0x6d: /* REP INSW */
ICOUNT -= timing.rep_ins16_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_ins16_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } 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])); PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));
cpustate->regs.w[DI] += 2 * cpustate->DirVal; cpustate->regs.w[DI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_ins16_count; ICOUNT -= timing.rep_ins16_count;
@ -438,10 +446,12 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0x6e: /* REP OUTSB */ case 0x6e: /* REP OUTSB */
ICOUNT -= timing.rep_outs8_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_outs8_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } 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])); write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));
cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */ cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */
ICOUNT -= timing.rep_outs8_count; ICOUNT -= timing.rep_outs8_count;
@ -449,10 +459,12 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0x6f: /* REP OUTSW */ case 0x6f: /* REP OUTSW */
ICOUNT -= timing.rep_outs16_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_outs16_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } 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])); write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));
cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */ cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */
ICOUNT -= timing.rep_outs16_count; ICOUNT -= timing.rep_outs16_count;
@ -461,12 +473,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
break; break;
#endif #endif
case 0xa4: /* REP MOVSB */ case 0xa4: /* REP MOVSB */
ICOUNT -= timing.rep_movs8_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_movs8_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
BYTE tmp; BYTE tmp;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
tmp = GetMemB(DS,cpustate->regs.w[SI]); tmp = GetMemB(DS,cpustate->regs.w[SI]);
PutMemB(ES,cpustate->regs.w[DI], tmp); PutMemB(ES,cpustate->regs.w[DI], tmp);
cpustate->regs.w[DI] += cpustate->DirVal; cpustate->regs.w[DI] += cpustate->DirVal;
@ -476,12 +490,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xa5: /* REP MOVSW */ case 0xa5: /* REP MOVSW */
ICOUNT -= timing.rep_movs16_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_movs16_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
WORD tmp; WORD tmp;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
tmp = GetMemW(DS,cpustate->regs.w[SI]); tmp = GetMemW(DS,cpustate->regs.w[SI]);
PutMemW(ES,cpustate->regs.w[DI], tmp); PutMemW(ES,cpustate->regs.w[DI], tmp);
cpustate->regs.w[DI] += 2 * cpustate->DirVal; cpustate->regs.w[DI] += 2 * cpustate->DirVal;
@ -491,12 +507,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xa6: /* REP(N)E CMPSB */ case 0xa6: /* REP(N)E CMPSB */
ICOUNT -= timing.rep_cmps8_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_cmps8_base;
cpustate->rep_in_progress = FALSE;
for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
{ {
unsigned dst, src; unsigned dst, src;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
dst = GetMemB(ES, cpustate->regs.w[DI]); dst = GetMemB(ES, cpustate->regs.w[DI]);
src = GetMemB(DS, cpustate->regs.w[SI]); src = GetMemB(DS, cpustate->regs.w[SI]);
SUBB(src,dst); /* opposite of the usual convention */ SUBB(src,dst); /* opposite of the usual convention */
@ -507,12 +525,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xa7: /* REP(N)E CMPSW */ case 0xa7: /* REP(N)E CMPSW */
ICOUNT -= timing.rep_cmps16_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_cmps16_base;
cpustate->rep_in_progress = FALSE;
for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
{ {
unsigned dst, src; unsigned dst, src;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
dst = GetMemW(ES, cpustate->regs.w[DI]); dst = GetMemW(ES, cpustate->regs.w[DI]);
src = GetMemW(DS, cpustate->regs.w[SI]); src = GetMemW(DS, cpustate->regs.w[SI]);
SUBW(src,dst); /* opposite of the usual convention */ SUBW(src,dst); /* opposite of the usual convention */
@ -523,10 +543,12 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xaa: /* REP STOSB */ case 0xaa: /* REP STOSB */
ICOUNT -= timing.rep_stos8_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_stos8_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]); PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
cpustate->regs.w[DI] += cpustate->DirVal; cpustate->regs.w[DI] += cpustate->DirVal;
ICOUNT -= timing.rep_stos8_count; ICOUNT -= timing.rep_stos8_count;
@ -534,10 +556,12 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xab: /* REP STOSW */ case 0xab: /* REP STOSW */
ICOUNT -= timing.rep_stos16_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_stos16_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]); PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
cpustate->regs.w[DI] += 2 * cpustate->DirVal; cpustate->regs.w[DI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_stos16_count; ICOUNT -= timing.rep_stos16_count;
@ -545,10 +569,12 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xac: /* REP LODSB */ case 0xac: /* REP LODSB */
ICOUNT -= timing.rep_lods8_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_lods8_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } 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.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
cpustate->regs.w[SI] += cpustate->DirVal; cpustate->regs.w[SI] += cpustate->DirVal;
ICOUNT -= timing.rep_lods8_count; ICOUNT -= timing.rep_lods8_count;
@ -556,10 +582,12 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xad: /* REP LODSW */ case 0xad: /* REP LODSW */
ICOUNT -= timing.rep_lods16_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_lods16_base;
cpustate->rep_in_progress = FALSE;
for (; count > 0; count--) for (; count > 0; count--)
{ {
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } 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[AX] = GetMemW(DS,cpustate->regs.w[SI]);
cpustate->regs.w[SI] += 2 * cpustate->DirVal; cpustate->regs.w[SI] += 2 * cpustate->DirVal;
ICOUNT -= timing.rep_lods16_count; ICOUNT -= timing.rep_lods16_count;
@ -567,12 +595,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xae: /* REP(N)E SCASB */ case 0xae: /* REP(N)E SCASB */
ICOUNT -= timing.rep_scas8_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_scas8_base;
cpustate->rep_in_progress = FALSE;
for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
{ {
unsigned src, dst; unsigned src, dst;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
src = GetMemB(ES, cpustate->regs.w[DI]); src = GetMemB(ES, cpustate->regs.w[DI]);
dst = cpustate->regs.b[AL]; dst = cpustate->regs.b[AL];
SUBB(dst,src); SUBB(dst,src);
@ -582,12 +612,14 @@ static void PREFIX(rep)(i8086_state *cpustate,int flagval)
cpustate->regs.w[CX]=count; cpustate->regs.w[CX]=count;
break; break;
case 0xaf: /* REP(N)E SCASW */ case 0xaf: /* REP(N)E SCASW */
ICOUNT -= timing.rep_scas16_base; if (!cpustate->rep_in_progress)
ICOUNT -= timing.rep_scas16_base;
cpustate->rep_in_progress = FALSE;
for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) for (cpustate->ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--)
{ {
unsigned src, dst; unsigned src, dst;
if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; break; } if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
src = GetMemW(ES, cpustate->regs.w[DI]); src = GetMemW(ES, cpustate->regs.w[DI]);
dst = cpustate->regs.w[AX]; dst = cpustate->regs.w[AX];
SUBW(dst,src); SUBW(dst,src);