aboutsummaryrefslogtreecommitdiffstats
path: root/src/cpu.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu.adb')
-rw-r--r--src/cpu.adb114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/cpu.adb b/src/cpu.adb
new file mode 100644
index 0000000..809e039
--- /dev/null
+++ b/src/cpu.adb
@@ -0,0 +1,114 @@
+with Ada.Sequential_IO;
+with Ada.Text_IO;
+with Bit_Ops;
+
+package body CPU is
+ function Get_Opcode (Inst : in out Instance) return Opcode is
+ Op : aliased Opcode_Raw;
+ Op_Record : Opcode with Address => Op'Address;
+ begin
+ Op := Opcode_Raw (Inst.Memory (Inst.Program_Counter)) * 2 ** 8;
+ Op := Op + Opcode_Raw (Inst.Memory (Inst.Program_Counter + 1));
+ Inst.Program_Counter := Inst.Program_Counter + 2;
+ return Op_Record;
+ end Get_Opcode;
+
+ procedure Reg_Store (Inst : in out Instance; VX : Register_Index) is
+ begin
+ for I in 0 .. VX loop
+ Inst.Memory (Inst.Address_Register + Address (I)) :=
+ Inst.Registers (I);
+ end loop;
+ end Reg_Store;
+
+ procedure Reg_Load (Inst : in out Instance; VX : Register_Index) is
+ begin
+ for I in 0 .. VX loop
+ Inst.Registers (I) := Inst.Memory
+ (Inst.Address_Register + Address (I));
+ end loop;
+ end Reg_Load;
+
+ procedure Ret (Inst : in out Instance) is
+ begin
+ Jump (Inst, Inst.Stack.Last_Element);
+ Inst.Stack.Delete_Last;
+ end Ret;
+
+ procedure Call (Inst : in out Instance; A : Address) is
+ begin
+ Inst.Stack.Append (Inst.Program_Counter);
+ Jump (Inst, A);
+ end Call;
+
+ procedure Jump (Inst : in out Instance; A : Address) is
+ begin
+ Inst.Program_Counter := A;
+ end Jump;
+
+ procedure Skip (Inst : in out Instance) is
+ begin
+ Inst.Program_Counter := Inst.Program_Counter + 2;
+ end Skip;
+
+ procedure Math (Inst : in out Instance; VX, VY : Register_Index; N : Byte)
+ is begin
+ case N is
+ when 0 =>
+ Inst.Registers (VX) := Inst.Registers (VY);
+ when 1 =>
+ Inst.Registers (VX) := Bit_Ops.Bitwise_Or
+ (Inst.Registers (VX), Inst.Registers (VY));
+ when 2 =>
+ Inst.Registers (VX) := Bit_Ops.Bitwise_And
+ (Inst.Registers (VX), Inst.Registers (VY));
+ when 3 =>
+ Inst.Registers (VX) := Bit_Ops.Bitwise_Xor
+ (Inst.Registers (VX), Inst.Registers (VY));
+ when 4 =>
+ declare
+ X : constant Byte := Inst.Registers (VX);
+ Y : constant Byte := Inst.Registers (VY);
+ begin
+ Inst.Registers (VX) := X + Y;
+ Inst.Registers (15) :=
+ (if Integer (X) + Integer (Y) > Integer (X + Y)
+ then 1 else 0);
+ end;
+ when 5 =>
+ declare
+ X : constant Byte := Inst.Registers (VX);
+ Y : constant Byte := Inst.Registers (VY);
+ begin
+ Inst.Registers (VX) := X - Y;
+ Inst.Registers (15) := (if X >= Y then 1 else 0);
+ end;
+ when 6 =>
+ Inst.Registers (15) := Inst.Registers (VX) mod 2;
+ Inst.Registers (VX) := Inst.Registers (VX) / 2;
+ when 14 =>
+ Inst.Registers (15) := Inst.Registers (VX) / (2 ** 7);
+ Inst.Registers (VX) := Inst.Registers (VX) * 2;
+ when others => begin
+ Ada.Text_IO.Put_Line ("Uh oh!");
+ Ada.Text_IO.Put_Line (Byte'Image (N));
+ end;
+ end case;
+ end Math;
+
+ procedure Load_File (Inst : in out Instance; File_Name : String) is
+ package Byte_IO is new Ada.Sequential_IO (Byte);
+
+ I : Address := Start_Address;
+ File_Handle : Byte_IO.File_Type;
+ begin
+ Byte_IO.Open (File_Handle, Byte_IO.In_File, File_Name);
+
+ while not Byte_IO.End_Of_File (File_Handle) loop
+ Byte_IO.Read (File_Handle, Inst.Memory (I));
+ I := I + 1;
+ end loop;
+
+ Byte_IO.Close (File_Handle);
+ end Load_File;
+end CPU;