diff --git a/BizHawk.Emulation/CPUs/CP1610/CP1610.cs b/BizHawk.Emulation/CPUs/CP1610/CP1610.cs index 679a3e3642..0bfef2db09 100644 --- a/BizHawk.Emulation/CPUs/CP1610/CP1610.cs +++ b/BizHawk.Emulation/CPUs/CP1610/CP1610.cs @@ -8,7 +8,7 @@ namespace BizHawk.Emulation.CPUs.CP1610 private const ushort RESET = 0x1000; private const ushort INTERRUPT = 0x1004; - private bool FlagS, FlagC, FlagZ, FlagO, FlagI, FlagD, MSync, Interruptible; + private bool FlagS, FlagC, FlagZ, FlagO, FlagI, FlagD, IntRM, BusRq, BusAk, MSync, Interruptible; private ushort[] Register = new ushort[8]; private ushort RegisterSP { get { return Register[6]; } set { Register[6] = value; } } private ushort RegisterPC { get { return Register[7]; } set { Register[7] = value; } } @@ -18,14 +18,6 @@ namespace BizHawk.Emulation.CPUs.CP1610 public Func ReadMemory; public Func WriteMemory; - public Func GetIntRM; - public Func GetBusRq; - public Func GetBusAk; - public Action SetBusAk; - - private bool IntRM { get { return GetIntRM(); } } - private bool BusRq { get { return GetBusRq(); } } - private bool BusAk { get { return GetBusAk(); } set { SetBusAk(value); } } private static bool logging = true; private static StreamWriter log; @@ -46,6 +38,31 @@ namespace BizHawk.Emulation.CPUs.CP1610 RegisterPC = RESET; } + public bool GetBusAk() + { + return BusAk; + } + + public void SetIntRM(bool value) + { + IntRM = value; + } + + public int GetPendingCycles() + { + return PendingCycles; + } + + public void SetBusRq(bool value) + { + BusRq = value; + } + + public void AddPendingCycles(int cycles) + { + PendingCycles += cycles; + } + public void LogData() { if (!logging) diff --git a/BizHawk.Emulation/CPUs/CP1610/Execute.cs b/BizHawk.Emulation/CPUs/CP1610/Execute.cs index 286a7a298b..9a6b05cb47 100644 --- a/BizHawk.Emulation/CPUs/CP1610/Execute.cs +++ b/BizHawk.Emulation/CPUs/CP1610/Execute.cs @@ -49,23 +49,12 @@ namespace BizHawk.Emulation.CPUs.CP1610 if (mem == 0x6) RegisterSP--; if (!FlagD) - { value = ReadMemory(Register[mem]); - if (mem != 0x6) - { - PendingCycles -= 8; TotalExecutedCycles += 8; - } - else - { - PendingCycles -= 11; TotalExecutedCycles += 11; - } - } else { // Double Byte Data. value = (ushort)(ReadMemory(Register[mem]++) & 0xFF); value |= (ushort)(ReadMemory(Register[mem]) << 8); - PendingCycles -= 10; TotalExecutedCycles += 10; } // Auto-increment the memory register if it does so on write. if (mem >= 0x4 && mem != 0x6) @@ -73,23 +62,23 @@ namespace BizHawk.Emulation.CPUs.CP1610 return value; } - public void Indirect_Get_Cycles(byte mem) + public int Indirect_Get_Cycles(byte mem) { if (!FlagD) { if (mem != 0x6) { - PendingCycles -= 8; TotalExecutedCycles += 8; + return 8; } else { - PendingCycles -= 11; TotalExecutedCycles += 11; + return 11; } } else { // Double Byte Data. - PendingCycles -= 10; TotalExecutedCycles += 10; + return 10; } } @@ -101,1721 +90,1697 @@ namespace BizHawk.Emulation.CPUs.CP1610 Register[mem]++; } - public void Execute(int cycles) + public void Execute() { - PendingCycles += cycles; - while (PendingCycles > 0) + if (logging) { - if (logging) - { - int addrToAdvance; - log.WriteLine("------"); - log.WriteLine(); - log.WriteLine(Disassemble(RegisterPC, out addrToAdvance)); - log.Flush(); - } - if (FlagI && Interruptible && !IntRM) - { - Indirect_Set(6, 7); - RegisterPC = INTERRUPT; - } - byte dest, src, mem; - ushort dest_value, src_value, mem_read, addr, addr_read, offset; - int decle2, decle3, result = 0, ones, carry, status_word, lower, sign, cond, ext; - bool branch = false; - bool prev_FlagD = FlagD; - int opcode = ReadMemory(RegisterPC++) & 0x3FF; - switch (opcode) - { - case 0x000: // HLT - throw new ArgumentException(UNEXPECTED_HLT); - case 0x001: // SDBD - FlagD = true; - PendingCycles -= 4; TotalExecutedCycles += 4; - Interruptible = false; - break; - case 0x002: // EIS - FlagI = true; - PendingCycles -= 4; TotalExecutedCycles += 4; - Interruptible = false; - break; - case 0x003: // DIS - FlagI = false; - PendingCycles -= 4; TotalExecutedCycles += 4; - Interruptible = false; - break; - case 0x004: // J, JE, JD, JSR, JSRE, JSRD - // 0000:0000:0000:0100 0000:00rr:aaaa:aaff 0000:00aa:aaaa:aaaa - decle2 = ReadMemory(RegisterPC++); - decle3 = ReadMemory(RegisterPC++); - // rr indicates the register into which to store the return address - dest = (byte)(((decle2 >> 8) & 0x3) + 4); - // aaaaaaaaaaaaaaaa indicates the address to where the CP1610 should Jump - addr = (ushort)(((decle2 << 8) & 0xFC00) | (decle3 & 0x3FF)); - if (dest != 0x7) - // Store the return address. - Register[dest] = (ushort)(RegisterPC & 0xFFFF); - // ff indicates how to affect the Interrupt (I) flag in the CP1610 - switch (decle2 & 0x3) - { - case 0x1: - FlagI = true; - break; - case 0x2: - FlagI = false; - break; - case 0x3: - // Unknown opcode. - throw new ArgumentException(); - } - RegisterPC = (ushort)addr; - PendingCycles -= 12; TotalExecutedCycles += 12; - Interruptible = true; - break; - case 0x005: // TCI - throw new ArgumentException(UNEXPECTED_TCI); - case 0x006: // CLRC - FlagC = false; - PendingCycles -= 4; TotalExecutedCycles += 4; - Interruptible = false; - break; - case 0x007: // SETC - FlagC = true; - PendingCycles -= 4; TotalExecutedCycles += 4; - Interruptible = false; - break; - // INCR - case 0x008: - case 0x009: - case 0x00A: - case 0x00B: - case 0x00C: - case 0x00D: - case 0x00E: - case 0x00F: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - result = (Register[dest] + 1) & 0xFFFF; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // DECR - case 0x010: - case 0x011: - case 0x012: - case 0x013: - case 0x014: - case 0x015: - case 0x016: - case 0x017: - dest = (byte)(opcode & 0x7); - result = (Register[dest] - 1) & 0xFFFF; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // COMR - case 0x018: - case 0x019: - case 0x01A: - case 0x01B: - case 0x01C: - case 0x01D: - case 0x01E: - case 0x01F: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - result = (Register[dest] ^ 0xFFFF); - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // NEGR - case 0x020: - case 0x021: - case 0x022: - case 0x023: - case 0x024: - case 0x025: - case 0x026: - case 0x027: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - dest_value = Register[dest]; - ones = (dest_value ^ 0xFFFF); - result = ones + 1; - Calc_FlagC(result); - Calc_FlagO_Add(ones, 1); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // ADCR - case 0x028: - case 0x029: - case 0x02A: - case 0x02B: - case 0x02C: - case 0x02D: - case 0x02E: - case 0x02F: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - dest_value = Register[dest]; - carry = FlagC ? 1 : 0; - result = dest_value + carry; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, carry); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // GSWD - case 0x030: - case 0x031: - case 0x032: - case 0x033: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - status_word = ((FlagS ? 1 : 0) << 3) | ((FlagZ ? 1 : 0) << 2) | ((FlagO ? 1 : 0) << 1) | - (FlagC ? 1 : 0); - Register[dest] = (ushort)((status_word << 12) | (status_word << 4)); - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // NOP - case 0x034: - case 0x035: - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // SIN - case 0x036: - case 0x037: - throw new ArgumentException(UNEXPECTED_SIN); - // RSWD - case 0x038: - case 0x039: - case 0x03A: - case 0x03B: - case 0x03C: - case 0x03D: - case 0x03E: - case 0x03F: - throw new NotImplementedException(); - src = (byte)(opcode & 0x7); - src_value = Register[src]; - FlagC = ((src_value & 0x80) != 0) ? true : false; - FlagO = ((src_value & 0x40) != 0) ? true : false; - FlagZ = ((src_value & 0x20) != 0) ? true : false; - FlagS = ((src_value & 0x10) != 0) ? true : false; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // SWAP - case 0x040: - case 0x041: - case 0x042: - case 0x043: - case 0x044: - case 0x045: - case 0x046: - case 0x047: - dest = (byte)(opcode & 0x3); - dest_value = Register[dest]; - lower = dest_value & 0xFF; - if (((opcode >> 3) & 0x1) == 0) - { - // Single swap. - result = (lower << 8) | ((dest_value >> 8) & 0xFF); - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double swap. - result = (lower << 8) | lower; - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS_7(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // SLL - case 0x048: - case 0x049: - case 0x04A: - case 0x04B: - case 0x04C: - case 0x04D: - case 0x04E: - case 0x04F: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - result = Register[dest] << 1; - if (((opcode >> 3) & 0x1) == 0) - { - // Single shift. - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double shift. - result <<= 1; - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // RLC - case 0x050: - case 0x051: - case 0x052: - case 0x053: - case 0x054: - case 0x055: - case 0x056: - case 0x057: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - dest_value = Register[dest]; - result = (dest_value << 1) | (FlagC ? 1 : 0); - FlagC = ((dest_value & 0x8000) != 0); - if (((opcode >> 3) & 0x1) == 0) - { - // Single rotate. - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double rotate. - result <<= 1; - result |= (FlagO ? 1 : 0); - FlagO = ((dest_value & 0x4000) != 0); - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // SLLC - case 0x058: - case 0x059: - case 0x05A: - case 0x05B: - case 0x05C: - case 0x05D: - case 0x05E: - case 0x05F: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - dest_value = Register[dest]; - result = dest_value << 1; - FlagC = ((dest_value & 0x8000) != 0); - if (((opcode >> 3) & 0x1) == 0) - { - // Single shift. - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double shift. - result <<= 1; - FlagO = ((dest_value & 0x4000) != 0); - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // SLR - case 0x060: - case 0x061: - case 0x062: - case 0x063: - case 0x064: - case 0x065: - case 0x066: - case 0x067: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - result = Register[dest] >> 1; - if (((opcode >> 3) & 0x1) == 0) - { - // Single shift. - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double shift. - result >>= 1; - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS_7(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // SAR - case 0x068: - case 0x069: - case 0x06A: - case 0x06B: - case 0x06C: - case 0x06D: - case 0x06E: - case 0x06F: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - dest_value = Register[dest]; - sign = dest_value & 0x8000; - result = (dest_value >> 1) | sign; - if (((opcode >> 3) & 0x1) == 0) - { - // Single shift. - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double shift. - result >>= 1; - result |= sign; - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS_7(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // RRC - case 0x070: - case 0x071: - case 0x072: - case 0x073: - case 0x074: - case 0x075: - case 0x076: - case 0x077: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - dest_value = Register[dest]; - result = (dest_value >> 1) | ((FlagC ? 1 : 0) << 15); - FlagC = ((dest_value & 0x1) != 0); - if (((opcode >> 3) & 0x1) == 0) - { - // Single rotate. - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double rotate. - result >>= 1; - result |= (FlagO ? 1 : 0) << 15; - FlagO = ((dest_value & 0x2) != 0); - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS_7(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // SARC - case 0x078: - case 0x079: - case 0x07A: - case 0x07B: - case 0x07C: - case 0x07D: - case 0x07E: - case 0x07F: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x3); - dest_value = Register[dest]; - sign = dest_value & 0x8000; - result = (dest_value >> 1) | sign; - FlagC = ((dest_value & 0x1) != 0); - if (((opcode >> 3) & 0x1) == 0) - { - // Single shift. - PendingCycles -= 6; TotalExecutedCycles += 6; - } - else - { - // Double shift. - result >>= 1; - result |= sign; - FlagO = ((dest_value & 0x2) != 0); - PendingCycles -= 8; TotalExecutedCycles += 8; - } - Calc_FlagS_7(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = false; - break; - // MOVR - case 0x080: - case 0x081: - case 0x082: - case 0x083: - case 0x084: - case 0x085: - case 0x086: - case 0x087: - case 0x088: - case 0x089: - case 0x08A: - case 0x08B: - case 0x08C: - case 0x08D: - case 0x08E: - case 0x08F: - case 0x090: - case 0x091: - case 0x092: - case 0x093: - case 0x094: - case 0x095: - case 0x096: - case 0x097: - case 0x098: - case 0x099: - case 0x09A: - case 0x09B: - case 0x09C: - case 0x09D: - case 0x09E: - case 0x09F: - case 0x0A0: - case 0x0A1: - case 0x0A2: - case 0x0A3: - case 0x0A4: - case 0x0A5: - case 0x0A6: - case 0x0A7: - case 0x0A8: - case 0x0A9: - case 0x0AA: - case 0x0AB: - case 0x0AC: - case 0x0AD: - case 0x0AE: - case 0x0AF: - case 0x0B0: - case 0x0B1: - case 0x0B2: - case 0x0B3: - case 0x0B4: - case 0x0B5: - case 0x0B6: - case 0x0B7: - case 0x0B8: - case 0x0B9: - case 0x0BA: - case 0x0BB: - case 0x0BC: - case 0x0BD: - case 0x0BE: - case 0x0BF: - src = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - result = Register[src]; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - if (dest == 0x6 || dest == 0x7) - { - PendingCycles -= 7; TotalExecutedCycles += 7; - } - else - { - PendingCycles -= 6; TotalExecutedCycles += 6; - } - Interruptible = true; - break; - // ADDR - case 0x0C0: - case 0x0C1: - case 0x0C2: - case 0x0C3: - case 0x0C4: - case 0x0C5: - case 0x0C6: - case 0x0C7: - case 0x0C8: - case 0x0C9: - case 0x0CA: - case 0x0CB: - case 0x0CC: - case 0x0CD: - case 0x0CE: - case 0x0CF: - case 0x0D0: - case 0x0D1: - case 0x0D2: - case 0x0D3: - case 0x0D4: - case 0x0D5: - case 0x0D6: - case 0x0D7: - case 0x0D8: - case 0x0D9: - case 0x0DA: - case 0x0DB: - case 0x0DC: - case 0x0DD: - case 0x0DE: - case 0x0DF: - case 0x0E0: - case 0x0E1: - case 0x0E2: - case 0x0E3: - case 0x0E4: - case 0x0E5: - case 0x0E6: - case 0x0E7: - case 0x0E8: - case 0x0E9: - case 0x0EA: - case 0x0EB: - case 0x0EC: - case 0x0ED: - case 0x0EE: - case 0x0EF: - case 0x0F0: - case 0x0F1: - case 0x0F2: - case 0x0F3: - case 0x0F4: - case 0x0F5: - case 0x0F6: - case 0x0F7: - case 0x0F8: - case 0x0F9: - case 0x0FA: - case 0x0FB: - case 0x0FC: - case 0x0FD: - case 0x0FE: - case 0x0FF: - throw new NotImplementedException(); - src = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - src_value = Register[src]; - dest_value = Register[dest]; - result = dest_value + src_value; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, src_value); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // SUBR - case 0x100: - case 0x101: - case 0x102: - case 0x103: - case 0x104: - case 0x105: - case 0x106: - case 0x107: - case 0x108: - case 0x109: - case 0x10A: - case 0x10B: - case 0x10C: - case 0x10D: - case 0x10E: - case 0x10F: - case 0x110: - case 0x111: - case 0x112: - case 0x113: - case 0x114: - case 0x115: - case 0x116: - case 0x117: - case 0x118: - case 0x119: - case 0x11A: - case 0x11B: - case 0x11C: - case 0x11D: - case 0x11E: - case 0x11F: - case 0x120: - case 0x121: - case 0x122: - case 0x123: - case 0x124: - case 0x125: - case 0x126: - case 0x127: - case 0x128: - case 0x129: - case 0x12A: - case 0x12B: - case 0x12C: - case 0x12D: - case 0x12E: - case 0x12F: - case 0x130: - case 0x131: - case 0x132: - case 0x133: - case 0x134: - case 0x135: - case 0x136: - case 0x137: - case 0x138: - case 0x139: - case 0x13A: - case 0x13B: - case 0x13C: - case 0x13D: - case 0x13E: - case 0x13F: - throw new NotImplementedException(); - src = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - src_value = Register[src]; - dest_value = Register[dest]; - result = Register[dest] - Register[src]; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, -src_value); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // CMPR - case 0x140: - case 0x141: - case 0x142: - case 0x143: - case 0x144: - case 0x145: - case 0x146: - case 0x147: - case 0x148: - case 0x149: - case 0x14A: - case 0x14B: - case 0x14C: - case 0x14D: - case 0x14E: - case 0x14F: - case 0x150: - case 0x151: - case 0x152: - case 0x153: - case 0x154: - case 0x155: - case 0x156: - case 0x157: - case 0x158: - case 0x159: - case 0x15A: - case 0x15B: - case 0x15C: - case 0x15D: - case 0x15E: - case 0x15F: - case 0x160: - case 0x161: - case 0x162: - case 0x163: - case 0x164: - case 0x165: - case 0x166: - case 0x167: - case 0x168: - case 0x169: - case 0x16A: - case 0x16B: - case 0x16C: - case 0x16D: - case 0x16E: - case 0x16F: - case 0x170: - case 0x171: - case 0x172: - case 0x173: - case 0x174: - case 0x175: - case 0x176: - case 0x177: - case 0x178: - case 0x179: - case 0x17A: - case 0x17B: - case 0x17C: - case 0x17D: - case 0x17E: - case 0x17F: - throw new NotImplementedException(); - src = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - src_value = Register[src]; - dest_value = Register[dest]; - result = dest_value - src_value; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, -src_value); - Calc_FlagS(result); - Calc_FlagZ(result); - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // ANDR - case 0x180: - case 0x181: - case 0x182: - case 0x183: - case 0x184: - case 0x185: - case 0x186: - case 0x187: - case 0x188: - case 0x189: - case 0x18A: - case 0x18B: - case 0x18C: - case 0x18D: - case 0x18E: - case 0x18F: - case 0x190: - case 0x191: - case 0x192: - case 0x193: - case 0x194: - case 0x195: - case 0x196: - case 0x197: - case 0x198: - case 0x199: - case 0x19A: - case 0x19B: - case 0x19C: - case 0x19D: - case 0x19E: - case 0x19F: - case 0x1A0: - case 0x1A1: - case 0x1A2: - case 0x1A3: - case 0x1A4: - case 0x1A5: - case 0x1A6: - case 0x1A7: - case 0x1A8: - case 0x1A9: - case 0x1AA: - case 0x1AB: - case 0x1AC: - case 0x1AD: - case 0x1AE: - case 0x1AF: - case 0x1B0: - case 0x1B1: - case 0x1B2: - case 0x1B3: - case 0x1B4: - case 0x1B5: - case 0x1B6: - case 0x1B7: - case 0x1B8: - case 0x1B9: - case 0x1BA: - case 0x1BB: - case 0x1BC: - case 0x1BD: - case 0x1BE: - case 0x1BF: - throw new NotImplementedException(); - src = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - result = Register[dest] & Register[src]; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // XORR - case 0x1C0: - case 0x1C1: - case 0x1C2: - case 0x1C3: - case 0x1C4: - case 0x1C5: - case 0x1C6: - case 0x1C7: - case 0x1C8: - case 0x1C9: - case 0x1CA: - case 0x1CB: - case 0x1CC: - case 0x1CD: - case 0x1CE: - case 0x1CF: - case 0x1D0: - case 0x1D1: - case 0x1D2: - case 0x1D3: - case 0x1D4: - case 0x1D5: - case 0x1D6: - case 0x1D7: - case 0x1D8: - case 0x1D9: - case 0x1DA: - case 0x1DB: - case 0x1DC: - case 0x1DD: - case 0x1DE: - case 0x1DF: - case 0x1E0: - case 0x1E1: - case 0x1E2: - case 0x1E3: - case 0x1E4: - case 0x1E5: - case 0x1E6: - case 0x1E7: - case 0x1E8: - case 0x1E9: - case 0x1EA: - case 0x1EB: - case 0x1EC: - case 0x1ED: - case 0x1EE: - case 0x1EF: - case 0x1F0: - case 0x1F1: - case 0x1F2: - case 0x1F3: - case 0x1F4: - case 0x1F5: - case 0x1F6: - case 0x1F7: - case 0x1F8: - case 0x1F9: - case 0x1FA: - case 0x1FB: - case 0x1FC: - case 0x1FD: - case 0x1FE: - case 0x1FF: - src = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - result = Register[dest] ^ Register[src]; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - PendingCycles -= 6; TotalExecutedCycles += 6; - Interruptible = true; - break; - // Branch Forward, no External Condition - case 0x200: // B - case 0x201: // BC - case 0x202: // BOV - case 0x203: // BPL - case 0x204: // BEQ - case 0x205: // BLT - case 0x206: // BLE - case 0x207: // BUSC - case 0x208: // NOPP - case 0x209: // BNC - case 0x20A: // BNOV - case 0x20B: // BMI - case 0x20C: // BNEQ - case 0x20D: // BGE - case 0x20E: // BGT - case 0x20F: // BESC - // Branch Forward, Exteranl Condition (BEXT) - case 0x210: - case 0x211: - case 0x212: - case 0x213: - case 0x214: - case 0x215: - case 0x216: - case 0x217: - case 0x218: - case 0x219: - case 0x21A: - case 0x21B: - case 0x21C: - case 0x21D: - case 0x21E: - case 0x21F: - // Branch Reverse, no External Condition - case 0x220: // B - case 0x221: // BC - case 0x222: // BOV - case 0x223: // BPL - case 0x224: // BEQ - case 0x225: // BLT - case 0x226: // BLE - case 0x227: // BUSC - case 0x228: // NOPP - case 0x229: // BNC - case 0x22A: // BNOV - case 0x22B: // BMI - case 0x22C: // BNEQ - case 0x22D: // BGE - case 0x22E: // BGT - case 0x22F: // BESC - // Branch Reverse, Exteranl Condition (BEXT) - case 0x230: - case 0x231: - case 0x232: - case 0x233: - case 0x234: - case 0x235: - case 0x236: - case 0x237: - case 0x238: - case 0x239: - case 0x23A: - case 0x23B: - case 0x23C: - case 0x23D: - case 0x23E: - case 0x23F: - offset = ReadMemory(RegisterPC++); - cond = opcode & 0xF; - ext = opcode & 0x10; - // BEXT - if (ext != 0) - throw new ArgumentException(UNEXPECTED_BEXT); - else - { - switch (cond) - { - // B - case 0x0: - branch = true; - break; - // BC - case 0x1: - branch = FlagC; - break; - // BOV - case 0x2: - branch = FlagO; - break; - // BPL - case 0x3: - branch = !FlagS; - break; - // BEQ - case 0x4: - branch = FlagZ; - break; - // BLT - case 0x5: - branch = (FlagS != FlagO); - break; - // BLE - case 0x6: - branch = (FlagZ || FlagS != FlagO); - break; - // BUSC - case 0x7: - branch = (FlagC != FlagS); - break; - // NOPP - case 0x8: - branch = false; - break; - // BNC - case 0x9: - branch = !FlagC; - break; - // BNOV - case 0xA: - branch = !FlagO; - break; - // BMI - case 0xB: - branch = FlagS; - break; - // BNEQ - case 0xC: - branch = !FlagZ; - break; - // BGE - case 0xD: - branch = (FlagS == FlagO); - break; - // BGT - case 0xE: - branch = (!FlagZ && FlagS == FlagO); - break; - // BESC - case 0xF: - branch = (FlagC == FlagS); - break; - } - } - if (branch) - { - // Branch in the reverse direction by negating the offset and subtracting 1. - if (((opcode >> 5) & 0x1) != 0) - offset = (ushort)(-offset - 1); - RegisterPC += offset; - PendingCycles -= 9; TotalExecutedCycles += 9; - } - else - { - PendingCycles -= 7; TotalExecutedCycles += 7; - } - Interruptible = true; - break; - // MVO - case 0x240: - case 0x241: - case 0x242: - case 0x243: - case 0x244: - case 0x245: - case 0x246: - case 0x247: - src = (byte)(opcode & 0x7); - addr = ReadMemory(RegisterPC++); - WriteMemory(addr, Register[src]); - PendingCycles -= 11; TotalExecutedCycles += 11; - Interruptible = false; - break; - // MVO@ - case 0x248: - case 0x249: - case 0x24A: - case 0x24B: - case 0x24C: - case 0x24D: - case 0x24E: - case 0x24F: - case 0x250: - case 0x251: - case 0x252: - case 0x253: - case 0x254: - case 0x255: - case 0x256: - case 0x257: - case 0x258: - case 0x259: - case 0x25A: - case 0x25B: - case 0x25C: - case 0x25D: - case 0x25E: - case 0x25F: - case 0x260: - case 0x261: - case 0x262: - case 0x263: - case 0x264: - case 0x265: - case 0x266: - case 0x267: - case 0x268: - case 0x269: - case 0x26A: - case 0x26B: - case 0x26C: - case 0x26D: - case 0x26E: - case 0x26F: - case 0x270: - case 0x271: - case 0x272: - case 0x273: - case 0x274: - case 0x275: - case 0x276: - case 0x277: - case 0x278: - case 0x279: - case 0x27A: - case 0x27B: - case 0x27C: - case 0x27D: - case 0x27E: - case 0x27F: - mem = (byte)((opcode >> 3) & 0x7); - src = (byte)(opcode & 0x7); - Indirect_Set(mem, src); - PendingCycles -= 9; TotalExecutedCycles += 9; - Interruptible = false; - break; - // MVI - case 0x280: - case 0x281: - case 0x282: - case 0x283: - case 0x284: - case 0x285: - case 0x286: - case 0x287: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - addr = ReadMemory(RegisterPC++); - Register[dest] = ReadMemory(addr); - PendingCycles -= 10; TotalExecutedCycles += 10; - Interruptible = true; - break; - // MVI@ - case 0x288: - case 0x289: - case 0x28A: - case 0x28B: - case 0x28C: - case 0x28D: - case 0x28E: - case 0x28F: - case 0x290: - case 0x291: - case 0x292: - case 0x293: - case 0x294: - case 0x295: - case 0x296: - case 0x297: - case 0x298: - case 0x299: - case 0x29A: - case 0x29B: - case 0x29C: - case 0x29D: - case 0x29E: - case 0x29F: - case 0x2A0: - case 0x2A1: - case 0x2A2: - case 0x2A3: - case 0x2A4: - case 0x2A5: - case 0x2A6: - case 0x2A7: - case 0x2A8: - case 0x2A9: - case 0x2AA: - case 0x2AB: - case 0x2AC: - case 0x2AD: - case 0x2AE: - case 0x2AF: - case 0x2B0: - case 0x2B1: - case 0x2B2: - case 0x2B3: - case 0x2B4: - case 0x2B5: - case 0x2B6: - case 0x2B7: - case 0x2B8: - case 0x2B9: - case 0x2BA: - case 0x2BB: - case 0x2BC: - case 0x2BD: - case 0x2BE: - case 0x2BF: - mem = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - Register[dest] = Indirect_Get(mem); - Indirect_Get_Cycles(mem); - Interruptible = true; - break; - // ADD - case 0x2C0: - case 0x2C1: - case 0x2C2: - case 0x2C3: - case 0x2C4: - case 0x2C5: - case 0x2C6: - case 0x2C7: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - addr = ReadMemory(RegisterPC++); - dest_value = Register[dest]; - addr_read = ReadMemory(addr); - result = dest_value + addr_read; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, addr_read); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - PendingCycles -= 10; TotalExecutedCycles += 10; - Interruptible = true; - break; - // ADD@ - case 0x2C8: - case 0x2C9: - case 0x2CA: - case 0x2CB: - case 0x2CC: - case 0x2CD: - case 0x2CE: - case 0x2CF: - case 0x2D0: - case 0x2D1: - case 0x2D2: - case 0x2D3: - case 0x2D4: - case 0x2D5: - case 0x2D6: - case 0x2D7: - case 0x2D8: - case 0x2D9: - case 0x2DA: - case 0x2DB: - case 0x2DC: - case 0x2DD: - case 0x2DE: - case 0x2DF: - case 0x2E0: - case 0x2E1: - case 0x2E2: - case 0x2E3: - case 0x2E4: - case 0x2E5: - case 0x2E6: - case 0x2E7: - case 0x2E8: - case 0x2E9: - case 0x2EA: - case 0x2EB: - case 0x2EC: - case 0x2ED: - case 0x2EE: - case 0x2EF: - case 0x2F0: - case 0x2F1: - case 0x2F2: - case 0x2F3: - case 0x2F4: - case 0x2F5: - case 0x2F6: - case 0x2F7: - case 0x2F8: - case 0x2F9: - case 0x2FA: - case 0x2FB: - case 0x2FC: - case 0x2FD: - case 0x2FE: - case 0x2FF: - mem = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - mem_read = Indirect_Get(mem); - Indirect_Get_Cycles(mem); - dest_value = Register[dest]; - result = dest_value + mem_read; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, mem_read); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - Interruptible = true; - break; - // SUB - case 0x300: - case 0x301: - case 0x302: - case 0x303: - case 0x304: - case 0x305: - case 0x306: - case 0x307: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - addr = ReadMemory(RegisterPC++); - dest_value = Register[dest]; - addr_read = ReadMemory(addr); - result = dest_value - addr_read; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, -addr_read); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - PendingCycles -= 10; TotalExecutedCycles += 10; - Interruptible = true; - break; - // SUB@ - case 0x308: - case 0x309: - case 0x30A: - case 0x30B: - case 0x30C: - case 0x30D: - case 0x30E: - case 0x30F: - case 0x310: - case 0x311: - case 0x312: - case 0x313: - case 0x314: - case 0x315: - case 0x316: - case 0x317: - case 0x318: - case 0x319: - case 0x31A: - case 0x31B: - case 0x31C: - case 0x31D: - case 0x31E: - case 0x31F: - case 0x320: - case 0x321: - case 0x322: - case 0x323: - case 0x324: - case 0x325: - case 0x326: - case 0x327: - case 0x328: - case 0x329: - case 0x32A: - case 0x32B: - case 0x32C: - case 0x32D: - case 0x32E: - case 0x32F: - case 0x330: - case 0x331: - case 0x332: - case 0x333: - case 0x334: - case 0x335: - case 0x336: - case 0x337: - case 0x338: - case 0x339: - case 0x33A: - case 0x33B: - case 0x33C: - case 0x33D: - case 0x33E: - case 0x33F: - throw new NotImplementedException(); - mem = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - mem_read = Indirect_Get(mem); - Indirect_Get_Cycles(mem); - dest_value = Register[dest]; - result = dest_value - mem_read; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, -mem_read); - Calc_FlagS(result); - Calc_FlagZ(result); - result &= 0xFFFF; - Register[dest] = (ushort)result; - Interruptible = true; - break; - // CMP - case 0x340: - case 0x341: - case 0x342: - case 0x343: - case 0x344: - case 0x345: - case 0x346: - case 0x347: - dest = (byte)(opcode & 0x7); - addr = ReadMemory(RegisterPC++); - dest_value = Register[dest]; - addr_read = ReadMemory(addr); - result = dest_value - addr_read; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, -addr_read); - Calc_FlagS(result); - Calc_FlagZ(result); - PendingCycles -= 10; TotalExecutedCycles += 10; - Interruptible = true; - break; - // CMP@ - case 0x348: - case 0x349: - case 0x34A: - case 0x34B: - case 0x34C: - case 0x34D: - case 0x34E: - case 0x34F: - case 0x350: - case 0x351: - case 0x352: - case 0x353: - case 0x354: - case 0x355: - case 0x356: - case 0x357: - case 0x358: - case 0x359: - case 0x35A: - case 0x35B: - case 0x35C: - case 0x35D: - case 0x35E: - case 0x35F: - case 0x360: - case 0x361: - case 0x362: - case 0x363: - case 0x364: - case 0x365: - case 0x366: - case 0x367: - case 0x368: - case 0x369: - case 0x36A: - case 0x36B: - case 0x36C: - case 0x36D: - case 0x36E: - case 0x36F: - case 0x370: - case 0x371: - case 0x372: - case 0x373: - case 0x374: - case 0x375: - case 0x376: - case 0x377: - case 0x378: - case 0x379: - case 0x37A: - case 0x37B: - case 0x37C: - case 0x37D: - case 0x37E: - case 0x37F: - throw new NotImplementedException(); - mem = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - mem_read = Indirect_Get(mem); - Indirect_Get_Cycles(mem); - dest_value = Register[dest]; - result = dest_value - mem_read; - Calc_FlagC(result); - Calc_FlagO_Add(dest_value, -mem_read); - Calc_FlagS(result); - Calc_FlagZ(result); - Interruptible = true; - break; - // AND - case 0x380: - case 0x381: - case 0x382: - case 0x383: - case 0x384: - case 0x385: - case 0x386: - case 0x387: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - addr = ReadMemory(RegisterPC++); - dest_value = Register[dest]; - addr_read = ReadMemory(addr); - result = dest_value & addr_read; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - PendingCycles -= 10; TotalExecutedCycles += 10; - Interruptible = true; - break; - // AND@ - case 0x388: - case 0x389: - case 0x38A: - case 0x38B: - case 0x38C: - case 0x38D: - case 0x38E: - case 0x38F: - case 0x390: - case 0x391: - case 0x392: - case 0x393: - case 0x394: - case 0x395: - case 0x396: - case 0x397: - case 0x398: - case 0x399: - case 0x39A: - case 0x39B: - case 0x39C: - case 0x39D: - case 0x39E: - case 0x39F: - case 0x3A0: - case 0x3A1: - case 0x3A2: - case 0x3A3: - case 0x3A4: - case 0x3A5: - case 0x3A6: - case 0x3A7: - case 0x3A8: - case 0x3A9: - case 0x3AA: - case 0x3AB: - case 0x3AC: - case 0x3AD: - case 0x3AE: - case 0x3AF: - case 0x3B0: - case 0x3B1: - case 0x3B2: - case 0x3B3: - case 0x3B4: - case 0x3B5: - case 0x3B6: - case 0x3B7: - case 0x3B8: - case 0x3B9: - case 0x3BA: - case 0x3BB: - case 0x3BC: - case 0x3BD: - case 0x3BE: - case 0x3BF: - mem = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - mem_read = Indirect_Get(mem); - Indirect_Get_Cycles(mem); - result = Register[dest] & mem_read; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = true; - break; - // XOR - case 0x3C0: - case 0x3C1: - case 0x3C2: - case 0x3C3: - case 0x3C4: - case 0x3C5: - case 0x3C6: - case 0x3C7: - throw new NotImplementedException(); - dest = (byte)(opcode & 0x7); - addr = ReadMemory(RegisterPC++); - dest_value = Register[dest]; - addr_read = ReadMemory(addr); - result = dest_value ^ addr_read; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - PendingCycles -= 10; TotalExecutedCycles += 10; - Interruptible = true; - break; - // XOR@ - case 0x3C8: - case 0x3C9: - case 0x3CA: - case 0x3CB: - case 0x3CC: - case 0x3CD: - case 0x3CE: - case 0x3CF: - case 0x3D0: - case 0x3D1: - case 0x3D2: - case 0x3D3: - case 0x3D4: - case 0x3D5: - case 0x3D6: - case 0x3D7: - case 0x3D8: - case 0x3D9: - case 0x3DA: - case 0x3DB: - case 0x3DC: - case 0x3DD: - case 0x3DE: - case 0x3DF: - case 0x3E0: - case 0x3E1: - case 0x3E2: - case 0x3E3: - case 0x3E4: - case 0x3E5: - case 0x3E6: - case 0x3E7: - case 0x3E8: - case 0x3E9: - case 0x3EA: - case 0x3EB: - case 0x3EC: - case 0x3ED: - case 0x3EE: - case 0x3EF: - case 0x3F0: - case 0x3F1: - case 0x3F2: - case 0x3F3: - case 0x3F4: - case 0x3F5: - case 0x3F6: - case 0x3F7: - case 0x3F8: - case 0x3F9: - case 0x3FA: - case 0x3FB: - case 0x3FC: - case 0x3FD: - case 0x3FE: - case 0x3FF: - throw new NotImplementedException(); - mem = (byte)((opcode >> 3) & 0x7); - dest = (byte)(opcode & 0x7); - mem_read = Indirect_Get(mem); - Indirect_Get_Cycles(mem); - result = Register[dest] ^ mem_read; - Calc_FlagS(result); - Calc_FlagZ(result); - Register[dest] = (ushort)result; - Interruptible = true; - break; - } - if (FlagD == prev_FlagD) - FlagD = false; - LogData(); + int addrToAdvance; + log.WriteLine("------"); + log.WriteLine(); + log.WriteLine(Disassemble(RegisterPC, out addrToAdvance)); + log.Flush(); } + if (FlagI && Interruptible && !IntRM) + { + Indirect_Set(6, 7); + RegisterPC = INTERRUPT; + } + byte dest, src, mem; + ushort dest_value, src_value, mem_read, addr, addr_read, offset; + int cycles = 0, decle2, decle3, result = 0, ones, carry, status_word, lower, sign, cond, ext; + bool branch = false; + bool prev_FlagD = FlagD; + int opcode = ReadMemory(RegisterPC++) & 0x3FF; + switch (opcode) + { + case 0x000: // HLT + throw new ArgumentException(UNEXPECTED_HLT); + case 0x001: // SDBD + FlagD = true; + cycles = 4; + Interruptible = false; + break; + case 0x002: // EIS + FlagI = true; + cycles = 4; + Interruptible = false; + break; + case 0x003: // DIS + FlagI = false; + cycles = 4; + Interruptible = false; + break; + case 0x004: // J, JE, JD, JSR, JSRE, JSRD + // 0000:0000:0000:0100 0000:00rr:aaaa:aaff 0000:00aa:aaaa:aaaa + decle2 = ReadMemory(RegisterPC++); + decle3 = ReadMemory(RegisterPC++); + // rr indicates the register into which to store the return address + dest = (byte)(((decle2 >> 8) & 0x3) + 4); + // aaaaaaaaaaaaaaaa indicates the address to where the CP1610 should Jump + addr = (ushort)(((decle2 << 8) & 0xFC00) | (decle3 & 0x3FF)); + if (dest != 0x7) + // Store the return address. + Register[dest] = (ushort)(RegisterPC & 0xFFFF); + // ff indicates how to affect the Interrupt (I) flag in the CP1610 + switch (decle2 & 0x3) + { + case 0x1: + FlagI = true; + break; + case 0x2: + FlagI = false; + break; + case 0x3: + // Unknown opcode. + throw new ArgumentException(); + } + RegisterPC = (ushort)addr; + cycles = 12; + Interruptible = true; + break; + case 0x005: // TCI + throw new ArgumentException(UNEXPECTED_TCI); + case 0x006: // CLRC + FlagC = false; + cycles = 4; + Interruptible = false; + break; + case 0x007: // SETC + FlagC = true; + cycles = 4; + Interruptible = false; + break; + // INCR + case 0x008: + case 0x009: + case 0x00A: + case 0x00B: + case 0x00C: + case 0x00D: + case 0x00E: + case 0x00F: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + result = (Register[dest] + 1) & 0xFFFF; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // DECR + case 0x010: + case 0x011: + case 0x012: + case 0x013: + case 0x014: + case 0x015: + case 0x016: + case 0x017: + dest = (byte)(opcode & 0x7); + result = (Register[dest] - 1) & 0xFFFF; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // COMR + case 0x018: + case 0x019: + case 0x01A: + case 0x01B: + case 0x01C: + case 0x01D: + case 0x01E: + case 0x01F: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + result = (Register[dest] ^ 0xFFFF); + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // NEGR + case 0x020: + case 0x021: + case 0x022: + case 0x023: + case 0x024: + case 0x025: + case 0x026: + case 0x027: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + dest_value = Register[dest]; + ones = (dest_value ^ 0xFFFF); + result = ones + 1; + Calc_FlagC(result); + Calc_FlagO_Add(ones, 1); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // ADCR + case 0x028: + case 0x029: + case 0x02A: + case 0x02B: + case 0x02C: + case 0x02D: + case 0x02E: + case 0x02F: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + dest_value = Register[dest]; + carry = FlagC ? 1 : 0; + result = dest_value + carry; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, carry); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // GSWD + case 0x030: + case 0x031: + case 0x032: + case 0x033: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + status_word = ((FlagS ? 1 : 0) << 3) | ((FlagZ ? 1 : 0) << 2) | ((FlagO ? 1 : 0) << 1) | + (FlagC ? 1 : 0); + Register[dest] = (ushort)((status_word << 12) | (status_word << 4)); + cycles = 6; + Interruptible = true; + break; + // NOP + case 0x034: + case 0x035: + cycles = 6; + Interruptible = true; + break; + // SIN + case 0x036: + case 0x037: + throw new ArgumentException(UNEXPECTED_SIN); + // RSWD + case 0x038: + case 0x039: + case 0x03A: + case 0x03B: + case 0x03C: + case 0x03D: + case 0x03E: + case 0x03F: + throw new NotImplementedException(); + src = (byte)(opcode & 0x7); + src_value = Register[src]; + FlagC = ((src_value & 0x80) != 0) ? true : false; + FlagO = ((src_value & 0x40) != 0) ? true : false; + FlagZ = ((src_value & 0x20) != 0) ? true : false; + FlagS = ((src_value & 0x10) != 0) ? true : false; + cycles = 6; + Interruptible = true; + break; + // SWAP + case 0x040: + case 0x041: + case 0x042: + case 0x043: + case 0x044: + case 0x045: + case 0x046: + case 0x047: + dest = (byte)(opcode & 0x3); + dest_value = Register[dest]; + lower = dest_value & 0xFF; + if (((opcode >> 3) & 0x1) == 0) + { + // Single swap. + result = (lower << 8) | ((dest_value >> 8) & 0xFF); + cycles = 6; + } + else + { + // Double swap. + result = (lower << 8) | lower; + cycles = 8; + } + Calc_FlagS_7(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // SLL + case 0x048: + case 0x049: + case 0x04A: + case 0x04B: + case 0x04C: + case 0x04D: + case 0x04E: + case 0x04F: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + result = Register[dest] << 1; + if (((opcode >> 3) & 0x1) == 0) + // Single shift. + cycles = 6; + else + { + // Double shift. + result <<= 1; + cycles = 8; + } + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // RLC + case 0x050: + case 0x051: + case 0x052: + case 0x053: + case 0x054: + case 0x055: + case 0x056: + case 0x057: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + dest_value = Register[dest]; + result = (dest_value << 1) | (FlagC ? 1 : 0); + FlagC = ((dest_value & 0x8000) != 0); + if (((opcode >> 3) & 0x1) == 0) + // Single rotate. + cycles = 6; + else + { + // Double rotate. + result <<= 1; + result |= (FlagO ? 1 : 0); + FlagO = ((dest_value & 0x4000) != 0); + cycles = 8; + } + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // SLLC + case 0x058: + case 0x059: + case 0x05A: + case 0x05B: + case 0x05C: + case 0x05D: + case 0x05E: + case 0x05F: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + dest_value = Register[dest]; + result = dest_value << 1; + FlagC = ((dest_value & 0x8000) != 0); + if (((opcode >> 3) & 0x1) == 0) + // Single shift. + cycles = 6; + else + { + // Double shift. + result <<= 1; + FlagO = ((dest_value & 0x4000) != 0); + cycles = 8; + } + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // SLR + case 0x060: + case 0x061: + case 0x062: + case 0x063: + case 0x064: + case 0x065: + case 0x066: + case 0x067: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + result = Register[dest] >> 1; + if (((opcode >> 3) & 0x1) == 0) + // Single shift. + cycles = 6; + else + { + // Double shift. + result >>= 1; + cycles = 8; + } + Calc_FlagS_7(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // SAR + case 0x068: + case 0x069: + case 0x06A: + case 0x06B: + case 0x06C: + case 0x06D: + case 0x06E: + case 0x06F: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + dest_value = Register[dest]; + sign = dest_value & 0x8000; + result = (dest_value >> 1) | sign; + if (((opcode >> 3) & 0x1) == 0) + // Single shift. + cycles = 6; + else + { + // Double shift. + result >>= 1; + result |= sign; + cycles = 8; + } + Calc_FlagS_7(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // RRC + case 0x070: + case 0x071: + case 0x072: + case 0x073: + case 0x074: + case 0x075: + case 0x076: + case 0x077: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + dest_value = Register[dest]; + result = (dest_value >> 1) | ((FlagC ? 1 : 0) << 15); + FlagC = ((dest_value & 0x1) != 0); + if (((opcode >> 3) & 0x1) == 0) + // Single rotate. + cycles = 6; + else + { + // Double rotate. + result >>= 1; + result |= (FlagO ? 1 : 0) << 15; + FlagO = ((dest_value & 0x2) != 0); + cycles = 8; + } + Calc_FlagS_7(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // SARC + case 0x078: + case 0x079: + case 0x07A: + case 0x07B: + case 0x07C: + case 0x07D: + case 0x07E: + case 0x07F: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x3); + dest_value = Register[dest]; + sign = dest_value & 0x8000; + result = (dest_value >> 1) | sign; + FlagC = ((dest_value & 0x1) != 0); + if (((opcode >> 3) & 0x1) == 0) + // Single shift. + cycles = 6; + else + { + // Double shift. + result >>= 1; + result |= sign; + FlagO = ((dest_value & 0x2) != 0); + cycles = 8; + } + Calc_FlagS_7(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = false; + break; + // MOVR + case 0x080: + case 0x081: + case 0x082: + case 0x083: + case 0x084: + case 0x085: + case 0x086: + case 0x087: + case 0x088: + case 0x089: + case 0x08A: + case 0x08B: + case 0x08C: + case 0x08D: + case 0x08E: + case 0x08F: + case 0x090: + case 0x091: + case 0x092: + case 0x093: + case 0x094: + case 0x095: + case 0x096: + case 0x097: + case 0x098: + case 0x099: + case 0x09A: + case 0x09B: + case 0x09C: + case 0x09D: + case 0x09E: + case 0x09F: + case 0x0A0: + case 0x0A1: + case 0x0A2: + case 0x0A3: + case 0x0A4: + case 0x0A5: + case 0x0A6: + case 0x0A7: + case 0x0A8: + case 0x0A9: + case 0x0AA: + case 0x0AB: + case 0x0AC: + case 0x0AD: + case 0x0AE: + case 0x0AF: + case 0x0B0: + case 0x0B1: + case 0x0B2: + case 0x0B3: + case 0x0B4: + case 0x0B5: + case 0x0B6: + case 0x0B7: + case 0x0B8: + case 0x0B9: + case 0x0BA: + case 0x0BB: + case 0x0BC: + case 0x0BD: + case 0x0BE: + case 0x0BF: + src = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + result = Register[src]; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + if (dest == 0x6 || dest == 0x7) + cycles = 7; + else + cycles = 6; + Interruptible = true; + break; + // ADDR + case 0x0C0: + case 0x0C1: + case 0x0C2: + case 0x0C3: + case 0x0C4: + case 0x0C5: + case 0x0C6: + case 0x0C7: + case 0x0C8: + case 0x0C9: + case 0x0CA: + case 0x0CB: + case 0x0CC: + case 0x0CD: + case 0x0CE: + case 0x0CF: + case 0x0D0: + case 0x0D1: + case 0x0D2: + case 0x0D3: + case 0x0D4: + case 0x0D5: + case 0x0D6: + case 0x0D7: + case 0x0D8: + case 0x0D9: + case 0x0DA: + case 0x0DB: + case 0x0DC: + case 0x0DD: + case 0x0DE: + case 0x0DF: + case 0x0E0: + case 0x0E1: + case 0x0E2: + case 0x0E3: + case 0x0E4: + case 0x0E5: + case 0x0E6: + case 0x0E7: + case 0x0E8: + case 0x0E9: + case 0x0EA: + case 0x0EB: + case 0x0EC: + case 0x0ED: + case 0x0EE: + case 0x0EF: + case 0x0F0: + case 0x0F1: + case 0x0F2: + case 0x0F3: + case 0x0F4: + case 0x0F5: + case 0x0F6: + case 0x0F7: + case 0x0F8: + case 0x0F9: + case 0x0FA: + case 0x0FB: + case 0x0FC: + case 0x0FD: + case 0x0FE: + case 0x0FF: + throw new NotImplementedException(); + src = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + src_value = Register[src]; + dest_value = Register[dest]; + result = dest_value + src_value; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, src_value); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // SUBR + case 0x100: + case 0x101: + case 0x102: + case 0x103: + case 0x104: + case 0x105: + case 0x106: + case 0x107: + case 0x108: + case 0x109: + case 0x10A: + case 0x10B: + case 0x10C: + case 0x10D: + case 0x10E: + case 0x10F: + case 0x110: + case 0x111: + case 0x112: + case 0x113: + case 0x114: + case 0x115: + case 0x116: + case 0x117: + case 0x118: + case 0x119: + case 0x11A: + case 0x11B: + case 0x11C: + case 0x11D: + case 0x11E: + case 0x11F: + case 0x120: + case 0x121: + case 0x122: + case 0x123: + case 0x124: + case 0x125: + case 0x126: + case 0x127: + case 0x128: + case 0x129: + case 0x12A: + case 0x12B: + case 0x12C: + case 0x12D: + case 0x12E: + case 0x12F: + case 0x130: + case 0x131: + case 0x132: + case 0x133: + case 0x134: + case 0x135: + case 0x136: + case 0x137: + case 0x138: + case 0x139: + case 0x13A: + case 0x13B: + case 0x13C: + case 0x13D: + case 0x13E: + case 0x13F: + throw new NotImplementedException(); + src = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + src_value = Register[src]; + dest_value = Register[dest]; + result = Register[dest] - Register[src]; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, -src_value); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // CMPR + case 0x140: + case 0x141: + case 0x142: + case 0x143: + case 0x144: + case 0x145: + case 0x146: + case 0x147: + case 0x148: + case 0x149: + case 0x14A: + case 0x14B: + case 0x14C: + case 0x14D: + case 0x14E: + case 0x14F: + case 0x150: + case 0x151: + case 0x152: + case 0x153: + case 0x154: + case 0x155: + case 0x156: + case 0x157: + case 0x158: + case 0x159: + case 0x15A: + case 0x15B: + case 0x15C: + case 0x15D: + case 0x15E: + case 0x15F: + case 0x160: + case 0x161: + case 0x162: + case 0x163: + case 0x164: + case 0x165: + case 0x166: + case 0x167: + case 0x168: + case 0x169: + case 0x16A: + case 0x16B: + case 0x16C: + case 0x16D: + case 0x16E: + case 0x16F: + case 0x170: + case 0x171: + case 0x172: + case 0x173: + case 0x174: + case 0x175: + case 0x176: + case 0x177: + case 0x178: + case 0x179: + case 0x17A: + case 0x17B: + case 0x17C: + case 0x17D: + case 0x17E: + case 0x17F: + throw new NotImplementedException(); + src = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + src_value = Register[src]; + dest_value = Register[dest]; + result = dest_value - src_value; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, -src_value); + Calc_FlagS(result); + Calc_FlagZ(result); + cycles = 6; + Interruptible = true; + break; + // ANDR + case 0x180: + case 0x181: + case 0x182: + case 0x183: + case 0x184: + case 0x185: + case 0x186: + case 0x187: + case 0x188: + case 0x189: + case 0x18A: + case 0x18B: + case 0x18C: + case 0x18D: + case 0x18E: + case 0x18F: + case 0x190: + case 0x191: + case 0x192: + case 0x193: + case 0x194: + case 0x195: + case 0x196: + case 0x197: + case 0x198: + case 0x199: + case 0x19A: + case 0x19B: + case 0x19C: + case 0x19D: + case 0x19E: + case 0x19F: + case 0x1A0: + case 0x1A1: + case 0x1A2: + case 0x1A3: + case 0x1A4: + case 0x1A5: + case 0x1A6: + case 0x1A7: + case 0x1A8: + case 0x1A9: + case 0x1AA: + case 0x1AB: + case 0x1AC: + case 0x1AD: + case 0x1AE: + case 0x1AF: + case 0x1B0: + case 0x1B1: + case 0x1B2: + case 0x1B3: + case 0x1B4: + case 0x1B5: + case 0x1B6: + case 0x1B7: + case 0x1B8: + case 0x1B9: + case 0x1BA: + case 0x1BB: + case 0x1BC: + case 0x1BD: + case 0x1BE: + case 0x1BF: + throw new NotImplementedException(); + src = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + result = Register[dest] & Register[src]; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // XORR + case 0x1C0: + case 0x1C1: + case 0x1C2: + case 0x1C3: + case 0x1C4: + case 0x1C5: + case 0x1C6: + case 0x1C7: + case 0x1C8: + case 0x1C9: + case 0x1CA: + case 0x1CB: + case 0x1CC: + case 0x1CD: + case 0x1CE: + case 0x1CF: + case 0x1D0: + case 0x1D1: + case 0x1D2: + case 0x1D3: + case 0x1D4: + case 0x1D5: + case 0x1D6: + case 0x1D7: + case 0x1D8: + case 0x1D9: + case 0x1DA: + case 0x1DB: + case 0x1DC: + case 0x1DD: + case 0x1DE: + case 0x1DF: + case 0x1E0: + case 0x1E1: + case 0x1E2: + case 0x1E3: + case 0x1E4: + case 0x1E5: + case 0x1E6: + case 0x1E7: + case 0x1E8: + case 0x1E9: + case 0x1EA: + case 0x1EB: + case 0x1EC: + case 0x1ED: + case 0x1EE: + case 0x1EF: + case 0x1F0: + case 0x1F1: + case 0x1F2: + case 0x1F3: + case 0x1F4: + case 0x1F5: + case 0x1F6: + case 0x1F7: + case 0x1F8: + case 0x1F9: + case 0x1FA: + case 0x1FB: + case 0x1FC: + case 0x1FD: + case 0x1FE: + case 0x1FF: + src = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + result = Register[dest] ^ Register[src]; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + cycles = 6; + Interruptible = true; + break; + // Branch Forward, no External Condition + case 0x200: // B + case 0x201: // BC + case 0x202: // BOV + case 0x203: // BPL + case 0x204: // BEQ + case 0x205: // BLT + case 0x206: // BLE + case 0x207: // BUSC + case 0x208: // NOPP + case 0x209: // BNC + case 0x20A: // BNOV + case 0x20B: // BMI + case 0x20C: // BNEQ + case 0x20D: // BGE + case 0x20E: // BGT + case 0x20F: // BESC + // Branch Forward, Exteranl Condition (BEXT) + case 0x210: + case 0x211: + case 0x212: + case 0x213: + case 0x214: + case 0x215: + case 0x216: + case 0x217: + case 0x218: + case 0x219: + case 0x21A: + case 0x21B: + case 0x21C: + case 0x21D: + case 0x21E: + case 0x21F: + // Branch Reverse, no External Condition + case 0x220: // B + case 0x221: // BC + case 0x222: // BOV + case 0x223: // BPL + case 0x224: // BEQ + case 0x225: // BLT + case 0x226: // BLE + case 0x227: // BUSC + case 0x228: // NOPP + case 0x229: // BNC + case 0x22A: // BNOV + case 0x22B: // BMI + case 0x22C: // BNEQ + case 0x22D: // BGE + case 0x22E: // BGT + case 0x22F: // BESC + // Branch Reverse, Exteranl Condition (BEXT) + case 0x230: + case 0x231: + case 0x232: + case 0x233: + case 0x234: + case 0x235: + case 0x236: + case 0x237: + case 0x238: + case 0x239: + case 0x23A: + case 0x23B: + case 0x23C: + case 0x23D: + case 0x23E: + case 0x23F: + offset = ReadMemory(RegisterPC++); + cond = opcode & 0xF; + ext = opcode & 0x10; + // BEXT + if (ext != 0) + throw new ArgumentException(UNEXPECTED_BEXT); + else + { + switch (cond) + { + // B + case 0x0: + branch = true; + break; + // BC + case 0x1: + branch = FlagC; + break; + // BOV + case 0x2: + branch = FlagO; + break; + // BPL + case 0x3: + branch = !FlagS; + break; + // BEQ + case 0x4: + branch = FlagZ; + break; + // BLT + case 0x5: + branch = (FlagS != FlagO); + break; + // BLE + case 0x6: + branch = (FlagZ || FlagS != FlagO); + break; + // BUSC + case 0x7: + branch = (FlagC != FlagS); + break; + // NOPP + case 0x8: + branch = false; + break; + // BNC + case 0x9: + branch = !FlagC; + break; + // BNOV + case 0xA: + branch = !FlagO; + break; + // BMI + case 0xB: + branch = FlagS; + break; + // BNEQ + case 0xC: + branch = !FlagZ; + break; + // BGE + case 0xD: + branch = (FlagS == FlagO); + break; + // BGT + case 0xE: + branch = (!FlagZ && FlagS == FlagO); + break; + // BESC + case 0xF: + branch = (FlagC == FlagS); + break; + } + } + if (branch) + { + // Branch in the reverse direction by negating the offset and subtracting 1. + if (((opcode >> 5) & 0x1) != 0) + offset = (ushort)(-offset - 1); + RegisterPC += offset; + cycles = 9; + } + else + cycles = 7; + Interruptible = true; + break; + // MVO + case 0x240: + case 0x241: + case 0x242: + case 0x243: + case 0x244: + case 0x245: + case 0x246: + case 0x247: + src = (byte)(opcode & 0x7); + addr = ReadMemory(RegisterPC++); + WriteMemory(addr, Register[src]); + cycles = 11; + Interruptible = false; + break; + // MVO@ + case 0x248: + case 0x249: + case 0x24A: + case 0x24B: + case 0x24C: + case 0x24D: + case 0x24E: + case 0x24F: + case 0x250: + case 0x251: + case 0x252: + case 0x253: + case 0x254: + case 0x255: + case 0x256: + case 0x257: + case 0x258: + case 0x259: + case 0x25A: + case 0x25B: + case 0x25C: + case 0x25D: + case 0x25E: + case 0x25F: + case 0x260: + case 0x261: + case 0x262: + case 0x263: + case 0x264: + case 0x265: + case 0x266: + case 0x267: + case 0x268: + case 0x269: + case 0x26A: + case 0x26B: + case 0x26C: + case 0x26D: + case 0x26E: + case 0x26F: + case 0x270: + case 0x271: + case 0x272: + case 0x273: + case 0x274: + case 0x275: + case 0x276: + case 0x277: + case 0x278: + case 0x279: + case 0x27A: + case 0x27B: + case 0x27C: + case 0x27D: + case 0x27E: + case 0x27F: + mem = (byte)((opcode >> 3) & 0x7); + src = (byte)(opcode & 0x7); + Indirect_Set(mem, src); + cycles = 9; + Interruptible = false; + break; + // MVI + case 0x280: + case 0x281: + case 0x282: + case 0x283: + case 0x284: + case 0x285: + case 0x286: + case 0x287: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + addr = ReadMemory(RegisterPC++); + Register[dest] = ReadMemory(addr); + cycles = 10; + Interruptible = true; + break; + // MVI@ + case 0x288: + case 0x289: + case 0x28A: + case 0x28B: + case 0x28C: + case 0x28D: + case 0x28E: + case 0x28F: + case 0x290: + case 0x291: + case 0x292: + case 0x293: + case 0x294: + case 0x295: + case 0x296: + case 0x297: + case 0x298: + case 0x299: + case 0x29A: + case 0x29B: + case 0x29C: + case 0x29D: + case 0x29E: + case 0x29F: + case 0x2A0: + case 0x2A1: + case 0x2A2: + case 0x2A3: + case 0x2A4: + case 0x2A5: + case 0x2A6: + case 0x2A7: + case 0x2A8: + case 0x2A9: + case 0x2AA: + case 0x2AB: + case 0x2AC: + case 0x2AD: + case 0x2AE: + case 0x2AF: + case 0x2B0: + case 0x2B1: + case 0x2B2: + case 0x2B3: + case 0x2B4: + case 0x2B5: + case 0x2B6: + case 0x2B7: + case 0x2B8: + case 0x2B9: + case 0x2BA: + case 0x2BB: + case 0x2BC: + case 0x2BD: + case 0x2BE: + case 0x2BF: + mem = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + Register[dest] = Indirect_Get(mem); + cycles = Indirect_Get_Cycles(mem); + Interruptible = true; + break; + // ADD + case 0x2C0: + case 0x2C1: + case 0x2C2: + case 0x2C3: + case 0x2C4: + case 0x2C5: + case 0x2C6: + case 0x2C7: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + addr = ReadMemory(RegisterPC++); + dest_value = Register[dest]; + addr_read = ReadMemory(addr); + result = dest_value + addr_read; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, addr_read); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + cycles = 10; + Interruptible = true; + break; + // ADD@ + case 0x2C8: + case 0x2C9: + case 0x2CA: + case 0x2CB: + case 0x2CC: + case 0x2CD: + case 0x2CE: + case 0x2CF: + case 0x2D0: + case 0x2D1: + case 0x2D2: + case 0x2D3: + case 0x2D4: + case 0x2D5: + case 0x2D6: + case 0x2D7: + case 0x2D8: + case 0x2D9: + case 0x2DA: + case 0x2DB: + case 0x2DC: + case 0x2DD: + case 0x2DE: + case 0x2DF: + case 0x2E0: + case 0x2E1: + case 0x2E2: + case 0x2E3: + case 0x2E4: + case 0x2E5: + case 0x2E6: + case 0x2E7: + case 0x2E8: + case 0x2E9: + case 0x2EA: + case 0x2EB: + case 0x2EC: + case 0x2ED: + case 0x2EE: + case 0x2EF: + case 0x2F0: + case 0x2F1: + case 0x2F2: + case 0x2F3: + case 0x2F4: + case 0x2F5: + case 0x2F6: + case 0x2F7: + case 0x2F8: + case 0x2F9: + case 0x2FA: + case 0x2FB: + case 0x2FC: + case 0x2FD: + case 0x2FE: + case 0x2FF: + mem = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + mem_read = Indirect_Get(mem); + cycles = Indirect_Get_Cycles(mem); + dest_value = Register[dest]; + result = dest_value + mem_read; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, mem_read); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + Interruptible = true; + break; + // SUB + case 0x300: + case 0x301: + case 0x302: + case 0x303: + case 0x304: + case 0x305: + case 0x306: + case 0x307: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + addr = ReadMemory(RegisterPC++); + dest_value = Register[dest]; + addr_read = ReadMemory(addr); + result = dest_value - addr_read; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, -addr_read); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + cycles = 10; + Interruptible = true; + break; + // SUB@ + case 0x308: + case 0x309: + case 0x30A: + case 0x30B: + case 0x30C: + case 0x30D: + case 0x30E: + case 0x30F: + case 0x310: + case 0x311: + case 0x312: + case 0x313: + case 0x314: + case 0x315: + case 0x316: + case 0x317: + case 0x318: + case 0x319: + case 0x31A: + case 0x31B: + case 0x31C: + case 0x31D: + case 0x31E: + case 0x31F: + case 0x320: + case 0x321: + case 0x322: + case 0x323: + case 0x324: + case 0x325: + case 0x326: + case 0x327: + case 0x328: + case 0x329: + case 0x32A: + case 0x32B: + case 0x32C: + case 0x32D: + case 0x32E: + case 0x32F: + case 0x330: + case 0x331: + case 0x332: + case 0x333: + case 0x334: + case 0x335: + case 0x336: + case 0x337: + case 0x338: + case 0x339: + case 0x33A: + case 0x33B: + case 0x33C: + case 0x33D: + case 0x33E: + case 0x33F: + throw new NotImplementedException(); + mem = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + mem_read = Indirect_Get(mem); + cycles = Indirect_Get_Cycles(mem); + dest_value = Register[dest]; + result = dest_value - mem_read; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, -mem_read); + Calc_FlagS(result); + Calc_FlagZ(result); + result &= 0xFFFF; + Register[dest] = (ushort)result; + Interruptible = true; + break; + // CMP + case 0x340: + case 0x341: + case 0x342: + case 0x343: + case 0x344: + case 0x345: + case 0x346: + case 0x347: + dest = (byte)(opcode & 0x7); + addr = ReadMemory(RegisterPC++); + dest_value = Register[dest]; + addr_read = ReadMemory(addr); + result = dest_value - addr_read; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, -addr_read); + Calc_FlagS(result); + Calc_FlagZ(result); + cycles = 10; + Interruptible = true; + break; + // CMP@ + case 0x348: + case 0x349: + case 0x34A: + case 0x34B: + case 0x34C: + case 0x34D: + case 0x34E: + case 0x34F: + case 0x350: + case 0x351: + case 0x352: + case 0x353: + case 0x354: + case 0x355: + case 0x356: + case 0x357: + case 0x358: + case 0x359: + case 0x35A: + case 0x35B: + case 0x35C: + case 0x35D: + case 0x35E: + case 0x35F: + case 0x360: + case 0x361: + case 0x362: + case 0x363: + case 0x364: + case 0x365: + case 0x366: + case 0x367: + case 0x368: + case 0x369: + case 0x36A: + case 0x36B: + case 0x36C: + case 0x36D: + case 0x36E: + case 0x36F: + case 0x370: + case 0x371: + case 0x372: + case 0x373: + case 0x374: + case 0x375: + case 0x376: + case 0x377: + case 0x378: + case 0x379: + case 0x37A: + case 0x37B: + case 0x37C: + case 0x37D: + case 0x37E: + case 0x37F: + throw new NotImplementedException(); + mem = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + mem_read = Indirect_Get(mem); + cycles = Indirect_Get_Cycles(mem); + dest_value = Register[dest]; + result = dest_value - mem_read; + Calc_FlagC(result); + Calc_FlagO_Add(dest_value, -mem_read); + Calc_FlagS(result); + Calc_FlagZ(result); + Interruptible = true; + break; + // AND + case 0x380: + case 0x381: + case 0x382: + case 0x383: + case 0x384: + case 0x385: + case 0x386: + case 0x387: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + addr = ReadMemory(RegisterPC++); + dest_value = Register[dest]; + addr_read = ReadMemory(addr); + result = dest_value & addr_read; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + cycles = 10; + Interruptible = true; + break; + // AND@ + case 0x388: + case 0x389: + case 0x38A: + case 0x38B: + case 0x38C: + case 0x38D: + case 0x38E: + case 0x38F: + case 0x390: + case 0x391: + case 0x392: + case 0x393: + case 0x394: + case 0x395: + case 0x396: + case 0x397: + case 0x398: + case 0x399: + case 0x39A: + case 0x39B: + case 0x39C: + case 0x39D: + case 0x39E: + case 0x39F: + case 0x3A0: + case 0x3A1: + case 0x3A2: + case 0x3A3: + case 0x3A4: + case 0x3A5: + case 0x3A6: + case 0x3A7: + case 0x3A8: + case 0x3A9: + case 0x3AA: + case 0x3AB: + case 0x3AC: + case 0x3AD: + case 0x3AE: + case 0x3AF: + case 0x3B0: + case 0x3B1: + case 0x3B2: + case 0x3B3: + case 0x3B4: + case 0x3B5: + case 0x3B6: + case 0x3B7: + case 0x3B8: + case 0x3B9: + case 0x3BA: + case 0x3BB: + case 0x3BC: + case 0x3BD: + case 0x3BE: + case 0x3BF: + mem = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + mem_read = Indirect_Get(mem); + cycles = Indirect_Get_Cycles(mem); + result = Register[dest] & mem_read; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = true; + break; + // XOR + case 0x3C0: + case 0x3C1: + case 0x3C2: + case 0x3C3: + case 0x3C4: + case 0x3C5: + case 0x3C6: + case 0x3C7: + throw new NotImplementedException(); + dest = (byte)(opcode & 0x7); + addr = ReadMemory(RegisterPC++); + dest_value = Register[dest]; + addr_read = ReadMemory(addr); + result = dest_value ^ addr_read; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + cycles = 10; + Interruptible = true; + break; + // XOR@ + case 0x3C8: + case 0x3C9: + case 0x3CA: + case 0x3CB: + case 0x3CC: + case 0x3CD: + case 0x3CE: + case 0x3CF: + case 0x3D0: + case 0x3D1: + case 0x3D2: + case 0x3D3: + case 0x3D4: + case 0x3D5: + case 0x3D6: + case 0x3D7: + case 0x3D8: + case 0x3D9: + case 0x3DA: + case 0x3DB: + case 0x3DC: + case 0x3DD: + case 0x3DE: + case 0x3DF: + case 0x3E0: + case 0x3E1: + case 0x3E2: + case 0x3E3: + case 0x3E4: + case 0x3E5: + case 0x3E6: + case 0x3E7: + case 0x3E8: + case 0x3E9: + case 0x3EA: + case 0x3EB: + case 0x3EC: + case 0x3ED: + case 0x3EE: + case 0x3EF: + case 0x3F0: + case 0x3F1: + case 0x3F2: + case 0x3F3: + case 0x3F4: + case 0x3F5: + case 0x3F6: + case 0x3F7: + case 0x3F8: + case 0x3F9: + case 0x3FA: + case 0x3FB: + case 0x3FC: + case 0x3FD: + case 0x3FE: + case 0x3FF: + throw new NotImplementedException(); + mem = (byte)((opcode >> 3) & 0x7); + dest = (byte)(opcode & 0x7); + mem_read = Indirect_Get(mem); + cycles = Indirect_Get_Cycles(mem); + result = Register[dest] ^ mem_read; + Calc_FlagS(result); + Calc_FlagZ(result); + Register[dest] = (ushort)result; + Interruptible = true; + break; + } + if (FlagD == prev_FlagD) + FlagD = false; + PendingCycles -= cycles; TotalExecutedCycles += cycles; } } } diff --git a/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs b/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs index 9079778a83..cb98504f00 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/Intellivision.cs @@ -15,36 +15,11 @@ namespace BizHawk.Emulation.Consoles.Intellivision STIC Stic; PSG Psg; - private bool Sr1ToIntRM, Sr2ToBusRq, BusAkToSst; - - private bool GetSr1ToIntRM() + public void Connect() { - return Sr1ToIntRM; - } - - private bool GetSr2ToBusRq() - { - return Sr2ToBusRq; - } - - private bool GetBusAkToSst() - { - return BusAkToSst; - } - - private void SetSr1ToIntRM(bool value) - { - Sr1ToIntRM = value; - } - - private void SetSr2ToBusRq(bool value) - { - Sr2ToBusRq = value; - } - - private void SetBusAkToSst(bool value) - { - BusAkToSst = value; + Cpu.SetIntRM(Stic.GetSr1()); + Cpu.SetBusRq(Stic.GetSr2()); + Stic.SetSst(Cpu.GetBusAk()); } public void LoadExecutiveRom() @@ -87,22 +62,15 @@ namespace BizHawk.Emulation.Consoles.Intellivision Cpu = new CP1610(); Cpu.ReadMemory = ReadMemory; Cpu.WriteMemory = WriteMemory; - Cpu.GetIntRM = GetSr1ToIntRM; - Cpu.GetBusRq = GetSr2ToBusRq; - Cpu.GetBusAk = GetBusAkToSst; - Cpu.SetBusAk = SetBusAkToSst; Cpu.Reset(); Stic = new STIC(); - Stic.GetSr1 = GetSr1ToIntRM; - Stic.GetSr2 = GetSr2ToBusRq; - Stic.GetSst = GetBusAkToSst; - Stic.SetSr1 = SetSr1ToIntRM; - Stic.SetSr2 = SetSr2ToBusRq; Stic.Reset(); Psg = new PSG(); + Connect(); + CoreOutputComm = new CoreOutputComm(); Cpu.LogData(); @@ -110,7 +78,14 @@ namespace BizHawk.Emulation.Consoles.Intellivision public void FrameAdvance(bool render) { - Cpu.Execute(999); + Cpu.AddPendingCycles(999); + while (Cpu.GetPendingCycles() > 0) + { + Cpu.Execute(); + Stic.Execute(); + Connect(); + Cpu.LogData(); + } } diff --git a/BizHawk.Emulation/Consoles/Intellivision/STIC.cs b/BizHawk.Emulation/Consoles/Intellivision/STIC.cs index 463cd45f9f..1a08bed962 100644 --- a/BizHawk.Emulation/Consoles/Intellivision/STIC.cs +++ b/BizHawk.Emulation/Consoles/Intellivision/STIC.cs @@ -7,18 +7,8 @@ namespace BizHawk.Emulation.Consoles.Intellivision { public sealed class STIC { - private bool Fgbg = false; + private bool Sr1, Sr2, Sst, Fgbg = false; private ushort[] Register = new ushort[64]; - - public Func GetSr1; - public Func GetSr2; - public Func GetSst; - public Action SetSr1; - public Action SetSr2; - - private bool Sr1 { set { SetSr1(value); } } - private bool Sr2 { set { SetSr2(value); } } - private bool Sst { get { return GetSst(); } } public void Reset() { @@ -26,6 +16,21 @@ namespace BizHawk.Emulation.Consoles.Intellivision Sr2 = true; } + public bool GetSr1() + { + return Sr1; + } + + public bool GetSr2() + { + return Sr2; + } + + public void SetSst(bool value) + { + Sst = value; + } + public ushort? ReadSTIC(ushort addr) { switch (addr & 0xF000) @@ -120,5 +125,10 @@ namespace BizHawk.Emulation.Consoles.Intellivision } return false; } + + public void Execute() + { + Sr1 = false; + } } }