summaryrefslogtreecommitdiff
path: root/Chip/Q1CpuInstructions.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Chip/Q1CpuInstructions.cs')
-rw-r--r--Chip/Q1CpuInstructions.cs225
1 files changed, 225 insertions, 0 deletions
diff --git a/Chip/Q1CpuInstructions.cs b/Chip/Q1CpuInstructions.cs
new file mode 100644
index 0000000..8b79a1d
--- /dev/null
+++ b/Chip/Q1CpuInstructions.cs
@@ -0,0 +1,225 @@
+namespace Q1Emu.Chip;
+
+using System;
+using System.Collections.Generic;
+
+public partial class Q1Cpu
+{
+ public Dictionary<u8, (Action, Action<u8>, Action, Action<u8, u8>)> InstructionLookup;
+ private void LoadInstructionLookup()
+ {
+ this.InstructionLookup = new Dictionary<u8, (Action, Action<u8>, Action, Action<u8, u8>)>
+ {
+ { 0x00, (this.Instruction_NOP, this.Instruction_JMP, this.Instruction_HALT, this.Instruction_MOV) },
+ { 0x01, (this.Instruction_RET, this.Instruction_CALL, this.Instruction_SUS, this.Instruction_CMP) },
+ { 0x02, (this.Instruction_BR, this.Instruction_BZ, this.Instruction_BZ_LX, this.Instruction_LT) },
+ { 0x03, (this.Instruction_NOP, this.Instruction_NOP, this.Instruction_NOP, this.Instruction_GT) },
+
+ { 0x04, (this.Instruction_NOT_LX, this.Instruction_NOT, this.Instruction_NOP, this.Instruction_AND) },
+ { 0x05, (this.Instruction_INV_DX, this.Instruction_INV, this.Instruction_NOP, this.Instruction_OR) },
+ { 0x06, (this.Instruction_SHL_DX, this.Instruction_SHL, this.Instruction_NOP, this.Instruction_XOR) },
+ { 0x07, (this.Instruction_SHR_DX, this.Instruction_SHR, this.Instruction_NOP, this.Instruction_NOP) },
+
+ { 0x08, (this.Instruction_INC_AX, this.Instruction_INC, this.Instruction_NOP, this.Instruction_ADD) },
+ { 0x09, (this.Instruction_DEC_AX, this.Instruction_DEC, this.Instruction_NOP, this.Instruction_SUB) },
+ { 0x0A, (this.Instruction_NOP, this.Instruction_NOP, this.Instruction_NOP, this.Instruction_DIV) },
+ { 0x0B, (this.Instruction_NOP, this.Instruction_NOP, this.Instruction_NOP, this.Instruction_MUL) },
+ { 0x0C, (this.Instruction_NOP, this.Instruction_NOP, this.Instruction_NOP, this.Instruction_MOD) },
+ };
+ }
+ private void Instruction_ADD(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ u16 result = (u16) (v1 + v2);
+ this.AX = result;
+ }
+ private void Instruction_SUB(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ u16 result = (u16)(v1 - v2);
+ this.AX = result;
+ }
+ private void Instruction_MUL(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ u16 result = (u16) (v1 * v2);
+ this.AX = result;
+ }
+ private void Instruction_DIV(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ if (v2 == 0)
+ throw new DivideByZeroException("Cannot perform division by zero.");
+ u16 result = (u16)(v1 / v2);
+ this.AX = result;
+ }
+ private void Instruction_MOD(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ if (v2 == 0)
+ throw new DivideByZeroException("Cannot perform modulo operation with divisor zero.");
+ u16 result = (u16)(v1 % v2);
+ this.AX = result;
+ }
+ private void Instruction_INC(u8 obj)
+ {
+ this.TransformData(obj, value => (u16)(value + 1));
+ }
+ private void Instruction_DEC(u8 obj)
+ {
+ this.TransformData(obj, value => (u16)(value - 1));
+ }
+ private void Instruction_INC_AX()
+ {
+ this.AX = (u16)(this.AX + 1);
+ }
+ private void Instruction_DEC_AX()
+ {
+ this.AX = (u16)(this.AX - 1);
+ }
+ private void Instruction_SHL(u8 obj)
+ {
+ this.TransformData(obj, value => (u16)(value << 1));
+ }
+ private void Instruction_SHR(u8 obj)
+ {
+ this.TransformData(obj, value => (u16)(value >> 1));
+ }
+ private void Instruction_SHL_DX()
+ {
+ this.DX = (u16)(this.DX << 1);
+ }
+ private void Instruction_SHR_DX()
+ {
+ this.DX = (u16)(this.DX >> 1);
+ }
+ private void Instruction_XOR(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ u16 result = (u16)(v1 ^ v2);
+ this.DX = result;
+ }
+ private void Instruction_OR(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ u16 result = (u16)(v1 | v2);
+ this.DX = result;
+ }
+ private void Instruction_INV(u8 obj)
+ {
+ u16 value = this.FetchData(obj);
+ u16 result = (u16)~value;
+ this.DX = result;
+ }
+ private void Instruction_INV_DX()
+ {
+ this.DX = (u16)~this.DX;
+ }
+ private void Instruction_AND(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ u16 result = (u16)(v1 & v2);
+ this.DX = result;
+ }
+ private void Instruction_NOT(u8 obj)
+ {
+ u16 value = this.FetchData(obj);
+ u16 result = value == 0 ? (u16)1 : (u16)0;
+ this.LX = result;
+ }
+ private void Instruction_NOT_LX()
+ {
+ this.LX = this.LX == 0 ? (u16)1 : (u16)0;
+ }
+ private void Instruction_GT(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ this.LX = (u16)(v1 > v2 ? 1 : 0);
+ }
+ private void Instruction_LT(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ this.LX = (u16)(v1 < v2 ? 1 : 0);
+ }
+
+ private void Instruction_BR()
+ {
+ this.FetchInstruction(out _, out _, out _, out u8 length);
+ this.PC += length;
+ }
+ private void Instruction_BZ_LX()
+ {
+ if (this.LX == 0)
+ this.Instruction_BR();
+ }
+ private void Instruction_BZ(u8 obj)
+ {
+ u16 value = this.FetchData(obj);
+ if (value == 0)
+ this.Instruction_BR();
+ }
+ private void Instruction_CMP(u8 m1, u8 m2)
+ {
+ u16 v1 = this.FetchData(m1);
+ u16 v2 = this.FetchData(m2);
+
+ // Set LX based on comparison
+ this.LX = (u16)(v1 == v2 ? 1 : 0);
+ }
+ private void Instruction_MOV(u8 m1, u8 m2)
+ {
+ u16 value = this.FetchData(m1);
+ this.StoreData(m2, value);
+ }
+
+ public void Instruction_NOP() { }
+ public void Instruction_NOP(u8 m1) { }
+ public void Instruction_NOP(u8 m1, u8 m2) { }
+
+ public void Instruction_JMP(u8 m1)
+ {
+ this.PC = this.FetchData(m1);
+ }
+
+ public void Instruction_RET()
+ {
+ this.PC = this.PopStack();
+ }
+
+ public void Instruction_CALL(u8 m1)
+ {
+ u16 address = this.FetchData(m1);
+ this.PushStack(this.PC);
+ this.PC = address;
+ }
+
+ public void Instruction_HALT()
+ {
+ throw new NotImplementedException("Halt instruction not implemented yet.");
+ }
+
+ public void Instruction_SUS()
+ {
+ this.PC -= 2;
+ }
+} \ No newline at end of file