BizHawk/wonderswan/v30mz.cpp

1080 lines
49 KiB
C++
Raw Normal View History

2014-05-30 05:09:54 +00:00
/****************************************************************************
NEC V30MZ emulator
Stripped out non-V30MZ clock counts and code.
Small changes made by dox@space.pl (Corrected bug in NEG instruction , different AUX flag handling in some opcodes)
(Re)Written June-September 2000 by Bryan McPhail (mish@tendril.co.uk) based
on code by Oliver Bergmann (Raul_Bloodworth@hotmail.com) who based code
on the i286 emulator by Fabrice Frances which had initial work based on
David Hedley's pcemu(!).
****************************************************************************/
/* This NEC V30MZ emulator may be used for purposes both commercial and noncommercial if you give the author, Bryan McPhail,
a small credit somewhere(such as in the documentation for an executable package).
*/
/*
TODO:
Implement bus lock fully(prevent interrupts from occuring during a REP sequence, I think...), taking into account
HLT emulation to prevent deadlocks!
Implement better prefix emulation. It's extremely kludgey right now.
Implement prefetch/pipeline emulation.
*/
#include "system.h"
#include <cstring>
#include "v30mz-private.h"
using namespace MDFN_IEN_WSWAN::V30MZEnum;
namespace MDFN_IEN_WSWAN
{
#define ADDBRANCHTRACE(x,y) { }
#define ADDBRANCHTRACE_INT(x,y) { }
#define SETOLDCSIP() { }
#include "v30mz-modrm.inc"
unsigned V30MZ::EA_000() { EO=I.regs.w[BW]+I.regs.w[IX]; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_001() { EO=I.regs.w[BW]+I.regs.w[IY]; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_002() { EO=I.regs.w[BP]+I.regs.w[IX]; EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_003() { EO=I.regs.w[BP]+I.regs.w[IY]; EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_004() { EO=I.regs.w[IX]; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_005() { EO=I.regs.w[IY]; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_006() { EO=FETCH; EO+=FETCH<<8; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_007() { EO=I.regs.w[BW]; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_100() { EO=(I.regs.w[BW]+I.regs.w[IX]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_101() { EO=(I.regs.w[BW]+I.regs.w[IY]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_102() { EO=(I.regs.w[BP]+I.regs.w[IX]+(int8)FETCH); EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_103() { EO=(I.regs.w[BP]+I.regs.w[IY]+(int8)FETCH); EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_104() { EO=(I.regs.w[IX]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_105() { EO=(I.regs.w[IY]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_106() { EO=(I.regs.w[BP]+(int8)FETCH); EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_107() { EO=(I.regs.w[BW]+(int8)FETCH); EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_200() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BW]+I.regs.w[IX]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_201() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BW]+I.regs.w[IY]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_202() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BP]+I.regs.w[IX]+(int16)E16; EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_203() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BP]+I.regs.w[IY]+(int16)E16; EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_204() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[IX]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_205() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[IY]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
unsigned V30MZ::EA_206() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BP]+(int16)E16; EA=DefaultBase(SS)+EO; return EA; }
unsigned V30MZ::EA_207() { E16=FETCH; E16+=FETCH<<8; EO=I.regs.w[BW]+(int16)E16; EA=DefaultBase(DS0)+EO; return EA; }
void V30MZ::SetupEA()
{
for (int i = 0; i < 64; i += 8)
{
GetEA[i + 0] = &V30MZ::EA_000;
GetEA[i + 1] = &V30MZ::EA_001;
GetEA[i + 2] = &V30MZ::EA_002;
GetEA[i + 3] = &V30MZ::EA_003;
GetEA[i + 4] = &V30MZ::EA_004;
GetEA[i + 5] = &V30MZ::EA_005;
GetEA[i + 6] = &V30MZ::EA_006;
GetEA[i + 7] = &V30MZ::EA_007;
}
for (int i = 64; i < 128; i += 8)
{
GetEA[i + 0] = &V30MZ::EA_100;
GetEA[i + 1] = &V30MZ::EA_101;
GetEA[i + 2] = &V30MZ::EA_102;
GetEA[i + 3] = &V30MZ::EA_103;
GetEA[i + 4] = &V30MZ::EA_104;
GetEA[i + 5] = &V30MZ::EA_105;
GetEA[i + 6] = &V30MZ::EA_106;
GetEA[i + 7] = &V30MZ::EA_107;
}
for (int i = 128; i < 192; i += 8)
{
GetEA[i + 0] = &V30MZ::EA_200;
GetEA[i + 1] = &V30MZ::EA_201;
GetEA[i + 2] = &V30MZ::EA_202;
GetEA[i + 3] = &V30MZ::EA_203;
GetEA[i + 4] = &V30MZ::EA_204;
GetEA[i + 5] = &V30MZ::EA_205;
GetEA[i + 6] = &V30MZ::EA_206;
GetEA[i + 7] = &V30MZ::EA_207;
}
}
inline void V30MZ::i_real_pushf()
2014-05-30 05:09:54 +00:00
{
PUSH( CompressFlags() );
CLK(2);
}
inline void V30MZ::i_real_popf()
2014-05-30 05:09:54 +00:00
{
uint32 tmp;
POP(tmp);
ExpandFlags(tmp);
CLK(3);
}
/***************************************************************************/
V30MZ::V30MZ()
{
SetupEA();
}
void V30MZ::reset()
{
const BREGS reg_name[8] = { AL, CL, DL, BL, AH, CH, DH, BH };
ICount = 0;
timestamp = 0;
std::memset(&I, 0, sizeof(I));
I.sregs[PS] = 0xffff;
for(unsigned int i = 0; i < 256; i++)
{
unsigned int c = 0;
for (unsigned int j = i; j > 0; j >>= 1)
if (j & 1) c++;
parity_table[i] = !(c & 1);
}
I.ZeroVal = I.ParityVal = 1;
for(unsigned int i = 0; i < 256; i++)
{
Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ;
}
for(unsigned int i = 0xc0; i < 0x100; i++)
{
Mod_RM.RM.w[i] = (WREGS)( i & 7 );
Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
}
prefix_base = 0;
seg_prefix = 0;
InHLT = 0;
}
void V30MZ::interrupt(uint32 vector, bool IgnoreIF)
{
InHLT = FALSE; // This is correct! Standby mode is always exited when there is an INT signal, regardless of whether interrupt are disabled.
if(I.IF || IgnoreIF)
{
uint32 dest_seg, dest_off;
PUSH( CompressFlags() );
I.TF = I.IF = 0;
dest_off = ReadWord(vector);
dest_seg = ReadWord(vector+2);
PUSH(I.sregs[PS]);
PUSH(I.pc);
I.pc = (uint16)dest_off;
I.sregs[PS] = (uint16)dest_seg;
ADDBRANCHTRACE_INT(I.sregs[PS], I.pc);
CLK(32);
}
}
void V30MZ::nec_interrupt(unsigned int_num)
{
uint32 dest_seg, dest_off;
if (int_num == -1)
return;
i_real_pushf();
I.TF = I.IF = 0;
dest_off = ReadWord((int_num)*4);
dest_seg = ReadWord((int_num)*4+2);
PUSH(I.sregs[PS]);
PUSH(I.pc);
I.pc = (uint16)dest_off;
I.sregs[PS] = (uint16)dest_seg;
ADDBRANCHTRACE(I.sregs[PS], I.pc);
}
bool V30MZ::CheckInHLT()
{
if(InHLT)
{
sys->interrupt.Check();
if(InHLT)
{
int32 tmp = ICount;
if(tmp > 0)
CLK(tmp);
return(1);
}
}
return(0);
}
/****************************************************************************/
/* OPCODES */
/****************************************************************************/
inline void V30MZ::i_real_insb()
2014-05-30 05:09:54 +00:00
{
PutMemB(DS1,I.regs.w[IY], read_port(I.regs.w[DW]));
I.regs.w[IY]+= -2 * I.DF + 1;
CLK(6);
}
inline void V30MZ::i_real_insw()
2014-05-30 05:09:54 +00:00
{
PutMemB(DS1,I.regs.w[IY],read_port(I.regs.w[DW]));
PutMemB(DS1,(I.regs.w[IY]+1)&0xffff,read_port((I.regs.w[DW]+1)&0xffff));
I.regs.w[IY]+= -4 * I.DF + 2;
CLK(6);
}
inline void V30MZ::i_real_outsb()
2014-05-30 05:09:54 +00:00
{
write_port(I.regs.w[DW],GetMemB(DS0,I.regs.w[IX]));
I.regs.w[IX]+= -2 * I.DF + 1;
CLK(7);
}
inline void V30MZ::i_real_outsw()
2014-05-30 05:09:54 +00:00
{
write_port(I.regs.w[DW],GetMemB(DS0,I.regs.w[IX]));
write_port((I.regs.w[DW]+1)&0xffff,GetMemB(DS0,(I.regs.w[IX]+1)&0xffff));
I.regs.w[IX]+= -4 * I.DF + 2;
CLK(7);
}
inline void V30MZ::i_real_movsb()
2014-05-30 05:09:54 +00:00
{
uint32 tmp = GetMemB(DS0,I.regs.w[IX]);
PutMemB(DS1,I.regs.w[IY], tmp);
I.regs.w[IY] += -2 * I.DF + 1;
I.regs.w[IX] += -2 * I.DF + 1;
CLK(5);
}
inline void V30MZ::i_real_movsw()
2014-05-30 05:09:54 +00:00
{
uint32 tmp = GetMemW(DS0,I.regs.w[IX]); PutMemW(DS1,I.regs.w[IY], tmp); I.regs.w[IY] += -4 * I.DF + 2;
I.regs.w[IX] += -4 * I.DF + 2; CLK(5);
}
inline void V30MZ::i_real_cmpsb()
2014-05-30 05:09:54 +00:00
{
uint32 src = GetMemB(DS1, I.regs.w[IY]); uint32 dst = GetMemB(DS0, I.regs.w[IX]); SUBB; I.regs.w[IY] += -2 * I.DF + 1;
I.regs.w[IX] += -2 * I.DF + 1; CLK(6);
}
inline void V30MZ::i_real_cmpsw()
2014-05-30 05:09:54 +00:00
{
uint32 src = GetMemW(DS1, I.regs.w[IY]); uint32 dst = GetMemW(DS0, I.regs.w[IX]); SUBW; I.regs.w[IY] += -4 * I.DF + 2;
I.regs.w[IX] += -4 * I.DF + 2; CLK(6);
}
inline void V30MZ::i_real_stosb()
2014-05-30 05:09:54 +00:00
{
PutMemB(DS1,I.regs.w[IY],I.regs.b[AL]); I.regs.w[IY] += -2 * I.DF + 1; CLK(3);
}
inline void V30MZ::i_real_stosw()
2014-05-30 05:09:54 +00:00
{
PutMemW(DS1,I.regs.w[IY],I.regs.w[AW]); I.regs.w[IY] += -4 * I.DF + 2; CLK(3);
}
inline void V30MZ::i_real_lodsb()
2014-05-30 05:09:54 +00:00
{
I.regs.b[AL] = GetMemB(DS0,I.regs.w[IX]); I.regs.w[IX] += -2 * I.DF + 1; CLK(3);
}
inline void V30MZ::i_real_lodsw()
2014-05-30 05:09:54 +00:00
{
I.regs.w[AW] = GetMemW(DS0,I.regs.w[IX]); I.regs.w[IX] += -4 * I.DF + 2; CLK(3);
}
inline void V30MZ::i_real_scasb()
2014-05-30 05:09:54 +00:00
{
uint32 src = GetMemB(DS1, I.regs.w[IY]); uint32 dst = I.regs.b[AL]; SUBB;
I.regs.w[IY] += -2 * I.DF + 1; CLK(4);
}
inline void V30MZ::i_real_scasw()
2014-05-30 05:09:54 +00:00
{
uint32 src = GetMemW(DS1, I.regs.w[IY]); uint32 dst = I.regs.w[AW]; SUBW;
I.regs.w[IY] += -4 * I.DF + 2; CLK(4);
}
void V30MZ::DoOP(uint8 opcode)
{
//#define OP(num,func_name) static void func_name()
#define OP(num, func_name) case num:
//#define OP_RANGE(num1, num2, func_name) case num1 ... num2:
#define OP_EPILOGUE break
switch(opcode)
{
default:
Debug::printf("Invalid op: %02x\n", opcode);
CLK(10);
break;
OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x06, i_push_ds1 ) { PUSH(I.sregs[DS1]); CLK(2); } OP_EPILOGUE;
OP( 0x07, i_pop_ds1 ) { POP(I.sregs[DS1]); CLK(3); } OP_EPILOGUE;
OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x0e, i_push_cs ) { PUSH(I.sregs[PS]); CLK(2); } OP_EPILOGUE;
OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2, 1); } OP_EPILOGUE;
OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKM(2, 1); } OP_EPILOGUE;
OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x16, i_push_ss ) { PUSH(I.sregs[SS]); CLK(2); } OP_EPILOGUE;
OP( 0x17, i_pop_ss ) { POP(I.sregs[SS]); CLK(3); } OP_EPILOGUE;
OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x1e, i_push_ds ) { PUSH(I.sregs[DS0]); CLK(2); } OP_EPILOGUE;
OP( 0x1f, i_pop_ds ) { POP(I.sregs[DS0]); CLK(3); } OP_EPILOGUE;
OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x26, i_ds1 ) { seg_prefix=TRUE; prefix_base=I.sregs[DS1]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
OP( 0x27, i_daa ) { ADJ4(6,0x60); CLK(10); } OP_EPILOGUE;
OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x2e, i_ps ) { seg_prefix=TRUE; prefix_base=I.sregs[PS]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLK(10); } OP_EPILOGUE;
OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE;
OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE;
OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE;
OP( 0x36, i_ss ) { seg_prefix=TRUE; prefix_base=I.sregs[SS]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
OP( 0x37, i_aaa ) { ADJB(6,1); CLK(9); } OP_EPILOGUE;
OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,1); } OP_EPILOGUE;
OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKM(2,1); } OP_EPILOGUE;
OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,1); } OP_EPILOGUE;
OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKM(2,1); } OP_EPILOGUE;
OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLK(1); } OP_EPILOGUE;
OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLK(1); } OP_EPILOGUE;
OP( 0x3e, i_ds0 ) { seg_prefix=TRUE; prefix_base=I.sregs[DS0]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=FALSE; } OP_EPILOGUE;
OP( 0x3f, i_aas ) { ADJB(-6,-1); CLK(9); } OP_EPILOGUE;
OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(1); } OP_EPILOGUE;
OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(1); } OP_EPILOGUE;
OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(1); } OP_EPILOGUE;
OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(1); } OP_EPILOGUE;
OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(1); } OP_EPILOGUE;
OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(1); } OP_EPILOGUE;
OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(1); } OP_EPILOGUE;
OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(1); } OP_EPILOGUE;
OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(1); } OP_EPILOGUE;
OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(1); } OP_EPILOGUE;
OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(1); } OP_EPILOGUE;
OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(1); } OP_EPILOGUE;
OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(1); } OP_EPILOGUE;
OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(1); } OP_EPILOGUE;
OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(1); } OP_EPILOGUE;
OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(1); } OP_EPILOGUE;
OP( 0x50, i_push_ax ) { PUSH(I.regs.w[AW]); CLK(1); } OP_EPILOGUE;
OP( 0x51, i_push_cx ) { PUSH(I.regs.w[CW]); CLK(1); } OP_EPILOGUE;
OP( 0x52, i_push_dx ) { PUSH(I.regs.w[DW]); CLK(1); } OP_EPILOGUE;
OP( 0x53, i_push_bx ) { PUSH(I.regs.w[BW]); CLK(1); } OP_EPILOGUE;
OP( 0x54, i_push_sp ) { PUSH(I.regs.w[SP]); CLK(1); } OP_EPILOGUE;
OP( 0x55, i_push_bp ) { PUSH(I.regs.w[BP]); CLK(1); } OP_EPILOGUE;
OP( 0x56, i_push_si ) { PUSH(I.regs.w[IX]); CLK(1); } OP_EPILOGUE;
OP( 0x57, i_push_di ) { PUSH(I.regs.w[IY]); CLK(1); } OP_EPILOGUE;
OP( 0x58, i_pop_ax ) { POP(I.regs.w[AW]); CLK(1); } OP_EPILOGUE;
OP( 0x59, i_pop_cx ) { POP(I.regs.w[CW]); CLK(1); } OP_EPILOGUE;
OP( 0x5a, i_pop_dx ) { POP(I.regs.w[DW]); CLK(1); } OP_EPILOGUE;
OP( 0x5b, i_pop_bx ) { POP(I.regs.w[BW]); CLK(1); } OP_EPILOGUE;
OP( 0x5c, i_pop_sp ) { POP(I.regs.w[SP]); CLK(1); } OP_EPILOGUE;
OP( 0x5d, i_pop_bp ) { POP(I.regs.w[BP]); CLK(1); } OP_EPILOGUE;
OP( 0x5e, i_pop_si ) { POP(I.regs.w[IX]); CLK(1); } OP_EPILOGUE;
OP( 0x5f, i_pop_di ) { POP(I.regs.w[IY]); CLK(1); } OP_EPILOGUE;
OP( 0x60, i_pusha ) {
unsigned tmp=I.regs.w[SP];
PUSH(I.regs.w[AW]);
PUSH(I.regs.w[CW]);
PUSH(I.regs.w[DW]);
PUSH(I.regs.w[BW]);
PUSH(tmp);
PUSH(I.regs.w[BP]);
PUSH(I.regs.w[IX]);
PUSH(I.regs.w[IY]);
CLK(9);
} OP_EPILOGUE;
OP( 0x61, i_popa ) {
unsigned tmp;
POP(I.regs.w[IY]);
POP(I.regs.w[IX]);
POP(I.regs.w[BP]);
POP(tmp);
POP(I.regs.w[BW]);
POP(I.regs.w[DW]);
POP(I.regs.w[CW]);
POP(I.regs.w[AW]);
CLK(8);
(void)tmp;
2014-05-30 05:09:54 +00:00
} OP_EPILOGUE;
OP( 0x62, i_chkind )
{
uint32 low,high,tmp;
GetModRM;
low = GetRMWord(ModRM);
high = GetnextRMWord;
tmp = RegWord(ModRM);
CLK(13);
if (tmp<low || tmp>high)
{
nec_interrupt(5);
}
} OP_EPILOGUE;
OP( 0x68, i_push_d16 ) { uint32 tmp; FETCHuint16(tmp); PUSH(tmp); CLK(1); } OP_EPILOGUE;
OP( 0x69, i_imul_d16 ) { uint32 tmp; DEF_r16w; FETCHuint16(tmp); dst = (int32)((int16)src)*(int32)((int16)tmp); I.CarryVal = I.OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1); RegWord(ModRM)=(uint16)dst; CLKM(4,3);} OP_EPILOGUE;
OP( 0x6a, i_push_d8 ) { uint32 tmp = (uint16)((int16)((int8)FETCH)); PUSH(tmp); CLK(1); } OP_EPILOGUE;
OP( 0x6b, i_imul_d8 ) { uint32 src2; DEF_r16w; src2= (uint16)((int16)((int8)FETCH)); dst = (int32)((int16)src)*(int32)((int16)src2); I.CarryVal = I.OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1); RegWord(ModRM)=(uint16)dst; CLKM(4,3); } OP_EPILOGUE;
OP( 0x6c, i_insb ) { i_real_insb(); } OP_EPILOGUE;
OP( 0x6d, i_insw ) { i_real_insw(); } OP_EPILOGUE;
OP( 0x6e, i_outsb ) { i_real_outsb(); } OP_EPILOGUE;
OP( 0x6f, i_outsw ) { i_real_outsw(); } OP_EPILOGUE;
OP( 0x70, i_jo ) { JMP( FLAG_O); CLK(1); } OP_EPILOGUE;
OP( 0x71, i_jno ) { JMP(!FLAG_O); CLK(1); } OP_EPILOGUE;
OP( 0x72, i_jc ) { JMP( CF); CLK(1); } OP_EPILOGUE;
OP( 0x73, i_jnc ) { JMP(!CF); CLK(1); } OP_EPILOGUE;
OP( 0x74, i_jz ) { JMP( ZF); CLK(1); } OP_EPILOGUE;
OP( 0x75, i_jnz ) { JMP(!ZF); CLK(1); } OP_EPILOGUE;
OP( 0x76, i_jce ) { JMP(CF || ZF); CLK(1); } OP_EPILOGUE;
OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLK(1); } OP_EPILOGUE;
OP( 0x78, i_js ) { JMP( SF); CLK(1); } OP_EPILOGUE;
OP( 0x79, i_jns ) { JMP(!SF); CLK(1); } OP_EPILOGUE;
OP( 0x7a, i_jp ) { JMP( PF); CLK(1); } OP_EPILOGUE;
OP( 0x7b, i_jnp ) { JMP(!PF); CLK(1); } OP_EPILOGUE;
OP( 0x7c, i_jl ) { JMP((SF!=FLAG_O)&&(!ZF)); CLK(1); } OP_EPILOGUE;
OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==FLAG_O)); CLK(1); } OP_EPILOGUE;
OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=FLAG_O)); CLK(1); } OP_EPILOGUE;
OP( 0x7f, i_jnle ) { JMP((SF==FLAG_O)&&(!ZF)); CLK(1); } OP_EPILOGUE;
OP( 0x80, i_80pre ) { uint32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH;
CLKM(3, 1);
switch (ModRM & 0x38) {
case 0x00: ADDB; PutbackRMByte(ModRM,dst); break;
case 0x08: ORB; PutbackRMByte(ModRM,dst); break;
case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break;
case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break;
case 0x20: ANDB; PutbackRMByte(ModRM,dst); break;
case 0x28: SUBB; PutbackRMByte(ModRM,dst); break;
case 0x30: XORB; PutbackRMByte(ModRM,dst); break;
case 0x38: SUBB; break; /* CMP */
}
} OP_EPILOGUE;
OP( 0x81, i_81pre ) { uint32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH; src+= (FETCH << 8);
CLKM(3, 1);
switch (ModRM & 0x38) {
case 0x00: ADDW; PutbackRMWord(ModRM,dst); break;
case 0x08: ORW; PutbackRMWord(ModRM,dst); break;
case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break;
case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break;
case 0x20: ANDW; PutbackRMWord(ModRM,dst); break;
case 0x28: SUBW; PutbackRMWord(ModRM,dst); break;
case 0x30: XORW; PutbackRMWord(ModRM,dst); break;
case 0x38: SUBW; break; /* CMP */
}
} OP_EPILOGUE;
OP( 0x82, i_82pre ) { uint32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (uint8)((int8)FETCH);
CLKM(3,1);
switch (ModRM & 0x38) {
case 0x00: ADDB; PutbackRMByte(ModRM,dst); break;
case 0x08: ORB; PutbackRMByte(ModRM,dst); break;
case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break;
case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break;
case 0x20: ANDB; PutbackRMByte(ModRM,dst); break;
case 0x28: SUBB; PutbackRMByte(ModRM,dst); break;
case 0x30: XORB; PutbackRMByte(ModRM,dst); break;
case 0x38: SUBB; break; /* CMP */
}
} OP_EPILOGUE;
OP( 0x83, i_83pre ) { uint32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (uint16)((int16)((int8)FETCH));
CLKM(3,1);
switch (ModRM & 0x38) {
case 0x00: ADDW; PutbackRMWord(ModRM,dst); break;
case 0x08: ORW; PutbackRMWord(ModRM,dst); break;
case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break;
case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break;
case 0x20: ANDW; PutbackRMWord(ModRM,dst); break;
case 0x28: SUBW; PutbackRMWord(ModRM,dst); break;
case 0x30: XORW; PutbackRMWord(ModRM,dst); break;
case 0x38: SUBW; break; /* CMP */
}
} OP_EPILOGUE;
OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,1); } OP_EPILOGUE;
OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKM(2,1); } OP_EPILOGUE;
OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(5,3); } OP_EPILOGUE;
OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKM(5,3); } OP_EPILOGUE;
OP( 0x88, i_mov_br8 ) { uint8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLK(1); } OP_EPILOGUE;
OP( 0x89, i_mov_wr16 ) { uint16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLK(1); } OP_EPILOGUE;
OP( 0x8a, i_mov_r8b ) { uint8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLK(1); } OP_EPILOGUE;
OP( 0x8b, i_mov_r16w ) { uint16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLK(1); } OP_EPILOGUE;
OP( 0x8c, i_mov_wsreg ) { GetModRM; PutRMWord(ModRM,I.sregs[(ModRM & 0x38) >> 3]); CLK(1); } OP_EPILOGUE;
OP( 0x8d, i_lea ) { uint16 ModRM = FETCH; if(ModRM >= 192) { Debug::printf("LEA Error: %02x\n", ModRM);} else { (void)(this->*GetEA[ModRM])(); } RegWord(ModRM)=EO; CLK(1); } OP_EPILOGUE;
OP( 0x8e, i_mov_sregw ) { uint16 src; GetModRM; src = GetRMWord(ModRM); CLKM(3,2);
switch (ModRM & 0x38) {
case 0x00: I.sregs[DS1] = src; break; /* mov ds1,ew */
case 0x08: I.sregs[PS] = src; break; /* mov cs,ew */
case 0x10: I.sregs[SS] = src; break; /* mov ss,ew */
case 0x18: I.sregs[DS0] = src; break; /* mov ds0,ew */
}
} OP_EPILOGUE;
OP( 0x8f, i_popw ) { uint16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); CLKM(3,1); } OP_EPILOGUE;
OP( 0x90, i_nop ) { CLK(3); } OP_EPILOGUE;
OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } OP_EPILOGUE;
OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } OP_EPILOGUE;
OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } OP_EPILOGUE;
OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } OP_EPILOGUE;
OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } OP_EPILOGUE;
OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } OP_EPILOGUE;
OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } OP_EPILOGUE;
// AKA CVTBW
OP( 0x98, i_cbw ) { I.regs.b[AH] = (I.regs.b[AL] & 0x80) ? 0xff : 0; CLK(1); } OP_EPILOGUE;
// AKA CVTWL
OP( 0x99, i_cwd ) { I.regs.w[DW] = (I.regs.b[AH] & 0x80) ? 0xffff : 0; CLK(1); } OP_EPILOGUE;
OP( 0x9a, i_call_far ) { uint32 tmp, tmp2; FETCHuint16(tmp); FETCHuint16(tmp2); PUSH(I.sregs[PS]); PUSH(I.pc); I.pc = (uint16)tmp; I.sregs[PS] = (uint16)tmp2; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(10); } OP_EPILOGUE;
OP( 0x9b, i_poll ) { Debug::puts("POLL"); } OP_EPILOGUE;
OP( 0x9c, i_pushf ) { i_real_pushf(); } OP_EPILOGUE;
OP( 0x9d, i_popf ) { i_real_popf(); } OP_EPILOGUE;
OP( 0x9e, i_sahf ) { uint32 tmp = (CompressFlags() & 0xff00) | (I.regs.b[AH] & 0xd5); ExpandFlags(tmp); CLK(4); } OP_EPILOGUE;
OP( 0x9f, i_lahf ) { I.regs.b[AH] = CompressFlags() & 0xff; CLK(2); } OP_EPILOGUE;
OP( 0xa0, i_mov_aldisp ) { uint32 addr; FETCHuint16(addr); I.regs.b[AL] = GetMemB(DS0, addr); CLK(1); } OP_EPILOGUE;
OP( 0xa1, i_mov_axdisp ) { uint32 addr; FETCHuint16(addr); I.regs.b[AL] = GetMemB(DS0, addr); I.regs.b[AH] = GetMemB(DS0, (addr+1)&0xffff); CLK(1); } OP_EPILOGUE;
OP( 0xa2, i_mov_dispal ) { uint32 addr; FETCHuint16(addr); PutMemB(DS0, addr, I.regs.b[AL]); CLK(1); } OP_EPILOGUE;
OP( 0xa3, i_mov_dispax ) { uint32 addr; FETCHuint16(addr); PutMemB(DS0, addr, I.regs.b[AL]); PutMemB(DS0, (addr+1)&0xffff, I.regs.b[AH]); CLK(1); } OP_EPILOGUE;
OP( 0xa4, i_movsb ) { i_real_movsb(); } OP_EPILOGUE;
OP( 0xa5, i_movsw ) { i_real_movsw(); } OP_EPILOGUE;
OP( 0xa6, i_cmpsb ) { i_real_cmpsb(); } OP_EPILOGUE;
OP( 0xa7, i_cmpsw ) { i_real_cmpsw(); } OP_EPILOGUE;
OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLK(1); } OP_EPILOGUE;
OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLK(1); } OP_EPILOGUE;
OP( 0xaa, i_stosb ) { i_real_stosb(); } OP_EPILOGUE;
OP( 0xab, i_stosw ) { i_real_stosw(); } OP_EPILOGUE;
OP( 0xac, i_lodsb ) { i_real_lodsb(); } OP_EPILOGUE;
OP( 0xad, i_lodsw ) { i_real_lodsw(); } OP_EPILOGUE;
OP( 0xae, i_scasb ) { i_real_scasb(); } OP_EPILOGUE;
OP( 0xaf, i_scasw ) { i_real_scasw(); } OP_EPILOGUE;
OP( 0xb0, i_mov_ald8 ) { I.regs.b[AL] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb1, i_mov_cld8 ) { I.regs.b[CL] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb2, i_mov_dld8 ) { I.regs.b[DL] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb3, i_mov_bld8 ) { I.regs.b[BL] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb4, i_mov_ahd8 ) { I.regs.b[AH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb5, i_mov_chd8 ) { I.regs.b[CH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb6, i_mov_dhd8 ) { I.regs.b[DH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb7, i_mov_bhd8 ) { I.regs.b[BH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb8, i_mov_axd16 ) { I.regs.b[AL] = FETCH; I.regs.b[AH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xb9, i_mov_cxd16 ) { I.regs.b[CL] = FETCH; I.regs.b[CH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xba, i_mov_dxd16 ) { I.regs.b[DL] = FETCH; I.regs.b[DH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xbb, i_mov_bxd16 ) { I.regs.b[BL] = FETCH; I.regs.b[BH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xbc, i_mov_spd16 ) { I.regs.b[SPL] = FETCH; I.regs.b[SPH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xbd, i_mov_bpd16 ) { I.regs.b[BPL] = FETCH; I.regs.b[BPH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xbe, i_mov_sid16 ) { I.regs.b[IXL] = FETCH; I.regs.b[IXH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xbf, i_mov_did16 ) { I.regs.b[IYL] = FETCH; I.regs.b[IYH] = FETCH; CLK(1); } OP_EPILOGUE;
OP( 0xc0, i_rotshft_bd8 ) {
uint32 src, dst; uint8 c;
GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src;
c=FETCH;
c&=0x1f;
CLKM(5,3);
if (c) switch (ModRM & 0x38) {
case 0x00: do { ROL_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x08: do { ROR_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x10: do { ROLC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x18: do { RORC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x20: SHL_uint8(c); I.AuxVal = 1; break;//
case 0x28: SHR_uint8(c); I.AuxVal = 1; break;//
case 0x30: break;
case 0x38: SHRA_uint8(c); break;
}
} OP_EPILOGUE;
OP( 0xc1, i_rotshft_wd8 ) {
uint32 src, dst; uint8 c;
GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src;
c=FETCH;
c&=0x1f;
CLKM(5,3);
if (c) switch (ModRM & 0x38) {
case 0x00: do { ROL_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x08: do { ROR_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x10: do { ROLC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x18: do { RORC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x20: SHL_uint16(c); I.AuxVal = 1; break;
case 0x28: SHR_uint16(c); I.AuxVal = 1; break;
case 0x30: break;
case 0x38: SHRA_uint16(c); break;
}
} OP_EPILOGUE;
OP( 0xc2, i_ret_d16 ) { uint32 count = FETCH; count += FETCH << 8; POP(I.pc); I.regs.w[SP]+=count; CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
OP( 0xc3, i_ret ) { POP(I.pc); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
OP( 0xc4, i_les_dw ) { GetModRM; uint16 tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; I.sregs[DS1] = GetnextRMWord; CLK(6); } OP_EPILOGUE;
OP( 0xc5, i_lds_dw ) { GetModRM; uint16 tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; I.sregs[DS0] = GetnextRMWord; CLK(6); } OP_EPILOGUE;
OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); CLK(1); } OP_EPILOGUE;
OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); CLK(1); } OP_EPILOGUE;
// NEC calls it "PREPARE"
OP( 0xc8, i_enter ) {
uint32 nb = FETCH;
uint32 i,level;
CLK(19);
nb += FETCH << 8;
level = FETCH;
level &= 0x1F; // Only lower 5 bits are valid on V30MZ
PUSH(I.regs.w[BP]);
I.regs.w[BP]=I.regs.w[SP];
I.regs.w[SP] -= nb;
for (i=1;i<level;i++) {
PUSH(GetMemW(SS,I.regs.w[BP]-i*2));
CLK(4);
}
if (level) PUSH(I.regs.w[BP]);
} OP_EPILOGUE;
OP( 0xc9, i_leave ) {
I.regs.w[SP]=I.regs.w[BP];
POP(I.regs.w[BP]);
CLK(2);
} OP_EPILOGUE;
OP( 0xca, i_retf_d16 ) { uint32 count = FETCH; count += FETCH << 8; POP(I.pc); POP(I.sregs[PS]); I.regs.w[SP]+=count; CLK(9); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
OP( 0xcb, i_retf ) { POP(I.pc); POP(I.sregs[PS]); CLK(8); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
OP( 0xcc, i_int3 ) { nec_interrupt(3); CLK(9); } OP_EPILOGUE;
OP( 0xcd, i_int ) { nec_interrupt(FETCH); CLK(10); } OP_EPILOGUE;
OP( 0xce, i_into ) { if (FLAG_O) { nec_interrupt(4); CLK(13); } else CLK(6); } OP_EPILOGUE;
OP( 0xcf, i_iret ) { POP(I.pc); POP(I.sregs[PS]); i_real_popf(); CLK(10); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
OP( 0xd0, i_rotshft_b ) {
uint32 src, dst; GetModRM; src = (uint32)GetRMByte(ModRM); dst=src;
CLKM(3,1);
switch (ModRM & 0x38) {
case 0x00: ROL_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
case 0x08: ROR_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
case 0x10: ROLC_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
case 0x18: RORC_uint8; PutbackRMByte(ModRM,(uint8)dst); I.OverVal = (src^dst)&0x80; break;
case 0x20: SHL_uint8(1); I.OverVal = (src^dst)&0x80;I.AuxVal = 1; break;
case 0x28: SHR_uint8(1); I.OverVal = (src^dst)&0x80;I.AuxVal = 1; break;
case 0x30: break;
case 0x38: SHRA_uint8(1); I.OverVal = 0; break;
}
} OP_EPILOGUE;
OP( 0xd1, i_rotshft_w ) {
uint32 src, dst; GetModRM; src = (uint32)GetRMWord(ModRM); dst=src;
CLKM(3,1);
switch (ModRM & 0x38) {
case 0x00: ROL_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
case 0x08: ROR_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
case 0x10: ROLC_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
case 0x18: RORC_uint16; PutbackRMWord(ModRM,(uint16)dst); I.OverVal = (src^dst)&0x8000; break;
case 0x20: SHL_uint16(1); I.AuxVal = 1;I.OverVal = (src^dst)&0x8000; break;
case 0x28: SHR_uint16(1); I.AuxVal = 1;I.OverVal = (src^dst)&0x8000; break;
case 0x30: break;
case 0x38: SHRA_uint16(1); I.AuxVal = 1;I.OverVal = 0; break;
}
} OP_EPILOGUE;
OP( 0xd2, i_rotshft_bcl ) {
uint32 src, dst; uint8 c; GetModRM; src = (uint32)GetRMByte(ModRM); dst=src;
c=I.regs.b[CL];
CLKM(5,3);
c&=0x1f;
if (c) switch (ModRM & 0x38) {
case 0x00: do { ROL_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x08: do { ROR_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x10: do { ROLC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x18: do { RORC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break;
case 0x20: SHL_uint8(c); I.AuxVal = 1; break;
case 0x28: SHR_uint8(c); I.AuxVal = 1;break;
case 0x30: break;
case 0x38: SHRA_uint8(c); break;
}
} OP_EPILOGUE;
OP( 0xd3, i_rotshft_wcl ) {
uint32 src, dst; uint8 c; GetModRM; src = (uint32)GetRMWord(ModRM); dst=src;
c=I.regs.b[CL];
c&=0x1f;
CLKM(5,3);
if (c) switch (ModRM & 0x38) {
case 0x00: do { ROL_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x08: do { ROR_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x10: do { ROLC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x18: do { RORC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break;
case 0x20: SHL_uint16(c); I.AuxVal = 1; break;
case 0x28: SHR_uint16(c); I.AuxVal = 1; break;
case 0x30: break;
case 0x38: SHRA_uint16(c); break;
}
} OP_EPILOGUE;
OP( 0xd4, i_aam ) { uint32 mult=FETCH; mult=0; I.regs.b[AH] = I.regs.b[AL] / 10; I.regs.b[AL] %= 10; SetSZPF_Word(I.regs.w[AW]); CLK(17); } OP_EPILOGUE;
OP( 0xd5, i_aad ) { uint32 mult=FETCH; mult=0; I.regs.b[AL] = I.regs.b[AH] * 10 + I.regs.b[AL]; I.regs.b[AH] = 0; SetSZPF_Byte(I.regs.b[AL]); CLK(6); } OP_EPILOGUE;
OP( 0xd6, i_setalc ) { I.regs.b[AL] = (CF)?0xff:0x00; CLK(3); } OP_EPILOGUE;
OP( 0xd7, i_trans ) { uint32 dest = (I.regs.w[BW]+I.regs.b[AL])&0xffff; I.regs.b[AL] = GetMemB(DS0, dest); CLK(5); } OP_EPILOGUE;
//
OP( 0xd8, i_fpo)
OP( 0xd9, i_fpo)
OP( 0xda, i_fpo)
OP( 0xdb, i_fpo)
OP( 0xdc, i_fpo)
OP( 0xdd, i_fpo)
OP( 0xde, i_fpo)
OP( 0xdf, i_fpo)
/*OP_RANGE(0xd8, 0xdf, i_fpo)*/ { /*printf("FPO1, Op:%02x\n", opcode);*/ GetModRM; CLK(1); } OP_EPILOGUE;
OP( 0xe0, i_loopne ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if (!ZF && I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(3); } OP_EPILOGUE;
OP( 0xe1, i_loope ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if ( ZF && I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(3); } OP_EPILOGUE;
OP( 0xe2, i_loop ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if (I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(5); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(2); } OP_EPILOGUE;
OP( 0xe3, i_jcxz ) { int8 disp = (int8)FETCH; if (I.regs.w[CW] == 0) { I.pc = (uint16)(I.pc+disp); CLK(4); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(1); } OP_EPILOGUE;
OP( 0xe4, i_inal ) { uint8 port = FETCH; I.regs.b[AL] = read_port(port); CLK(6); } OP_EPILOGUE;
OP( 0xe5, i_inax ) { uint8 port = FETCH; I.regs.b[AL] = read_port(port); I.regs.b[AH] = read_port(port+1); CLK(6); } OP_EPILOGUE;
OP( 0xe6, i_outal ) { uint8 port = FETCH; write_port(port, I.regs.b[AL]); CLK(6); } OP_EPILOGUE;
OP( 0xe7, i_outax ) { uint8 port = FETCH; write_port(port, I.regs.b[AL]); write_port(port+1, I.regs.b[AH]); CLK(6); } OP_EPILOGUE;
OP( 0xe8, i_call_d16 ) { uint32 tmp; FETCHuint16(tmp); PUSH(I.pc); I.pc = (uint16)(I.pc+(int16)tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(5); } OP_EPILOGUE;
OP( 0xe9, i_jmp_d16 ) { uint32 tmp; FETCHuint16(tmp); I.pc = (uint16)(I.pc+(int16)tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(4); } OP_EPILOGUE;
OP( 0xea, i_jmp_far ) { uint32 tmp,tmp1; FETCHuint16(tmp); FETCHuint16(tmp1); I.sregs[PS] = (uint16)tmp1; I.pc = (uint16)tmp; ; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(7); } OP_EPILOGUE;
OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((int8)FETCH); CLK(4);I.pc = (uint16)(I.pc+tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE;
OP( 0xec, i_inaldx ) { I.regs.b[AL] = read_port(I.regs.w[DW]); CLK(6);} OP_EPILOGUE;
OP( 0xed, i_inaxdx ) { uint32 port = I.regs.w[DW]; I.regs.b[AL] = read_port(port); I.regs.b[AH] = read_port(port+1); CLK(6); } OP_EPILOGUE;
OP( 0xee, i_outdxal ) { write_port(I.regs.w[DW], I.regs.b[AL]); CLK(6); } OP_EPILOGUE;
OP( 0xef, i_outdxax ) { uint32 port = I.regs.w[DW]; write_port(port, I.regs.b[AL]); write_port(port+1, I.regs.b[AH]); CLK(6); } OP_EPILOGUE;
// NEC calls it "BUSLOCK"
OP( 0xf0, i_lock ) { CLK(1); DoOP(FETCHOP); } OP_EPILOGUE;
// We put CHK_ICOUNT *after* the first iteration has completed, to match real behavior.
#define CHK_ICOUNT(cond) if(ICount < 0 && (cond)) { I.pc -= seg_prefix ? 3 : 2; break; }
OP( 0xf2, i_repne )
{
uint32 next = FETCHOP;
switch(next) { /* Segments */
case 0x26: seg_prefix=TRUE; prefix_base=I.sregs[DS1]<<4; next = FETCHOP; CLK(2); break;
case 0x2e: seg_prefix=TRUE; prefix_base=I.sregs[PS]<<4; next = FETCHOP; CLK(2); break;
case 0x36: seg_prefix=TRUE; prefix_base=I.sregs[SS]<<4; next = FETCHOP; CLK(2); break;
case 0x3e: seg_prefix=TRUE; prefix_base=I.sregs[DS0]<<4; next = FETCHOP; CLK(2); break;
}
switch(next) {
case 0x6c: CLK(5); if (I.regs.w[CW]) do { i_real_insb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0x6d: CLK(5); if (I.regs.w[CW]) do { i_real_insw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0x6e: CLK(5); if (I.regs.w[CW]) do { i_real_outsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0x6f: CLK(5); if (I.regs.w[CW]) do { i_real_outsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xa4: CLK(5); if (I.regs.w[CW]) do { i_real_movsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xa5: CLK(5); if (I.regs.w[CW]) do { i_real_movsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xa6: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsb(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 0); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==0); break;
case 0xa7: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsw(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 0); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==0); break;
case 0xaa: CLK(5); if (I.regs.w[CW]) do { i_real_stosb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xab: CLK(5); if (I.regs.w[CW]) do { i_real_stosw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xac: CLK(5); if (I.regs.w[CW]) do { i_real_lodsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xad: CLK(5); if (I.regs.w[CW]) do { i_real_lodsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xae: CLK(5); if (I.regs.w[CW]) do { i_real_scasb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 0); } while (I.regs.w[CW]>0 && ZF==0); break;
case 0xaf: CLK(5); if (I.regs.w[CW]) do { i_real_scasw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 0); } while (I.regs.w[CW]>0 && ZF==0); break;
default: DoOP(next); break;
}
seg_prefix=FALSE;
} OP_EPILOGUE;
OP( 0xf3, i_repe)
{
uint32 next = FETCHOP;
switch(next) { /* Segments */
case 0x26: seg_prefix=TRUE; prefix_base=I.sregs[DS1]<<4; next = FETCHOP; CLK(2); break;
case 0x2e: seg_prefix=TRUE; prefix_base=I.sregs[PS]<<4; next = FETCHOP; CLK(2); break;
case 0x36: seg_prefix=TRUE; prefix_base=I.sregs[SS]<<4; next = FETCHOP; CLK(2); break;
case 0x3e: seg_prefix=TRUE; prefix_base=I.sregs[DS0]<<4; next = FETCHOP; CLK(2); break;
}
switch(next) {
case 0x6c: CLK(5); if (I.regs.w[CW]) do { i_real_insb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0x6d: CLK(5); if (I.regs.w[CW]) do { i_real_insw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0x6e: CLK(5); if (I.regs.w[CW]) do { i_real_outsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0x6f: CLK(5); if (I.regs.w[CW]) do { i_real_outsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xa4: CLK(5); if (I.regs.w[CW]) do { i_real_movsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xa5: CLK(5); if (I.regs.w[CW]) do { i_real_movsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xa6: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsb(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 1); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==1); break;
case 0xa7: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsw(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 1);/* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==1); break;
case 0xaa: CLK(5); if (I.regs.w[CW]) do { i_real_stosb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xab: CLK(5); if (I.regs.w[CW]) do { i_real_stosw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xac: CLK(5); if (I.regs.w[CW]) do { i_real_lodsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xad: CLK(5); if (I.regs.w[CW]) do { i_real_lodsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break;
case 0xae: CLK(5); if (I.regs.w[CW]) do { i_real_scasb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 1); } while (I.regs.w[CW]>0 && ZF==1); break;
case 0xaf: CLK(5); if (I.regs.w[CW]) do { i_real_scasw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 1); } while (I.regs.w[CW]>0 && ZF==1); break;
default: DoOP(next); break;
}
seg_prefix=FALSE;
} OP_EPILOGUE;
OP( 0xf4, i_hlt ) { InHLT = TRUE; CheckInHLT(); } OP_EPILOGUE;
OP( 0xf5, i_cmc ) { I.CarryVal = !CF; CLK(4); } OP_EPILOGUE;
OP( 0xf6, i_f6pre ) { uint32 tmp; uint32 uresult,uresult2; int32 result,result2;
GetModRM; tmp = GetRMByte(ModRM);
switch (ModRM & 0x38) {
case 0x00: tmp &= FETCH; I.CarryVal = I.OverVal = I.AuxVal=0; SetSZPF_Byte(tmp); CLKM(2,1); break; /* TEST */
case 0x08: break;
case 0x10: PutbackRMByte(ModRM,~tmp); CLKM(3,1); break; /* NOT */
case 0x18: I.CarryVal=(tmp!=0);tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); CLKM(3,1); break; /* NEG */
case 0x20: uresult = I.regs.b[AL]*tmp; I.regs.w[AW]=(uint16)uresult; I.CarryVal=I.OverVal=(I.regs.b[AH]!=0); CLKM(4,3); break; /* MULU */
case 0x28: result = (int16)((int8)I.regs.b[AL])*(int16)((int8)tmp); I.regs.w[AW]=(uint16)result; I.CarryVal=I.OverVal=(I.regs.b[AH]!=0); CLKM(4,3); break; /* MUL */
case 0x30: if (tmp) { DIVUB; } else nec_interrupt(0); CLKM(16,15); break;
case 0x38: if (tmp) { DIVB; } else nec_interrupt(0); CLKM(18,17); break;
}
} OP_EPILOGUE;
OP( 0xf7, i_f7pre ) { uint32 tmp,tmp2; uint32 uresult,uresult2; int32 result,result2;
GetModRM; tmp = GetRMWord(ModRM);
switch (ModRM & 0x38) {
case 0x00: FETCHuint16(tmp2); tmp &= tmp2; I.CarryVal = I.OverVal = I.AuxVal=0; SetSZPF_Word(tmp); CLKM(2,1); break; /* TEST */
case 0x08: break;
case 0x10: PutbackRMWord(ModRM,~tmp); CLKM(3,1); break; /* NOT */
case 0x18: I.CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); CLKM(3,1); break; /* NEG */
case 0x20: uresult = I.regs.w[AW]*tmp; I.regs.w[AW]=uresult&0xffff; I.regs.w[DW]=((uint32)uresult)>>16; I.CarryVal=I.OverVal=(I.regs.w[DW]!=0); CLKM(4,3); break; /* MULU */
case 0x28: result = (int32)((int16)I.regs.w[AW])*(int32)((int16)tmp); I.regs.w[AW]=result&0xffff; I.regs.w[DW]=result>>16; I.CarryVal=I.OverVal=(I.regs.w[DW]!=0); CLKM(4,3); break; /* MUL */
case 0x30: if (tmp) { DIVUW; } else nec_interrupt(0); CLKM(24,23); break;
case 0x38: if (tmp) { DIVW; } else nec_interrupt(0); CLKM(25,24); break;
}
} OP_EPILOGUE;
OP( 0xf8, i_clc ) { I.CarryVal = 0; CLK(4); } OP_EPILOGUE;
OP( 0xf9, i_stc ) { I.CarryVal = 1; CLK(4); } OP_EPILOGUE;
OP( 0xfa, i_di ) { SetIF(0); CLK(4); } OP_EPILOGUE;
OP( 0xfb, i_ei ) { SetIF(1); CLK(4); } OP_EPILOGUE;
OP( 0xfc, i_cld ) { SetDF(0); CLK(4); } OP_EPILOGUE;
OP( 0xfd, i_std ) { SetDF(1); CLK(4); } OP_EPILOGUE;
OP( 0xfe, i_fepre ) { uint32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM);
switch(ModRM & 0x38) {
case 0x00: tmp1 = tmp+1; I.OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(uint8)tmp1); CLKM(3,1); break; /* INC */
case 0x08: tmp1 = tmp-1; I.OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(uint8)tmp1); CLKM(3,1); break; /* DEC */
}
} OP_EPILOGUE;
OP( 0xff, i_ffpre ) { uint32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM);
switch(ModRM & 0x38) {
case 0x00: tmp1 = tmp+1; I.OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(uint16)tmp1); CLKM(3,1); break; /* INC */
case 0x08: tmp1 = tmp-1; I.OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(uint16)tmp1); CLKM(3,1); break; /* DEC */
case 0x10: PUSH(I.pc); I.pc = (uint16)tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(6,5); break; /* CALL */
case 0x18: tmp1 = I.sregs[PS]; I.sregs[PS] = GetnextRMWord; PUSH(tmp1); PUSH(I.pc); I.pc = tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(12,1); break; /* CALL FAR */
case 0x20: I.pc = tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(5,4); break; /* JMP */
case 0x28: I.pc = tmp; I.sregs[PS] = GetnextRMWord; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(10,1); break; /* JMP FAR */
case 0x30: PUSH(tmp); CLKM(2,1); break;
}
} OP_EPILOGUE;
} // End switch statement
} // End func
/*****************************************************************************/
unsigned V30MZ::get_reg(int regnum) const
2014-05-30 05:09:54 +00:00
{
switch( regnum )
{
case NEC_PC: return I.pc;
case NEC_SP: return I.regs.w[SP];
case NEC_FLAGS: return CompressFlags();
case NEC_AW: return I.regs.w[AW];
case NEC_CW: return I.regs.w[CW];
case NEC_DW: return I.regs.w[DW];
case NEC_BW: return I.regs.w[BW];
case NEC_BP: return I.regs.w[BP];
case NEC_IX: return I.regs.w[IX];
case NEC_IY: return I.regs.w[IY];
case NEC_DS1: return I.sregs[DS1];
case NEC_PS: return I.sregs[PS];
case NEC_SS: return I.sregs[SS];
case NEC_DS0: return I.sregs[DS0];
}
return 0;
}
void nec_set_irq_line(int irqline, int state);
void V30MZ::set_reg(int regnum, unsigned val)
{
switch( regnum )
{
case NEC_PC: I.pc = val; break;
case NEC_SP: I.regs.w[SP] = val; break;
case NEC_FLAGS: ExpandFlags(val); break;
case NEC_AW: I.regs.w[AW] = val; break;
case NEC_CW: I.regs.w[CW] = val; break;
case NEC_DW: I.regs.w[DW] = val; break;
case NEC_BW: I.regs.w[BW] = val; break;
case NEC_BP: I.regs.w[BP] = val; break;
case NEC_IX: I.regs.w[IX] = val; break;
case NEC_IY: I.regs.w[IY] = val; break;
case NEC_DS1: I.sregs[DS1] = val; break;
case NEC_PS: I.sregs[PS] = val; break;
case NEC_SS: I.sregs[SS] = val; break;
case NEC_DS0: I.sregs[DS0] = val; break;
}
}
void V30MZ::execute(int cycles)
{
ICount += cycles;
if(InHLT)
{
SETOLDCSIP();
sys->interrupt.Check();
if(InHLT)
{
int32 tmp = ICount;
if(tmp > 0)
CLK(tmp);
return;
}
}
while(ICount > 0)
{
SETOLDCSIP();
sys->interrupt.Check();
DoOP(FETCHOP);
}
}
2014-06-19 15:57:07 +00:00
uint8 V30MZ::cpu_readop(uint32 addr)
{
if (ExecHook)
ExecHook(addr);
return sys->memory.Read20(addr);
}
uint8 V30MZ::cpu_readop_arg(uint32 addr)
{
// only forward the first opcode byte to callback
return sys->memory.Read20(addr);
}
uint8 V30MZ::cpu_readmem20(uint32 addr)
{
if (ReadHook)
ReadHook(addr);
return sys->memory.Read20(addr);
}
void V30MZ::cpu_writemem20(uint32 addr, uint8 val)
{
sys->memory.Write20(addr, val);
if (WriteHook)
WriteHook(addr);
}
2014-05-31 05:57:18 +00:00
SYNCFUNC(V30MZ)
{
NSS(old_CS);
NSS(old_IP);
NSS(timestamp);
NSS(ICount);
NSS(I);
NSS(InHLT);
NSS(prefix_base);
NSS(seg_prefix);
NSS(parity_table);
NSS(EA);
NSS(EO);
NSS(E16);
NSS(Mod_RM);
}
2014-05-30 05:09:54 +00:00
}