diff options
Diffstat (limited to 'Q1.core/Arch/Chip.cs')
| -rw-r--r-- | Q1.core/Arch/Chip.cs | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/Q1.core/Arch/Chip.cs b/Q1.core/Arch/Chip.cs new file mode 100644 index 0000000..af131dd --- /dev/null +++ b/Q1.core/Arch/Chip.cs @@ -0,0 +1,143 @@ +namespace Q1.core.Arch; + +// Big endian +public class Chip +{ + public IAddressable Bus; + public u16 Pc, Sp; + public u16 Ax, Dx, Lx; + + private u16[] _registers; + + public void Reset() + { + this._registers = new u16[64]; + this.Pc = ChipLayout.PROGRAM_START; + this.Sp = ChipLayout.STACK_START; + } + + public void Clock() + { + this.Bus.Clock(); + + this.Fetch(out u8 opcode, out u8 m1, out u8 m2, out bool word); + + switch (m1, m2) + { + case (0x00, 0x00): + InstructionSet.Lookup[opcode].Implicit.Execute(this, word); + break; + + case (_, 0x00): + InstructionSet.Lookup[opcode].SimpleAddressing.Execute(this, m1, word); + break; + + case (0x00, 0x01): + InstructionSet.Lookup[opcode].ExtendedImplicit.Execute(this, word); + break; + + case (_, _): + InstructionSet.Lookup[opcode].ExtendedAddressing.Execute(this, m1, m2, word); + break; + } + } + + /// [opcode: 7 bits] [word: 1 bits] [m1: 4 bits] [m2: 4 bits] + public void Fetch(out u8 opcode, out u8 m1, out u8 m2, out bool word) + { + 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 + } + + public void SkipInstruction() + { + this.Fetch(out u8 _, out u8 m1, out u8 m2, out bool word); + this.Pc += (u8)(Size(m1, word) + Size(m2, word)); + } + + public u16 Load(u8 mode, bool word) + { + AddressingMode am = AddressingModes.Lookup[mode]; + return word ? am.LoadWord(this) : am.LoadByte(this); + } + + public void Store(u8 mode, u16 value, bool word) + { + AddressingMode am = AddressingModes.Lookup[mode]; + if (word) am.StoreWord(this, value); + else am.StoreByte(this, (u8)(value & 0xFF)); + } + + public u8 Size(u8 mode, bool word) + { + AddressingMode am = AddressingModes.Lookup[mode]; + return word ? am.SizeW : am.SizeB; + } + + public void Push(u16 value) + { + if (this.Sp + 2 > ChipLayout.STACK_START + ChipLayout.STACK_SIZE) + throw new InvalidOperationException("Stack overflow"); + + this.Bus.WriteWord(this.Sp, value); + + this.Sp += 2; + } + + public u16 Pop() + { + if (this.Sp - 2 < ChipLayout.STACK_START) + throw new InvalidOperationException("Stack underflow"); + + this.Sp -= 2; + u16 value = this.Bus.ReadWord(this.Sp); + + return value; + } + + public u16 GetRegister(u8 index) + { + if (index < 64) 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 == 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 == 0x48) return this.Lx; + + if (index == 0x4C) return this.Pc; + if (index == 0x4D) return this.Sp; + + throw new InvalidOperationException($"Invalid register index: {index}"); + } + + public void SetRegister(u8 index, u16 value) + { + if (index < 64) 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 == 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 == 0x48) this.Lx = value; + + else if (index == 0x4C) this.Pc = value; + else if (index == 0x4D) this.Sp = value; + + else throw new InvalidOperationException($"Invalid register index: {index}"); + } +}
\ No newline at end of file |
