diff options
Diffstat (limited to 'Q1.core')
| -rw-r--r-- | Q1.core/Arch/Chip.cs | 75 | ||||
| -rw-r--r-- | Q1.core/Arch/Constants/ChipLayout.cs (renamed from Q1.core/Arch/ChipLayout.cs) | 2 | ||||
| -rw-r--r-- | Q1.core/Arch/Constants/ChipRegisters.cs | 19 | ||||
| -rw-r--r-- | Q1.core/Arch/InstructionEncoding.cs | 26 | ||||
| -rw-r--r-- | Q1.core/Arch/Lookups/AddressingModes.cs (renamed from Q1.core/Arch/AddressingModes.cs) | 15 | ||||
| -rw-r--r-- | Q1.core/Arch/Lookups/InstructionSet.cs (renamed from Q1.core/Arch/InstructionSet.cs) | 102 | ||||
| -rw-r--r-- | Q1.core/Exceptions.cs | 7 |
7 files changed, 170 insertions, 76 deletions
diff --git a/Q1.core/Arch/Chip.cs b/Q1.core/Arch/Chip.cs index 9f5f109..fef9cea 100644 --- a/Q1.core/Arch/Chip.cs +++ b/Q1.core/Arch/Chip.cs @@ -1,6 +1,8 @@ namespace Q1.core.Arch; using Components; +using Constants; +using Lookups; // Big endian public class Chip @@ -10,10 +12,15 @@ public class Chip public u16 Ax, Dx, Lx; private u16[] _registers; + + public Chip() + { + this.Reset(); + } public void Reset() { - this._registers = new u16[64]; + this._registers = new u16[ChipRegisters.GENERIC_REGISTER_COUNT]; this.Pc = ChipLayout.PROGRAM_START; this.Sp = ChipLayout.STACK_START; } @@ -23,23 +30,25 @@ public class Chip this.Bus.Clock(); this.Fetch(out u8 opcode, out u8 m1, out u8 m2, out bool word); + + var instruction = InstructionSet.Lookup[opcode]; switch (m1, m2) { case (0x00, 0x00): - InstructionSet.Lookup[opcode].Implicit.Execute(this, word); + instruction.Implicit.Execute(this, word); break; case (_, 0x00): - InstructionSet.Lookup[opcode].SimpleAddressing.Execute(this, m1, word); + instruction.SimpleAddressing.Execute(this, m1, word); break; case (0x00, 0x01): - InstructionSet.Lookup[opcode].ExtendedImplicit.Execute(this, word); + instruction.ExtendedImplicit.Execute(this, word); break; case (_, _): - InstructionSet.Lookup[opcode].ExtendedAddressing.Execute(this, m1, m2, word); + instruction.ExtendedAddressing.Execute(this, m1, m2, word); break; } } @@ -49,12 +58,8 @@ public class Chip { u16 instruction = this.Bus.ReadWord(this.Pc); this.Pc += 2; - - opcode = (u8) ((instruction >> 8) & 0xFE); // 128 opcodes - word = ((instruction >> 8) & 0x1) != 0; // flag for word mode - m1 = (u8) ((instruction >> 4) & 0x0F); // 16 modes - m2 = (u8) (instruction & 0x0F); // 16 modes + InstructionEncoding.Decode(instruction, out opcode, out m1, out m2, out word); } public void SkipInstruction() @@ -105,43 +110,44 @@ public class Chip public u16 GetRegister(u8 index) { - if (index < 64) return this._registers[index]; + if (index < ChipRegisters.GENERIC_REGISTER_COUNT) return this._registers[index]; - if (index == 0x40) return this.Ax; - if (index == 0x41) return (u16) (this.Ax >> 8); // High byte of Ax - if (index == 0x42) return (u16) (this.Ax & 0xFF); // Low byte of Ax + if (index == ChipRegisters.AX) return this.Ax; + if (index == ChipRegisters.AH) return (u16) (this.Ax >> 8); // High byte of Ax + if (index == ChipRegisters.AL) return (u16) (this.Ax & 0xFF); // Low byte of Ax - if (index == 0x44) return this.Dx; - if (index == 0x45) return (u16) (this.Dx >> 8); // High byte of Dx - if (index == 0x46) return (u16) (this.Dx & 0xFF); // Low byte of Dx + if (index == ChipRegisters.DX) return this.Dx; + if (index == ChipRegisters.DH) return (u16) (this.Dx >> 8); // High byte of Dx + if (index == ChipRegisters.DL) return (u16) (this.Dx & 0xFF); // Low byte of Dx - if (index == 0x48) return this.Lx; + if (index == ChipRegisters.LX) return this.Lx; - if (index == 0x4C) return this.Pc; - if (index == 0x4D) return this.Sp; + if (index == ChipRegisters.PC) return this.Pc; + if (index == ChipRegisters.SP) return this.Sp; throw new InvalidOperationException($"Invalid register index: {index}"); } public void SetRegister(u8 index, u16 value) { - if (index < 64) this._registers[index] = value; + if (index < ChipRegisters.GENERIC_REGISTER_COUNT) this._registers[index] = value; - else if (index == 0x40) this.Ax = value; - else if (index == 0x41) this.Ax = (u16)((this.Ax & 0x00FF) | ((value & 0xFF) << 8)); // Set high byte of Ax - else if (index == 0x42) this.Ax = (u16)((this.Ax & 0xFF00) | (value & 0xFF)); // Set low byte of Ax + else if (index == ChipRegisters.AX) this.Ax = value; + else if (index == ChipRegisters.AH) this.Ax = (u16)((this.Ax & 0x00FF) | ((value & 0xFF) << 8)); // Set high byte of Ax + else if (index == ChipRegisters.AL) this.Ax = (u16)((this.Ax & 0xFF00) | (value & 0xFF)); // Set low byte of Ax - else if (index == 0x44) this.Dx = value; - else if (index == 0x45) this.Dx = (u16)((this.Dx & 0x00FF) | ((value & 0xFF) << 8)); // Set high byte of Dx - else if (index == 0x46) this.Dx = (u16)((this.Dx & 0xFF00) | (value & 0xFF)); // Set low byte of Dx + else if (index == ChipRegisters.DX) this.Dx = value; + else if (index == ChipRegisters.DH) this.Dx = (u16)((this.Dx & 0x00FF) | ((value & 0xFF) << 8)); // Set high byte of Dx + else if (index == ChipRegisters.DL) this.Dx = (u16)((this.Dx & 0xFF00) | (value & 0xFF)); // Set low byte of Dx - else if (index == 0x48) this.Lx = value; + else if (index == ChipRegisters.LX) this.Lx = value; - else if (index == 0x4C) this.Pc = value; - else if (index == 0x4D) this.Sp = value; + else if (index == ChipRegisters.PC) this.Pc = value; + else if (index == ChipRegisters.SP) this.Sp = value; else throw new InvalidOperationException($"Invalid register index: {index}"); } + public void Interrupt(u16 code) { if (code >= ChipLayout.IVT_COUNT) @@ -151,4 +157,13 @@ public class Chip u16 interruptVectorAddress = (u16) (ChipLayout.IVT_START + code * 2); this.Pc = this.Bus.ReadWord(interruptVectorAddress); } + + public void RegisterInterruptHandler(u16 code, u16 handlerAddress) + { + if (code >= ChipLayout.IVT_COUNT) + throw new InvalidOperationException($"Invalid interrupt code: {code}"); + + u16 interruptVectorAddress = (u16) (ChipLayout.IVT_START + code * 2); + this.Bus.WriteWord(interruptVectorAddress, handlerAddress); + } }
\ No newline at end of file diff --git a/Q1.core/Arch/ChipLayout.cs b/Q1.core/Arch/Constants/ChipLayout.cs index 6c7187b..6990789 100644 --- a/Q1.core/Arch/ChipLayout.cs +++ b/Q1.core/Arch/Constants/ChipLayout.cs @@ -1,4 +1,4 @@ -namespace Q1.core.Arch; +namespace Q1.core.Arch.Constants; public static class ChipLayout { diff --git a/Q1.core/Arch/Constants/ChipRegisters.cs b/Q1.core/Arch/Constants/ChipRegisters.cs new file mode 100644 index 0000000..042ce32 --- /dev/null +++ b/Q1.core/Arch/Constants/ChipRegisters.cs @@ -0,0 +1,19 @@ +namespace Q1.core.Arch.Constants; + +public static class ChipRegisters +{ + public const u8 GENERIC_REGISTER_COUNT = 64; + + public const u8 AX = 0x40; + public const u8 AH = 0x41; + public const u8 AL = 0x42; + + public const u8 DX = 0x44; + public const u8 DH = 0x45; + public const u8 DL = 0x46; + + public const u8 LX = 0x48; + + public const u8 PC = 0x4C; + public const u8 SP = 0x4D; +}
\ No newline at end of file diff --git a/Q1.core/Arch/InstructionEncoding.cs b/Q1.core/Arch/InstructionEncoding.cs new file mode 100644 index 0000000..479d61f --- /dev/null +++ b/Q1.core/Arch/InstructionEncoding.cs @@ -0,0 +1,26 @@ +namespace Q1.core.Arch; + +public static class InstructionEncoding +{ + public static void Decode(u16 instruction, out u8 opcode, out u8 m1, out u8 m2, out bool word) + { + word = ((instruction >> 15) & 0x1) != 0; // top bit + opcode = (u8)((instruction >> 8) & 0x7F); // 7 clean bits + + m1 = (u8)((instruction >> 4) & 0x0F); + m2 = (u8)(instruction & 0x0F); + } + + public static u16 Encode(u8 opcode, u8 m1, u8 m2, bool word) + { + u16 instruction = 0; + + instruction |= (u16)((opcode & 0x7F) << 8); // 7-bit opcode + instruction |= (u16)((word ? 1 : 0) << 15); // top bit flag + + instruction |= (u16)((m1 & 0x0F) << 4); + instruction |= (u16)(m2 & 0x0F); + + return instruction; + } +}
\ No newline at end of file diff --git a/Q1.core/Arch/AddressingModes.cs b/Q1.core/Arch/Lookups/AddressingModes.cs index 96b4475..95e798d 100644 --- a/Q1.core/Arch/AddressingModes.cs +++ b/Q1.core/Arch/Lookups/AddressingModes.cs @@ -1,11 +1,22 @@ -namespace Q1.core.Arch; +namespace Q1.core.Arch.Lookups; -using Components; +using Q1.core.Components; public static class AddressingModes { public static AddressingMode[] Lookup = new AddressingMode[8]; + public static u8 GetAddressingMode(string name) + { + for (u8 i = 0; i < AddressingModes.Lookup.Length; i++) + { + if (AddressingModes.Lookup[i].Name == name) + return i; + } + + throw new ArgumentException($"Invalid addressing mode: {name}"); + } + static AddressingModes() { AddressingModes.Lookup[0x00] = new AddressingMode diff --git a/Q1.core/Arch/InstructionSet.cs b/Q1.core/Arch/Lookups/InstructionSet.cs index 212e77e..2ea20fc 100644 --- a/Q1.core/Arch/InstructionSet.cs +++ b/Q1.core/Arch/Lookups/InstructionSet.cs @@ -1,9 +1,25 @@ -namespace Q1.core.Arch; +namespace Q1.core.Arch.Lookups; public static class InstructionSet { public static readonly InstructionGroup[] Lookup = new InstructionGroup[128]; + public static u8 GetOpcode(string instructionName) + { + for (u8 opcode = 0; opcode < InstructionSet.Lookup.Length; opcode++) + { + var group = InstructionSet.Lookup[opcode]; + if (group.Implicit.Name == instructionName || + group.SimpleAddressing.Name == instructionName || + group.ExtendedImplicit.Name == instructionName || + group.ExtendedAddressing.Name == instructionName) + { + return opcode; + } + } + throw new ArgumentException($"Instruction '{instructionName}' not found in the instruction set."); + } + static InstructionSet() { var nop = new ImplicitInstruction { Name = "NOP", Execute = InstructionSet.Nop }; @@ -173,85 +189,85 @@ public static class InstructionSet Implicit = nop, SimpleAddressing = nopSimple, ExtendedImplicit = nop, - ExtendedAddressing = new ExtendedInstruction { Name = "DIV", Execute = InstructionSet.Modulo } + ExtendedAddressing = new ExtendedInstruction { Name = "MOD", Execute = InstructionSet.Modulo } }; #endregion } - private static void Nop(Chip chip, bool word) { /* No operation */ } - private static void Nop(Chip chip, u8 m1, bool word) { /* No operation */ } - private static void Nop(Chip chip, u8 m1, u8 m2, bool word) { /* No operation */ } + public static void Nop(Chip chip, bool word) { /* No operation */ } + public static void Nop(Chip chip, u8 m1, bool word) { /* No operation */ } + public static void Nop(Chip chip, u8 m1, u8 m2, bool word) { /* No operation */ } #region Control Instructions - private static void Halt(Chip chip, bool word) + public static void Halt(Chip chip, bool word) { - throw new NotImplementedException("HALT instruction is not implemented yet."); + throw new HaltException(); } - private static void Suspend(Chip chip, bool word) + public static void Suspend(Chip chip, bool word) { throw new NotImplementedException("SUS instruction is not implemented yet."); } - private static void Interrupt(Chip chip, u8 m1, bool word) + public static void Interrupt(Chip chip, u8 m1, bool word) { u16 interruptNumber = chip.Load(m1, word); chip.Interrupt(interruptNumber); } - private static void Move(Chip chip, u8 m1, u8 m2, bool word) + public static void Move(Chip chip, u8 m1, u8 m2, bool word) { u16 value = chip.Load(m1, word); chip.Store(m2, value, word); } - private static void Jump(Chip chip, u8 m1, bool word) + public static void Jump(Chip chip, u8 m1, bool word) { u16 address = chip.Load(m1, word); chip.Pc = address; } - private static void Call(Chip chip, u8 m1, bool word) + public static void Call(Chip chip, u8 m1, bool word) { u16 targetAddress = chip.Load(m1, word); chip.Push(chip.Pc); chip.Pc = targetAddress; } - private static void Return(Chip chip, bool word) + public static void Return(Chip chip, bool word) { u16 returnAddress = chip.Pop(); chip.Pc = returnAddress; } - private static void BranchIfZero(Chip chip, u8 m1, bool word) + public static void BranchIfZero(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); if (value == 0) chip.SkipInstruction(); } - private static void BranchIfZeroLx(Chip chip, bool word) + public static void BranchIfZeroLx(Chip chip, bool word) { if (chip.Lx == 0) chip.SkipInstruction(); } - private static void Branch(Chip chip, bool word) + public static void Branch(Chip chip, bool word) { chip.SkipInstruction(); } - private static void Push(Chip chip, u8 m1, bool word) + public static void Push(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); chip.Push(value); } - private static void Pop(Chip chip, u8 m1, bool word) + public static void Pop(Chip chip, u8 m1, bool word) { u16 value = chip.Pop(); chip.Store(m1, value, word); @@ -261,7 +277,7 @@ public static class InstructionSet #region Data Instructions - private static void Inverse(Chip chip, u8 m1, bool word) + public static void Inverse(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); value = (u16)~value; @@ -269,12 +285,12 @@ public static class InstructionSet chip.Dx = value; } - private static void InverseDx(Chip chip, bool word) + public static void InverseDx(Chip chip, bool word) { chip.Dx = (u16)~chip.Dx; } - private static void And(Chip chip, u8 m1, u8 m2, bool word) + public static void And(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -283,7 +299,7 @@ public static class InstructionSet chip.Dx = result; } - private static void Or(Chip chip, u8 m1, u8 m2, bool word) + public static void Or(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -292,7 +308,7 @@ public static class InstructionSet chip.Dx = result; } - private static void Xor(Chip chip, u8 m1, u8 m2, bool word) + public static void Xor(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -301,7 +317,7 @@ public static class InstructionSet chip.Dx = result; } - private static void ShiftLeft(Chip chip, u8 m1, u8 m2, bool word) + public static void ShiftLeft(Chip chip, u8 m1, u8 m2, bool word) { u16 value = chip.Load(m1, word); u16 shiftAmount = (u16) (chip.Load(m2, word) & 0xF); // Limit shift to 0-15 @@ -310,7 +326,7 @@ public static class InstructionSet chip.Dx = result; } - private static void ShiftRight(Chip chip, u8 m1, u8 m2, bool word) + public static void ShiftRight(Chip chip, u8 m1, u8 m2, bool word) { u16 value = chip.Load(m1, word); u16 shiftAmount = (u16) (chip.Load(m2, word) & 0xF); // Limit shift to 0-15 @@ -319,7 +335,7 @@ public static class InstructionSet chip.Dx = result; } - private static void ShiftPlaceLeft(Chip chip, u8 m1, bool word) + public static void ShiftPlaceLeft(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); u16 result = (u16) ((value << 1) | (value >> 15)); // Rotate left @@ -327,7 +343,7 @@ public static class InstructionSet chip.Dx = result; } - private static void ShiftPlaceRight(Chip chip, u8 m1, bool word) + public static void ShiftPlaceRight(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); u16 result = (u16) ((value >> 1) | (value << 15)); // Rotate right @@ -335,7 +351,7 @@ public static class InstructionSet chip.Dx = result; } - private static void ShiftPlaceLeftDx(Chip chip, bool word) + public static void ShiftPlaceLeftDx(Chip chip, bool word) { u16 value = chip.Dx; u16 result = (u16) ((value << 1) | (value >> 15)); // Rotate left @@ -343,7 +359,7 @@ public static class InstructionSet chip.Dx = result; } - private static void ShiftPlaceRightDx(Chip chip, bool word) + public static void ShiftPlaceRightDx(Chip chip, bool word) { u16 value = chip.Dx; u16 result = (u16) ((value >> 1) | (value << 15)); // Rotate right @@ -355,32 +371,32 @@ public static class InstructionSet #region Logic Instructions - private static void Not(Chip chip, u8 m1, bool word) + public static void Not(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); chip.Lx = value == 0 ? (u16)1 : (u16)0; } - private static void NotLx(Chip chip, bool word) + public static void NotLx(Chip chip, bool word) { chip.Lx = chip.Lx == 0 ? (u16)1 : (u16)0; } - private static void Compare(Chip chip, u8 m1, u8 m2, bool word) + public static void Compare(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); chip.Lx = value1 == value2 ? (u16)1 : (u16)0; } - private static void LessThan(Chip chip, u8 m1, u8 m2, bool word) + public static void LessThan(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); chip.Lx = value1 < value2 ? (u16)1 : (u16)0; } - private static void GreaterThan(Chip chip, u8 m1, u8 m2, bool word) + public static void GreaterThan(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -391,31 +407,31 @@ public static class InstructionSet #region Arithmetic Instructions - private static void Increment(Chip chip, u8 m1, bool word) + public static void Increment(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); value++; chip.Store(m1, value, word); } - private static void IncrementAx(Chip chip, bool word) + public static void IncrementAx(Chip chip, bool word) { chip.Ax++; } - private static void Decrement(Chip chip, u8 m1, bool word) + public static void Decrement(Chip chip, u8 m1, bool word) { u16 value = chip.Load(m1, word); value--; chip.Store(m1, value, word); } - private static void DecrementAx(Chip chip, bool word) + public static void DecrementAx(Chip chip, bool word) { chip.Ax--; } - private static void Add(Chip chip, u8 m1, u8 m2, bool word) + public static void Add(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -424,7 +440,7 @@ public static class InstructionSet chip.Ax = result; } - private static void Subtract(Chip chip, u8 m1, u8 m2, bool word) + public static void Subtract(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -433,7 +449,7 @@ public static class InstructionSet chip.Ax = result; } - private static void Multiply(Chip chip, u8 m1, u8 m2, bool word) + public static void Multiply(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -442,7 +458,7 @@ public static class InstructionSet chip.Ax = result; } - private static void Divide(Chip chip, u8 m1, u8 m2, bool word) + public static void Divide(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); @@ -453,7 +469,7 @@ public static class InstructionSet chip.Ax = result; } - private static void Modulo(Chip chip, u8 m1, u8 m2, bool word) + public static void Modulo(Chip chip, u8 m1, u8 m2, bool word) { u16 value1 = chip.Load(m1, word); u16 value2 = chip.Load(m2, word); diff --git a/Q1.core/Exceptions.cs b/Q1.core/Exceptions.cs new file mode 100644 index 0000000..fa5156f --- /dev/null +++ b/Q1.core/Exceptions.cs @@ -0,0 +1,7 @@ +namespace Q1.core; + +public class ChipException(string message) : Exception(message); + +public class InvalidInstructionException(u8 opcode) : ChipException($"Invalid instruction: 0x{opcode:X2}"); +public class InvalidAddressingModeException(u8 mode) : ChipException($"Invalid addressing mode: 0x{mode:X2}"); +public class HaltException() : ChipException("Execution halted");
\ No newline at end of file |
