diff options
Diffstat (limited to 'Chip/Q1CpuInstructions.cs')
| -rw-r--r-- | Chip/Q1CpuInstructions.cs | 225 |
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 |
