1332 lines
42 KiB
C#
1332 lines
42 KiB
C#
using mame;
|
|
using System;
|
|
using System.IO;
|
|
|
|
namespace cpu.nec
|
|
{
|
|
public partial class Nec : cpuexec_data
|
|
{
|
|
protected ulong totalExecutedCycles;
|
|
public int pendingCycles;
|
|
public override ulong TotalExecutedCycles
|
|
{
|
|
get
|
|
{
|
|
return totalExecutedCycles;
|
|
}
|
|
set
|
|
{
|
|
totalExecutedCycles = value;
|
|
}
|
|
}
|
|
public override int PendingCycles
|
|
{
|
|
get
|
|
{
|
|
return pendingCycles;
|
|
}
|
|
set
|
|
{
|
|
pendingCycles = value;
|
|
}
|
|
}
|
|
public override void set_irq_line(int irqline, LineState state)
|
|
{
|
|
if (irqline == (int)LineState.INPUT_LINE_NMI)
|
|
{
|
|
if (I.nmi_state == (uint)state)
|
|
{
|
|
return;
|
|
}
|
|
I.nmi_state = (uint)state;
|
|
if (state != LineState.CLEAR_LINE)
|
|
{
|
|
I.pending_irq |= 0x02;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
I.irq_state = (uint)state;
|
|
if (state == LineState.CLEAR_LINE)
|
|
{
|
|
I.pending_irq &= 0xfffffffe;
|
|
}
|
|
else
|
|
{
|
|
I.pending_irq |= 0x01;
|
|
}
|
|
}
|
|
}
|
|
public override void cpunum_set_input_line_and_vector(int cpunum, int line, LineState state, int vector)
|
|
{
|
|
if (line >= 0 && line < 35)
|
|
{
|
|
Cpuint.lirq.Add(new irq(cpunum, line, state, vector, Timer.get_current_time()));
|
|
int event_index = Cpuint.input_event_index[cpunum, line]++;
|
|
if (event_index >= 35)
|
|
{
|
|
Cpuint.input_event_index[cpunum, line]--;
|
|
//Cpuint.cpunum_empty_event_queue(machine, NULL, cpunum | (line << 8));
|
|
event_index = Cpuint.input_event_index[cpunum, line]++;
|
|
}
|
|
if (event_index < 35)
|
|
{
|
|
//Cpuint.input_event_queue[cpunum][line][event_index] = input_event;
|
|
//if (event_index == 0)
|
|
{
|
|
Timer.timer_set_internal(Cpuint.cpunum_empty_event_queue, "cpunum_empty_event_queue");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public struct necbasicregs
|
|
{
|
|
//public ushort[] w;//[8];
|
|
public byte[] b;//[16];
|
|
}
|
|
public struct nec_Regs
|
|
{
|
|
public necbasicregs regs;
|
|
public ushort[] sregs;//[4];
|
|
public ushort ip;
|
|
public int SignVal;
|
|
public uint AuxVal, OverVal, ZeroVal, CarryVal, ParityVal;
|
|
public bool TF, IF, DF, MF;
|
|
public uint int_vector;
|
|
public uint pending_irq;
|
|
public uint nmi_state;
|
|
public uint irq_state;
|
|
public bool poll_state;
|
|
public byte no_interrupt;
|
|
//int (*irq_callback)(int irqline);
|
|
//memory_interface mem;
|
|
//const nec_config *config;
|
|
}
|
|
public struct Mod_RM
|
|
{
|
|
public int[] regw;
|
|
public int[] regb;
|
|
public int[] RMw;
|
|
public int[] RMb;
|
|
}
|
|
public int iNOP;
|
|
public static Nec[] nn1;
|
|
public Mod_RM mod_RM;
|
|
public byte[] v25v35_decryptiontable;
|
|
public nec_Regs I;
|
|
public int chip_type;
|
|
public static int prefix_base;
|
|
public static int seg_prefix;
|
|
public int INT_IRQ = 0x01, NMI_IRQ = 0x02;
|
|
public bool[] parity_table = new bool[0x100];
|
|
public Func<int, byte> ReadOp, ReadOpArg;
|
|
public Func<int, byte> ReadByte;
|
|
public Action<int, byte> WriteByte;
|
|
public Func<int, ushort> ReadWord;
|
|
public Action<int, ushort> WriteWord;
|
|
public Func<int, byte> ReadIOByte;
|
|
public Action<int, byte> WriteIOByte;
|
|
public Func<int, ushort> ReadIOWord;
|
|
public Action<int, ushort> WriteIOWord;
|
|
public delegate void nec_delegate();
|
|
public nec_delegate[] nec_instruction;
|
|
public delegate int getea_delegate();
|
|
public getea_delegate[] GetEA;
|
|
public Nec()
|
|
{
|
|
nec_init();
|
|
}
|
|
private int DefaultBase(int Seg, nec_Regs I)
|
|
{
|
|
return (((seg_prefix != 0) && (Seg == 3 || Seg == 2)) ? prefix_base : (int)(I.sregs[Seg] << 4));
|
|
}
|
|
private byte GetMemB(int Seg, int Off)
|
|
{
|
|
return ReadByte(DefaultBase(Seg, I) + Off);
|
|
}
|
|
private ushort GetMemW(int Seg, int Off)
|
|
{
|
|
return ReadWord(DefaultBase(Seg, I) + Off);
|
|
}
|
|
private void PutMemB(int Seg, int Off, byte x)
|
|
{
|
|
WriteByte(DefaultBase(Seg, I) + Off, x);
|
|
}
|
|
private void PutMemW(int Seg, int Off, ushort x)
|
|
{
|
|
WriteWord(DefaultBase(Seg, I) + Off, x);
|
|
}
|
|
private byte FETCH()
|
|
{
|
|
return ReadOpArg(((I.sregs[1] << 4) + I.ip++) ^ 0);
|
|
}
|
|
public byte fetchop()
|
|
{
|
|
byte ret = ReadOp(((I.sregs[1] << 4) + I.ip++) ^ 0);
|
|
if (I.MF)
|
|
{
|
|
if (v25v35_decryptiontable != null)
|
|
{
|
|
ret = v25v35_decryptiontable[ret];
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
public ushort FETCHWORD()
|
|
{
|
|
ushort var = (ushort)(ReadOpArg(((I.sregs[1] << 4) + I.ip) ^ 0) + (ReadOpArg(((I.sregs[1] << 4) + I.ip + 1) ^ 0) << 8));
|
|
I.ip += 2;
|
|
return var;
|
|
}
|
|
public int GetModRM()
|
|
{
|
|
int ModRM = ReadOpArg(((I.sregs[1] << 4) + I.ip++) ^ 0);
|
|
return ModRM;
|
|
}
|
|
public void PUSH(ushort val)
|
|
{
|
|
//I.regs.w[4] -= 2;
|
|
ushort w4 = (ushort)(I.regs.b[8] + I.regs.b[9] * 0x100 - 2);
|
|
I.regs.b[8] = (byte)(w4 % 0x100);
|
|
I.regs.b[9] = (byte)(w4 / 0x100);
|
|
WriteWord((I.sregs[2] << 4) + I.regs.b[8] + I.regs.b[9] * 0x100, val);
|
|
}
|
|
public void POP(ref ushort var)
|
|
{
|
|
var = ReadWord((I.sregs[2] << 4) + I.regs.b[8] + I.regs.b[9] * 0x100);
|
|
//I.regs.w[4] += 2;
|
|
ushort w4 = (ushort)(I.regs.b[8] + I.regs.b[9] * 0x100 + 2);
|
|
I.regs.b[8] = (byte)(w4 % 0x100);
|
|
I.regs.b[9] = (byte)(w4 / 0x100);
|
|
}
|
|
public void POPW(int i)
|
|
{
|
|
ushort var = ReadWord((I.sregs[2] << 4) + I.regs.b[8] + I.regs.b[9] * 0x100);
|
|
I.regs.b[i * 2] = (byte)(var % 0x100);
|
|
I.regs.b[i * 2 + 1] = (byte)(var / 0x100);
|
|
ushort w4 = (ushort)(I.regs.b[8] + I.regs.b[9] * 0x100 + 2);
|
|
I.regs.b[8] = (byte)(w4 % 0x100);
|
|
I.regs.b[9] = (byte)(w4 / 0x100);
|
|
}
|
|
public byte PEEK(uint addr)
|
|
{
|
|
return (byte)ReadOpArg((int)(addr ^ 0));
|
|
}
|
|
public byte PEEKOP(uint addr)
|
|
{
|
|
return (byte)ReadOp((int)(addr ^ 0));
|
|
}
|
|
public void SetCFB(uint x)
|
|
{
|
|
I.CarryVal = x & 0x100;
|
|
}
|
|
public void SetCFW(uint x)
|
|
{
|
|
I.CarryVal = x & 0x10000;
|
|
}
|
|
public void SetAF(int x, int y, int z)
|
|
{
|
|
I.AuxVal = (uint)(((x) ^ ((y) ^ (z))) & 0x10);
|
|
}
|
|
public void SetSZPF_Byte(int x)
|
|
{
|
|
I.ZeroVal = I.ParityVal = (uint)((sbyte)x);
|
|
I.SignVal = (int)I.ZeroVal;
|
|
}
|
|
public void SetSZPF_Word(int x)
|
|
{
|
|
I.ZeroVal = I.ParityVal = (uint)((short)x);
|
|
I.SignVal = (int)I.ZeroVal;
|
|
}
|
|
public void SetOFW_Add(int x, int y, int z)
|
|
{
|
|
I.OverVal = (uint)(((x) ^ (y)) & ((x) ^ (z)) & 0x8000);
|
|
}
|
|
public void SetOFB_Add(int x, int y, int z)
|
|
{
|
|
I.OverVal = (uint)(((x) ^ (y)) & ((x) ^ (z)) & 0x80);
|
|
}
|
|
public void SetOFW_Sub(int x, int y, int z)
|
|
{
|
|
I.OverVal = (uint)(((z) ^ (y)) & ((z) ^ (x)) & 0x8000);
|
|
}
|
|
public void SetOFB_Sub(int x, int y, int z)
|
|
{
|
|
I.OverVal = (uint)(((z) ^ (y)) & ((z) ^ (x)) & 0x80);
|
|
}
|
|
public void ADDB(ref byte src, ref byte dst)
|
|
{
|
|
uint res = (uint)(dst + src);
|
|
SetCFB((uint)res);
|
|
SetOFB_Add((int)res, src, dst);
|
|
SetAF((int)res, src, dst);
|
|
SetSZPF_Byte((int)res);
|
|
dst = (byte)res;
|
|
}
|
|
public void ADDW(ref ushort src, ref ushort dst)
|
|
{
|
|
uint res = (uint)(dst + src);
|
|
SetCFW(res);
|
|
SetOFW_Add((int)res, src, dst);
|
|
SetAF((int)res, src, dst);
|
|
SetSZPF_Word((int)res);
|
|
dst = (ushort)res;
|
|
}
|
|
public void SUBB(ref byte src, ref byte dst)
|
|
{
|
|
uint res = (uint)(dst - src);
|
|
SetCFB(res);
|
|
SetOFB_Sub((int)res, src, dst);
|
|
SetAF((int)res, src, dst);
|
|
SetSZPF_Byte((int)res);
|
|
dst = (byte)res;
|
|
}
|
|
public void SUBW(ref ushort src, ref ushort dst)
|
|
{
|
|
uint res = (uint)(dst - src);
|
|
SetCFW(res);
|
|
SetOFW_Sub((int)res, src, dst);
|
|
SetAF((int)res, src, dst);
|
|
SetSZPF_Word((int)res);
|
|
dst = (ushort)res;
|
|
}
|
|
public void ORB(ref byte src, ref byte dst)
|
|
{
|
|
dst |= src;
|
|
I.CarryVal = I.OverVal = I.AuxVal = 0;
|
|
SetSZPF_Byte(dst);
|
|
}
|
|
public void ORW(ref ushort src, ref ushort dst)
|
|
{
|
|
dst |= src;
|
|
I.CarryVal = I.OverVal = I.AuxVal = 0;
|
|
SetSZPF_Word(dst);
|
|
}
|
|
public void ANDB(ref byte src, ref byte dst)
|
|
{
|
|
dst &= src;
|
|
I.CarryVal = I.OverVal = I.AuxVal = 0;
|
|
SetSZPF_Byte(dst);
|
|
}
|
|
public void ANDW(ref ushort src, ref ushort dst)
|
|
{
|
|
dst &= src;
|
|
I.CarryVal = I.OverVal = I.AuxVal = 0;
|
|
SetSZPF_Word(dst);
|
|
}
|
|
public void XORB(ref byte src, ref byte dst)
|
|
{
|
|
dst ^= src;
|
|
I.CarryVal = I.OverVal = I.AuxVal = 0;
|
|
SetSZPF_Byte(dst);
|
|
}
|
|
public void XORW(ref ushort src, ref ushort dst)
|
|
{
|
|
dst ^= src;
|
|
I.CarryVal = I.OverVal = I.AuxVal = 0;
|
|
SetSZPF_Word(dst);
|
|
}
|
|
public bool CF()
|
|
{
|
|
return (I.CarryVal != 0);
|
|
}
|
|
public bool SF()
|
|
{
|
|
return (I.SignVal < 0);
|
|
}
|
|
public bool ZF()
|
|
{
|
|
return (I.ZeroVal == 0);
|
|
}
|
|
public bool PF()
|
|
{
|
|
return parity_table[(byte)I.ParityVal];
|
|
}
|
|
public bool AF()
|
|
{
|
|
return (I.AuxVal != 0);
|
|
}
|
|
public bool OF()
|
|
{
|
|
return (I.OverVal != 0);
|
|
}
|
|
public bool MD()
|
|
{
|
|
return I.MF;
|
|
}
|
|
public void CLK(int all)
|
|
{
|
|
pendingCycles -= all;
|
|
}
|
|
public void CLKS(int v20, int v30, int v33)
|
|
{
|
|
int ccount = (v20 << 16) | (v30 << 8) | v33;
|
|
pendingCycles -= (ccount >> chip_type) & 0x7f;
|
|
}
|
|
public void CLKW(int v20o, int v30o, int v33o, int v20e, int v30e, int v33e, int addr)
|
|
{
|
|
int ocount = (v20o << 16) | (v30o << 8) | v33o, ecount = (v20e << 16) | (v30e << 8) | v33e;
|
|
pendingCycles -= ((addr & 1) != 0) ? ((ocount >> chip_type) & 0x7f) : ((ecount >> chip_type) & 0x7f);
|
|
}
|
|
public void CLKM(int ModRM, int v20, int v30, int v33, int v20m, int v30m, int v33m)
|
|
{
|
|
int ccount = (v20 << 16) | (v30 << 8) | v33, mcount = (v20m << 16) | (v30m << 8) | v33m;
|
|
pendingCycles -= (ModRM >= 0xc0) ? ((ccount >> chip_type) & 0x7f) : ((mcount >> chip_type) & 0x7f);
|
|
}
|
|
public void CLKR(int ModRM, int v20o, int v30o, int v33o, int v20e, int v30e, int v33e, int vall, int addr)
|
|
{
|
|
int ocount = (v20o << 16) | (v30o << 8) | v33o, ecount = (v20e << 16) | (v30e << 8) | v33e;
|
|
if (ModRM >= 0xc0)
|
|
{
|
|
pendingCycles -= vall;
|
|
}
|
|
else
|
|
{
|
|
pendingCycles -= ((addr & 1) != 0) ? ((ocount >> chip_type) & 0x7f) : ((ecount >> chip_type) & 0x7f);
|
|
}
|
|
}
|
|
public ushort CompressFlags()
|
|
{
|
|
return (ushort)((CF() ? 1 : 0) | ((PF() ? 1 : 0) << 2) | ((AF() ? 1 : 0) << 4) | ((ZF() ? 1 : 0) << 6) | ((SF() ? 1 : 0) << 7) | ((I.TF ? 1 : 0) << 8) | ((I.IF ? 1 : 0) << 9) | ((I.DF ? 1 : 0) << 10) | ((OF() ? 1 : 0) << 11) | ((MD() ? 1 : 0) << 15));
|
|
}
|
|
public void ExpandFlags(ushort f)
|
|
{
|
|
I.CarryVal = (uint)(f & 1);
|
|
I.ParityVal = (uint)((f & 4) == 0 ? 1 : 0);
|
|
I.AuxVal = (uint)(f & 16);
|
|
I.ZeroVal = (uint)((f & 64) == 0 ? 1 : 0);
|
|
I.SignVal = ((f & 128) != 0) ? -1 : 0;
|
|
I.TF = (f & 256) == 256;
|
|
I.IF = (f & 512) == 512;
|
|
I.DF = (f & 1024) == 1024;
|
|
I.OverVal = (uint)(f & 2048);
|
|
I.MF = (f & 0x8000) == 0x8000;
|
|
}
|
|
public void IncWordReg(int Reg)
|
|
{
|
|
int tmp = (int)(I.regs.b[Reg * 2] + I.regs.b[Reg * 2 + 1] * 0x100);
|
|
int tmp1 = tmp + 1;
|
|
I.OverVal = (uint)((tmp == 0x7fff) ? 1 : 0);
|
|
SetAF(tmp1, tmp, 1);
|
|
SetSZPF_Word(tmp1);
|
|
//I.regs.w[Reg] = (ushort)tmp1;
|
|
I.regs.b[Reg * 2] = (byte)((ushort)tmp1 % 0x100);
|
|
I.regs.b[Reg * 2 + 1] = (byte)((ushort)tmp1 / 0x100);
|
|
}
|
|
public void DecWordReg(int Reg)
|
|
{
|
|
int tmp = (int)(I.regs.b[Reg * 2] + I.regs.b[Reg * 2 + 1] * 0x100);
|
|
int tmp1 = tmp - 1;
|
|
I.OverVal = (uint)((tmp == 0x8000) ? 1 : 0);
|
|
SetAF(tmp1, tmp, 1);
|
|
SetSZPF_Word(tmp1);
|
|
//I.regs.w[Reg] = (ushort)tmp1;
|
|
I.regs.b[Reg * 2] = (byte)((ushort)tmp1 % 0x100);
|
|
I.regs.b[Reg * 2 + 1] = (byte)((ushort)tmp1 / 0x100);
|
|
}
|
|
public void JMP(bool flag)
|
|
{
|
|
int tmp = (int)((sbyte)FETCH());
|
|
if (flag)
|
|
{
|
|
byte[] table = new byte[] { 3, 10, 10 };
|
|
I.ip = (ushort)(I.ip + tmp);
|
|
pendingCycles -= table[chip_type / 8];
|
|
//PC = (I.sregs[1] << 4) + I.ip;
|
|
return;
|
|
}
|
|
}
|
|
public void ADJ4(int param1, int param2)
|
|
{
|
|
if (AF() || ((I.regs.b[0] & 0xf) > 9))
|
|
{
|
|
ushort tmp;
|
|
tmp = (ushort)(I.regs.b[0] + param1);
|
|
I.regs.b[0] = (byte)tmp;
|
|
I.AuxVal = 1;
|
|
I.CarryVal |= (uint)(tmp & 0x100);
|
|
}
|
|
if (CF() || (I.regs.b[0] > 0x9f))
|
|
{
|
|
I.regs.b[0] += (byte)param2;
|
|
I.CarryVal = 1;
|
|
}
|
|
SetSZPF_Byte(I.regs.b[0]);
|
|
}
|
|
public void ADJB(int param1, int param2)
|
|
{
|
|
if (AF() || ((I.regs.b[0] & 0xf) > 9))
|
|
{
|
|
I.regs.b[0] += (byte)param1;
|
|
I.regs.b[1] += (byte)param2;
|
|
I.AuxVal = 1;
|
|
I.CarryVal = 1;
|
|
}
|
|
else
|
|
{
|
|
I.AuxVal = 0;
|
|
I.CarryVal = 0;
|
|
}
|
|
I.regs.b[0] &= 0x0F;
|
|
}
|
|
public void BITOP_BYTE(ref int ModRM, ref int tmp)
|
|
{
|
|
ModRM = FETCH();
|
|
if (ModRM >= 0xc0)
|
|
{
|
|
tmp = I.regs.b[mod_RM.RMb[ModRM]];
|
|
}
|
|
else
|
|
{
|
|
EA = GetEA[ModRM]();
|
|
tmp = ReadByte(EA);
|
|
}
|
|
}
|
|
public void BITOP_WORD(ref int ModRM, ref int tmp)
|
|
{
|
|
ModRM = FETCH();
|
|
if (ModRM >= 0xc0)
|
|
{
|
|
tmp = I.regs.b[mod_RM.RMw[ModRM] * 2] + I.regs.b[mod_RM.RMw[ModRM] * 2 + 1] * 0x100;
|
|
}
|
|
else
|
|
{
|
|
EA = GetEA[ModRM]();
|
|
tmp = ReadWord(EA);
|
|
}
|
|
}
|
|
public void BIT_NOT(ref int tmp, ref int tmp2)
|
|
{
|
|
if ((tmp & (1 << tmp2)) != 0)
|
|
{
|
|
tmp &= (~(1 << tmp2));
|
|
}
|
|
else
|
|
{
|
|
tmp |= (1 << tmp2);
|
|
}
|
|
}
|
|
public void XchgAWReg(int Reg)
|
|
{
|
|
ushort tmp;
|
|
tmp = (ushort)(I.regs.b[Reg * 2] + I.regs.b[Reg * 2 + 1] * 0x100);
|
|
//I.regs.w[Reg] = I.regs.w[0];
|
|
//I.regs.w[0] = tmp;
|
|
I.regs.b[Reg * 2] = I.regs.b[0];
|
|
I.regs.b[Reg * 2 + 1] = I.regs.b[1];
|
|
I.regs.b[0] = (byte)(tmp % 0x100);
|
|
I.regs.b[1] = (byte)(tmp / 0x100);
|
|
}
|
|
public void ROL_BYTE(ref int dst)
|
|
{
|
|
I.CarryVal = (uint)(dst & 0x80);
|
|
dst = (dst << 1) + (CF() ? 1 : 0);
|
|
}
|
|
public void ROL_WORD(ref int dst)
|
|
{
|
|
I.CarryVal = (uint)(dst & 0x8000);
|
|
dst = (dst << 1) + (CF() ? 1 : 0);
|
|
}
|
|
public void ROR_BYTE(ref int dst)
|
|
{
|
|
I.CarryVal = (uint)(dst & 0x1);
|
|
dst = (dst >> 1) + ((CF() ? 1 : 0) << 7);
|
|
}
|
|
public void ROR_WORD(ref int dst)
|
|
{
|
|
I.CarryVal = (uint)(dst & 0x1);
|
|
dst = (dst >> 1) + ((CF() ? 1 : 0) << 15);
|
|
}
|
|
public void ROLC_BYTE(ref int dst)
|
|
{
|
|
dst = (dst << 1) + (CF() ? 1 : 0);
|
|
SetCFB((uint)dst);
|
|
}
|
|
public void ROLC_WORD(ref int dst)
|
|
{
|
|
dst = (dst << 1) + (CF() ? 1 : 0);
|
|
SetCFW((uint)dst);
|
|
}
|
|
public void RORC_BYTE(ref int dst)
|
|
{
|
|
dst = ((CF() ? 1 : 0) << 8) + dst;
|
|
I.CarryVal = (uint)(dst & 0x01);
|
|
dst >>= 1;
|
|
}
|
|
public void RORC_WORD(ref int dst)
|
|
{
|
|
dst = ((CF() ? 1 : 0) << 16) + dst;
|
|
I.CarryVal = (uint)(dst & 0x01);
|
|
dst >>= 1;
|
|
}
|
|
public void SHL_BYTE(int c, ref int dst, int ModRM)
|
|
{
|
|
pendingCycles -= c;
|
|
dst <<= c;
|
|
SetCFB((uint)dst);
|
|
SetSZPF_Byte(dst);
|
|
PutbackRMByte(ModRM, (byte)dst);
|
|
}
|
|
public void SHL_WORD(int c, ref int dst, int ModRM)
|
|
{
|
|
pendingCycles -= c;
|
|
dst <<= c;
|
|
SetCFW((uint)dst);
|
|
SetSZPF_Word(dst);
|
|
PutbackRMWord(ModRM, (ushort)dst);
|
|
}
|
|
public void SHR_BYTE(int c, ref int dst, int ModRM)
|
|
{
|
|
pendingCycles -= c;
|
|
dst >>= c - 1;
|
|
I.CarryVal = (uint)(dst & 0x1);
|
|
dst >>= 1;
|
|
SetSZPF_Byte(dst);
|
|
PutbackRMByte(ModRM, (byte)dst);
|
|
}
|
|
public void SHR_WORD(int c, ref int dst, int ModRM)
|
|
{
|
|
pendingCycles -= c;
|
|
dst >>= c - 1;
|
|
I.CarryVal = (uint)(dst & 0x1);
|
|
dst >>= 1;
|
|
SetSZPF_Word(dst);
|
|
PutbackRMWord(ModRM, (ushort)dst);
|
|
}
|
|
public void SHRA_BYTE(int c, ref int dst, int ModRM)
|
|
{
|
|
pendingCycles -= c;
|
|
dst = ((sbyte)dst) >> (c - 1);
|
|
I.CarryVal = (uint)(dst & 0x1);
|
|
dst = ((sbyte)((byte)dst)) >> 1;
|
|
SetSZPF_Byte(dst);
|
|
PutbackRMByte(ModRM, (byte)dst);
|
|
}
|
|
public void SHRA_WORD(int c, ref int dst, int ModRM)
|
|
{
|
|
pendingCycles -= c;
|
|
dst = ((short)dst) >> (c - 1);
|
|
I.CarryVal = (uint)(dst & 0x1);
|
|
dst = ((short)((ushort)dst)) >> 1;
|
|
SetSZPF_Word(dst);
|
|
PutbackRMWord(ModRM, (ushort)dst);
|
|
}
|
|
public void DIVUB(int tmp, out bool b1)
|
|
{
|
|
int uresult, uresult2;
|
|
b1 = false;
|
|
uresult = I.regs.b[0] + I.regs.b[1] * 0x100;
|
|
uresult2 = uresult % tmp;
|
|
if ((uresult /= tmp) > 0xff)
|
|
{
|
|
nec_interrupt(0, false);
|
|
b1 = true;
|
|
}
|
|
else
|
|
{
|
|
I.regs.b[0] = (byte)uresult;
|
|
I.regs.b[1] = (byte)uresult2;
|
|
}
|
|
}
|
|
public void DIVB(int tmp, out bool b1)
|
|
{
|
|
int result, result2;
|
|
b1 = false;
|
|
result = (short)(I.regs.b[0] + I.regs.b[1] * 0x100);
|
|
result2 = result % (short)((sbyte)tmp);
|
|
if ((result /= (short)((sbyte)tmp)) > 0xff)
|
|
{
|
|
nec_interrupt(0, false);
|
|
b1 = true;
|
|
}
|
|
else
|
|
{
|
|
I.regs.b[0] = (byte)result;
|
|
I.regs.b[1] = (byte)result2;
|
|
}
|
|
}
|
|
public void DIVUW(int tmp, out bool b1)
|
|
{
|
|
uint uresult, uresult2;
|
|
b1 = false;
|
|
uresult = ((uint)(I.regs.b[4] + I.regs.b[5] * 0x100) << 16) | (uint)(I.regs.b[0] + I.regs.b[1] * 0x100);
|
|
uresult2 = (uint)(uresult % tmp);
|
|
if ((uresult /= (uint)tmp) > 0xffff)
|
|
{
|
|
nec_interrupt(0, false);
|
|
b1 = true;
|
|
}
|
|
else
|
|
{
|
|
//I.regs.w[0] = (ushort)uresult;
|
|
//I.regs.w[2] = (ushort)uresult2;
|
|
I.regs.b[0] = (byte)(uresult % 0x100);
|
|
I.regs.b[1] = (byte)(uresult / 0x100);
|
|
I.regs.b[4] = (byte)(uresult2 % 0x100);
|
|
I.regs.b[5] = (byte)(uresult2 / 0x100);
|
|
}
|
|
}
|
|
public void DIVW(int tmp, out bool b1)
|
|
{
|
|
int result, result2;
|
|
b1 = false;
|
|
result = (int)(((uint)(I.regs.b[4] + I.regs.b[5] * 0x100) << 16) + (I.regs.b[0] + I.regs.b[1] * 0x100));
|
|
result2 = result % (int)((short)tmp);
|
|
if ((result /= (int)((short)tmp)) > 0xffff)
|
|
{
|
|
nec_interrupt(0, false);
|
|
b1 = true;
|
|
}
|
|
else
|
|
{
|
|
//I.regs.w[0] = (ushort)result;
|
|
//I.regs.w[2] = (ushort)result2;
|
|
I.regs.b[0] = (byte)((ushort)result % 0x100);
|
|
I.regs.b[1] = (byte)((ushort)result / 0x100);
|
|
I.regs.b[4] = (byte)((ushort)result2 % 0x100);
|
|
I.regs.b[5] = (byte)((ushort)result2 / 0x100);
|
|
}
|
|
}
|
|
public void ADD4S(ref int tmp, ref int tmp2)
|
|
{
|
|
int i, v1, v2, result;
|
|
int count = (I.regs.b[2] + 1) / 2;
|
|
ushort di = (ushort)(I.regs.b[14] + I.regs.b[15] * 0x100);
|
|
ushort si = (ushort)(I.regs.b[12] + I.regs.b[13] * 0x100);
|
|
byte[] table = new byte[] { 18, 19, 19 };
|
|
I.ZeroVal = I.CarryVal = 0;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
pendingCycles -= table[chip_type / 8];
|
|
tmp = GetMemB(3, si);
|
|
tmp2 = GetMemB(0, di);
|
|
v1 = (tmp >> 4) * 10 + (tmp & 0xf);
|
|
v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf);
|
|
result = (int)(v1 + v2 + I.CarryVal);
|
|
I.CarryVal = (uint)(result > 99 ? 1 : 0);
|
|
result = result % 100;
|
|
v1 = ((result / 10) << 4) | (result % 10);
|
|
PutMemB(0, di, (byte)v1);
|
|
if (v1 != 0)
|
|
{
|
|
I.ZeroVal = 1;
|
|
}
|
|
si++;
|
|
di++;
|
|
}
|
|
}
|
|
public void SUB4S(ref int tmp, ref int tmp2)
|
|
{
|
|
int count = (I.regs.b[2] + 1) / 2;
|
|
int i, v1, v2, result;
|
|
ushort di = (ushort)(I.regs.b[14] + I.regs.b[15] * 0x100);
|
|
ushort si = (ushort)(I.regs.b[12] + I.regs.b[13] * 0x100);
|
|
byte[] table = new byte[3] { 18, 19, 19 };
|
|
I.ZeroVal = I.CarryVal = 0;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
pendingCycles -= table[chip_type / 8];
|
|
tmp = GetMemB(0, di);
|
|
tmp2 = GetMemB(3, si);
|
|
v1 = (tmp >> 4) * 10 + (tmp & 0xf);
|
|
v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf);
|
|
if (v1 < (v2 + I.CarryVal))
|
|
{
|
|
v1 += 100;
|
|
result = (int)(v1 - (v2 + I.CarryVal));
|
|
I.CarryVal = 1;
|
|
}
|
|
else
|
|
{
|
|
result = (int)(v1 - (v2 + I.CarryVal));
|
|
I.CarryVal = 0;
|
|
}
|
|
v1 = ((result / 10) << 4) | (result % 10);
|
|
PutMemB(0, di, (byte)v1);
|
|
if (v1 != 0)
|
|
{
|
|
I.ZeroVal = 1;
|
|
}
|
|
si++;
|
|
di++;
|
|
}
|
|
}
|
|
private void CMP4S(ref int tmp, ref int tmp2)
|
|
{
|
|
int count = (I.regs.b[2] + 1) / 2;
|
|
int i, v1, v2, result;
|
|
ushort di = (ushort)(I.regs.b[14] + I.regs.b[15] * 0x100);
|
|
ushort si = (ushort)(I.regs.b[12] + I.regs.b[13] * 0x100);
|
|
byte[] table = new byte[3] { 14, 19, 19 };
|
|
I.ZeroVal = I.CarryVal = 0;
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
pendingCycles -= table[chip_type / 8];
|
|
tmp = GetMemB(0, di);
|
|
tmp2 = GetMemB(3, si);
|
|
v1 = (tmp >> 4) * 10 + (tmp & 0xf);
|
|
v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf);
|
|
if (v1 < (v2 + I.CarryVal))
|
|
{
|
|
v1 += 100;
|
|
result = (int)(v1 - (v2 + I.CarryVal));
|
|
I.CarryVal = 1;
|
|
}
|
|
else
|
|
{
|
|
result = (int)(v1 - (v2 + I.CarryVal));
|
|
I.CarryVal = 0;
|
|
}
|
|
v1 = ((result / 10) << 4) | (result % 10);
|
|
if (v1 != 0)
|
|
{
|
|
I.ZeroVal = 1;
|
|
}
|
|
si++;
|
|
di++;
|
|
}
|
|
}
|
|
public void nec_init()
|
|
{
|
|
mod_RM = new Mod_RM();
|
|
mod_RM.regw = new int[256];
|
|
mod_RM.regb = new int[256];
|
|
mod_RM.RMw = new int[256];
|
|
mod_RM.RMb = new int[256];
|
|
nec_instruction = new nec_delegate[]{
|
|
i_add_br8,
|
|
i_add_wr16,
|
|
i_add_r8b,
|
|
i_add_r16w,
|
|
i_add_ald8,
|
|
i_add_axd16,
|
|
i_push_es,
|
|
i_pop_es,
|
|
i_or_br8,
|
|
i_or_wr16,
|
|
i_or_r8b,
|
|
i_or_r16w,
|
|
i_or_ald8,
|
|
i_or_axd16,
|
|
i_push_cs,
|
|
i_pre_nec,
|
|
i_adc_br8,
|
|
i_adc_wr16,
|
|
i_adc_r8b,
|
|
i_adc_r16w,
|
|
i_adc_ald8,
|
|
i_adc_axd16,
|
|
i_push_ss,
|
|
i_pop_ss,
|
|
i_sbb_br8,
|
|
i_sbb_wr16,
|
|
i_sbb_r8b,
|
|
i_sbb_r16w,
|
|
i_sbb_ald8,
|
|
i_sbb_axd16,
|
|
i_push_ds,
|
|
i_pop_ds,
|
|
i_and_br8,
|
|
i_and_wr16,
|
|
i_and_r8b,
|
|
i_and_r16w,
|
|
i_and_ald8,
|
|
i_and_axd16,
|
|
i_es,
|
|
i_daa,
|
|
i_sub_br8,
|
|
i_sub_wr16,
|
|
i_sub_r8b,
|
|
i_sub_r16w,
|
|
i_sub_ald8,
|
|
i_sub_axd16,
|
|
i_cs,
|
|
i_das,
|
|
i_xor_br8,
|
|
i_xor_wr16,
|
|
i_xor_r8b,
|
|
i_xor_r16w,
|
|
i_xor_ald8,
|
|
i_xor_axd16,
|
|
i_ss,
|
|
i_aaa,
|
|
i_cmp_br8,
|
|
i_cmp_wr16,
|
|
i_cmp_r8b,
|
|
i_cmp_r16w,
|
|
i_cmp_ald8,
|
|
i_cmp_axd16,
|
|
i_ds,
|
|
i_aas,
|
|
i_inc_ax,
|
|
i_inc_cx,
|
|
i_inc_dx,
|
|
i_inc_bx,
|
|
i_inc_sp,
|
|
i_inc_bp,
|
|
i_inc_si,
|
|
i_inc_di,
|
|
i_dec_ax,
|
|
i_dec_cx,
|
|
i_dec_dx,
|
|
i_dec_bx,
|
|
i_dec_sp,
|
|
i_dec_bp,
|
|
i_dec_si,
|
|
i_dec_di,
|
|
i_push_ax,
|
|
i_push_cx,
|
|
i_push_dx,
|
|
i_push_bx,
|
|
i_push_sp,
|
|
i_push_bp,
|
|
i_push_si,
|
|
i_push_di,
|
|
i_pop_ax,
|
|
i_pop_cx,
|
|
i_pop_dx,
|
|
i_pop_bx,
|
|
i_pop_sp,
|
|
i_pop_bp,
|
|
i_pop_si,
|
|
i_pop_di,
|
|
i_pusha,
|
|
i_popa,
|
|
i_chkind,
|
|
i_brkn,
|
|
i_repnc,
|
|
i_repc,
|
|
i_invalid,
|
|
i_invalid,
|
|
i_push_d16,
|
|
i_imul_d16,
|
|
i_push_d8,
|
|
i_imul_d8,
|
|
i_insb,
|
|
i_insw,
|
|
i_outsb,
|
|
i_outsw,
|
|
i_jo,
|
|
i_jno,
|
|
i_jc,
|
|
i_jnc,
|
|
i_jz,
|
|
i_jnz,
|
|
i_jce,
|
|
i_jnce,
|
|
i_js,
|
|
i_jns,
|
|
i_jp,
|
|
i_jnp,
|
|
i_jl,
|
|
i_jnl,
|
|
i_jle,
|
|
i_jnle,
|
|
i_80pre,
|
|
i_81pre,
|
|
i_82pre,
|
|
i_83pre,
|
|
i_test_br8,
|
|
i_test_wr16,
|
|
i_xchg_br8,
|
|
i_xchg_wr16,
|
|
i_mov_br8,
|
|
i_mov_wr16,
|
|
i_mov_r8b,
|
|
i_mov_r16w,
|
|
i_mov_wsreg,
|
|
i_lea,
|
|
i_mov_sregw,
|
|
i_popw,
|
|
i_nop,
|
|
i_xchg_axcx,
|
|
i_xchg_axdx,
|
|
i_xchg_axbx,
|
|
i_xchg_axsp,
|
|
i_xchg_axbp,
|
|
i_xchg_axsi,
|
|
i_xchg_axdi,
|
|
i_cbw,
|
|
i_cwd,
|
|
i_call_far,
|
|
i_wait,
|
|
i_pushf,
|
|
i_popf,
|
|
i_sahf,
|
|
i_lahf,
|
|
i_mov_aldisp,
|
|
i_mov_axdisp,
|
|
i_mov_dispal,
|
|
i_mov_dispax,
|
|
i_movsb,
|
|
i_movsw,
|
|
i_cmpsb,
|
|
i_cmpsw,
|
|
i_test_ald8,
|
|
i_test_axd16,
|
|
i_stosb,
|
|
i_stosw,
|
|
i_lodsb,
|
|
i_lodsw,
|
|
i_scasb,
|
|
i_scasw,
|
|
i_mov_ald8,
|
|
i_mov_cld8,
|
|
i_mov_dld8,
|
|
i_mov_bld8,
|
|
i_mov_ahd8,
|
|
i_mov_chd8,
|
|
i_mov_dhd8,
|
|
i_mov_bhd8,
|
|
i_mov_axd16,
|
|
i_mov_cxd16,
|
|
i_mov_dxd16,
|
|
i_mov_bxd16,
|
|
i_mov_spd16,
|
|
i_mov_bpd16,
|
|
i_mov_sid16,
|
|
i_mov_did16,
|
|
i_rotshft_bd8,
|
|
i_rotshft_wd8,
|
|
i_ret_d16,
|
|
i_ret,
|
|
i_les_dw,
|
|
i_lds_dw,
|
|
i_mov_bd8,
|
|
i_mov_wd16,
|
|
i_enter,
|
|
i_leave,
|
|
i_retf_d16,
|
|
i_retf,
|
|
i_int3,
|
|
i_int,
|
|
i_into,
|
|
i_iret,
|
|
i_rotshft_b,
|
|
i_rotshft_w,
|
|
i_rotshft_bcl,
|
|
i_rotshft_wcl,
|
|
i_aam,
|
|
i_aad,
|
|
i_setalc,
|
|
i_trans,
|
|
i_fpo,
|
|
i_fpo,
|
|
i_fpo,
|
|
i_fpo,
|
|
i_fpo,
|
|
i_fpo,
|
|
i_fpo,
|
|
i_fpo,
|
|
i_loopne,
|
|
i_loope,
|
|
i_loop,
|
|
i_jcxz,
|
|
i_inal,
|
|
i_inax,
|
|
i_outal,
|
|
i_outax,
|
|
i_call_d16,
|
|
i_jmp_d16,
|
|
i_jmp_far,
|
|
i_jmp_d8,
|
|
i_inaldx,
|
|
i_inaxdx,
|
|
i_outdxal,
|
|
i_outdxax,
|
|
i_lock,
|
|
i_invalid,
|
|
i_repne,
|
|
i_repe,
|
|
i_hlt,
|
|
i_cmc,
|
|
i_f6pre,
|
|
i_f7pre,
|
|
i_clc,
|
|
i_stc,
|
|
i_di,
|
|
i_ei,
|
|
i_cld,
|
|
i_std,
|
|
i_fepre,
|
|
i_ffpre
|
|
};
|
|
GetEA = new getea_delegate[192]{
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
|
|
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
|
|
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
|
|
EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207
|
|
};
|
|
}
|
|
public override void Reset()
|
|
{
|
|
nec_reset();
|
|
}
|
|
public void nec_reset()
|
|
{
|
|
//const nec_config *config;
|
|
uint i, j, c;
|
|
//BREGS[] reg_name = new BREGS[8] { BREGS.AL, BREGS.CL, BREGS.DL, BREGS.BL, BREGS.AH, BREGS.CH, BREGS.DH, BREGS.BH };
|
|
int[] reg_name = new int[8] { 0, 2, 4, 6, 1, 3, 5, 7 };
|
|
//int (*save_irqcallback)(int);
|
|
//memory_interface save_mem;
|
|
//save_irqcallback = I.irq_callback;
|
|
//save_mem = I.mem;
|
|
//config = I.config;
|
|
I.sregs = new ushort[4];
|
|
I.regs.b = new byte[16];
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
I.sregs[i] = 0;
|
|
}
|
|
I.ip = 0;
|
|
I.SignVal = 0;
|
|
I.AuxVal = 0;
|
|
I.OverVal = 0;
|
|
I.ZeroVal = 0;
|
|
I.CarryVal = 0;
|
|
I.ParityVal = 0;
|
|
I.TF = false;
|
|
I.IF = false;
|
|
I.DF = false;
|
|
I.MF = false;
|
|
I.int_vector = 0;
|
|
I.pending_irq = 0;
|
|
I.irq_state = 0;
|
|
I.poll_state = false;
|
|
I.no_interrupt = 0;
|
|
//I.irq_callback = save_irqcallback;
|
|
//I.mem = save_mem;
|
|
//I.config = config;
|
|
I.sregs[1] = 0xffff;
|
|
//PC = (I.sregs[1] << 4) + I.ip;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
for (j = i, c = 0; j > 0; j >>= 1)
|
|
{
|
|
if ((j & 1) != 0)
|
|
{
|
|
c++;
|
|
}
|
|
}
|
|
parity_table[i] = ((c & 1) == 0);
|
|
}
|
|
I.ZeroVal = I.ParityVal = 1;
|
|
I.MF = true;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
mod_RM.regb[i] = reg_name[(i & 0x38) >> 3];
|
|
mod_RM.regw[i] = (int)((i & 0x38) >> 3);
|
|
}
|
|
for (i = 0xc0; i < 0x100; i++)
|
|
{
|
|
mod_RM.RMw[i] = (int)(i & 7);
|
|
mod_RM.RMb[i] = reg_name[i & 7];
|
|
}
|
|
I.poll_state = true;
|
|
}
|
|
public void nec_interrupt(int int_num, bool md_flag)
|
|
{
|
|
uint dest_seg, dest_off;
|
|
i_pushf();
|
|
I.TF = I.IF = false;
|
|
if (md_flag)
|
|
{
|
|
I.MF = false;
|
|
}
|
|
if (int_num == -1)
|
|
{
|
|
int_num = Cpuint.cpu_irq_callback(cpunum, 0);
|
|
I.irq_state = 0;
|
|
I.pending_irq &= 0xfffffffe;
|
|
}
|
|
dest_off = ReadWord(int_num * 4);
|
|
dest_seg = ReadWord(int_num * 4 + 2);
|
|
PUSH(I.sregs[1]);
|
|
PUSH(I.ip);
|
|
I.ip = (ushort)dest_off;
|
|
I.sregs[1] = (ushort)dest_seg;
|
|
//CHANGE_PC;
|
|
}
|
|
public void nec_trap()
|
|
{
|
|
nec_instruction[fetchop()]();
|
|
nec_interrupt(1, false);
|
|
}
|
|
public void external_int()
|
|
{
|
|
if ((I.pending_irq & 0x02) != 0)
|
|
{
|
|
nec_interrupt(2, false);
|
|
I.pending_irq &= unchecked((uint)(~2));
|
|
}
|
|
else if (I.pending_irq != 0)
|
|
{
|
|
nec_interrupt(-1, false);
|
|
}
|
|
}
|
|
public void SaveStateBinary(BinaryWriter writer)
|
|
{
|
|
int i;
|
|
writer.Write(I.regs.b, 0, 16);
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
writer.Write(I.sregs[i]);
|
|
}
|
|
writer.Write(I.ip);
|
|
writer.Write(I.TF);
|
|
writer.Write(I.IF);
|
|
writer.Write(I.DF);
|
|
writer.Write(I.MF);
|
|
writer.Write(I.SignVal);
|
|
writer.Write(I.int_vector);
|
|
writer.Write(I.pending_irq);
|
|
writer.Write(I.nmi_state);
|
|
writer.Write(I.irq_state);
|
|
writer.Write(I.poll_state);
|
|
writer.Write(I.AuxVal);
|
|
writer.Write(I.OverVal);
|
|
writer.Write(I.ZeroVal);
|
|
writer.Write(I.CarryVal);
|
|
writer.Write(I.ParityVal);
|
|
writer.Write(I.no_interrupt);
|
|
writer.Write(prefix_base);
|
|
writer.Write(seg_prefix);
|
|
writer.Write(TotalExecutedCycles);
|
|
writer.Write(PendingCycles);
|
|
}
|
|
public void LoadStateBinary(BinaryReader reader)
|
|
{
|
|
int i;
|
|
I.regs.b = reader.ReadBytes(16);
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
I.sregs[i] = reader.ReadUInt16();
|
|
}
|
|
I.ip = reader.ReadUInt16();
|
|
I.TF = reader.ReadBoolean();
|
|
I.IF = reader.ReadBoolean();
|
|
I.DF = reader.ReadBoolean();
|
|
I.MF = reader.ReadBoolean();
|
|
I.SignVal = reader.ReadInt32();
|
|
I.int_vector = reader.ReadUInt32();
|
|
I.pending_irq = reader.ReadUInt32();
|
|
I.nmi_state = reader.ReadUInt32();
|
|
I.irq_state = reader.ReadUInt32();
|
|
I.poll_state = reader.ReadBoolean();
|
|
I.AuxVal = reader.ReadUInt32();
|
|
I.OverVal = reader.ReadUInt32();
|
|
I.ZeroVal = reader.ReadUInt32();
|
|
I.CarryVal = reader.ReadUInt32();
|
|
I.ParityVal = reader.ReadUInt32();
|
|
I.no_interrupt = reader.ReadByte();
|
|
prefix_base = reader.ReadInt32();
|
|
seg_prefix = reader.ReadInt32();
|
|
TotalExecutedCycles = reader.ReadUInt64();
|
|
PendingCycles = reader.ReadInt32();
|
|
}
|
|
}
|
|
public class V30 : Nec
|
|
{
|
|
public V30()
|
|
{
|
|
nec_init();
|
|
chip_type = 8;
|
|
}
|
|
public override int ExecuteCycles(int cycles)
|
|
{
|
|
return v30_execute(cycles);
|
|
}
|
|
public int v30_execute(int cycles)
|
|
{
|
|
pendingCycles = cycles;
|
|
while (pendingCycles > 0)
|
|
{
|
|
int prevCycles = pendingCycles;
|
|
if (I.pending_irq != 0 && I.no_interrupt == 0)
|
|
{
|
|
if ((I.pending_irq & NMI_IRQ) != 0)
|
|
{
|
|
external_int();
|
|
}
|
|
else if (I.IF)
|
|
{
|
|
external_int();
|
|
}
|
|
}
|
|
if (I.no_interrupt != 0)
|
|
{
|
|
I.no_interrupt--;
|
|
}
|
|
iNOP = fetchop();
|
|
nec_instruction[iNOP]();
|
|
int delta = prevCycles - pendingCycles;
|
|
totalExecutedCycles += (ulong)delta;
|
|
}
|
|
return cycles - pendingCycles;
|
|
}
|
|
}
|
|
public class V33 : Nec
|
|
{
|
|
public V33()
|
|
{
|
|
nec_init();
|
|
chip_type = 0;
|
|
}
|
|
public override int ExecuteCycles(int cycles)
|
|
{
|
|
return v33_execute(cycles);
|
|
}
|
|
public int v33_execute(int cycles)
|
|
{
|
|
pendingCycles = cycles;
|
|
while (pendingCycles > 0)
|
|
{
|
|
int prevCycles = pendingCycles;
|
|
if (I.pending_irq != 0 && I.no_interrupt == 0)
|
|
{
|
|
if ((I.pending_irq & NMI_IRQ) != 0)
|
|
{
|
|
external_int();
|
|
}
|
|
else if (I.IF)
|
|
{
|
|
external_int();
|
|
}
|
|
}
|
|
if (I.no_interrupt != 0)
|
|
{
|
|
I.no_interrupt--;
|
|
}
|
|
iNOP = fetchop();
|
|
nec_instruction[iNOP]();
|
|
int delta = prevCycles - pendingCycles;
|
|
totalExecutedCycles += (ulong)delta;
|
|
}
|
|
return cycles - pendingCycles;
|
|
}
|
|
}
|
|
}
|