{$IFDEF INTERFACE} TGCpu = class public PC: TGCpuData; A: TGCpuData; Memory: TGCpuAddrChannel; IO: TGCpuAddrChannel; Terminated: Boolean; function Read: TGCpuData; procedure Write(Data: TGCpuData); procedure WriteOpcode(Opcode: TOpcode); procedure Output(Address: TGCpuData; Data: TGCpuData); {$IF TGCpuWidth>=8} function Read8: Byte; procedure Write8(Data: Byte); procedure Output8(Address: TGCpuData; Data: Byte); {$ENDIF} {$IF TGCpuWidth>=16} function Read16: Word; procedure Write16(Data: Word); procedure Output16(Address: TGCpuData; Data: Word); {$ENDIF} {$IF TGCpuWidth>=32} function Read32: DWord; procedure Write32(Data: DWord); procedure Output32(Address: TGCpuData; Data: DWord); {$ENDIF} {$IF TGCpuWidth>=64} function Read64: QWord; procedure Write64(Data: QWord); procedure Output64(Address: TGCpuData; Data: QWord); {$ENDIF} procedure Run; procedure Step; procedure Reset; constructor Create; destructor Destroy; override; end; {$UNDEF INTERFACE} {$ENDIF} {$IFDEF IMPLEMENTATION} constructor TGCpu.Create; begin Memory := TGCpuAddrChannel.Create; IO := TGCpuAddrChannel.Create; end; destructor TGCpu.Destroy; begin FreeAndNil(IO); FreeAndNil(Memory); inherited; end; procedure TGCpu.Reset; begin A := 0; PC := 0; Terminated := False; end; procedure TGCpu.Run; begin Reset; while not Terminated do Step; end; procedure TGCpu.Step; var Opcode: TOpcode; begin Opcode := TOpcode(Read8); case Opcode of opNop: ; opHalt: Terminated := True; opLoadImmediate: A := Read; {$IF TGCpuWidth>=8}opLoadImmediate8: PByte(@A)^ := Read8;{$ENDIF} {$IF TGCpuWidth>=16}opLoadImmediate16: PWord(@A)^ := Read16;{$ENDIF} {$IF TGCpuWidth>=32}opLoadImmediate32: PDWord(@A)^ := Read32;{$ENDIF} {$IF TGCpuWidth>=64}opLoadImmediate64: PQWord(@A)^ := Read64;{$ENDIF} opOutput: Output(Read, A); {$IF TGCpuWidth>=8}opOutput8: Output8(Read, A);{$ENDIF} {$IF TGCpuWidth>=16}opOutput16: Output16(Read, A);{$ENDIF} {$IF TGCpuWidth>=32}opOutput32: Output32(Read, A);{$ENDIF} {$IF TGCpuWidth>=64}opOutput64: Output64(Read, A);{$ENDIF} opInc: A := A + 1; {$IF TGCpuWidth>=8}opInc8: PByte(@A)^ := PByte(@A)^ + 1;{$ENDIF} {$IF TGCpuWidth>=16}opInc16: PWord(@A)^ := PWord(@A)^ + 1;{$ENDIF} {$IF TGCpuWidth>=32}opInc32: PDWord(@A)^ := PDWord(@A)^ + 1;{$ENDIF} {$IF TGCpuWidth>=64}opInc64: PQWord(@A)^ := PQWord(@A)^ + 1;{$ENDIF} end; end; function TGCpu.Read: TGCpuData; begin {$IF TGCpuWidth=8}Result := Memory.Read8(PC);{$ENDIF} {$IF TGCpuWidth=16}Result := Memory.Read16(PC);{$ENDIF} {$IF TGCpuWidth=32}Result := Memory.Read32(PC);{$ENDIF} {$IF TGCpuWidth=64}Result := Memory.Read64(PC);{$ENDIF} Inc(PC, SizeOf(TGCpuData)); end; procedure TGCpu.Write(Data: TGCpuData); begin {$IF TGCpuWidth=8}Memory.Write8(PC, Data);{$ENDIF} {$IF TGCpuWidth=16}Memory.Write16(PC, Data);{$ENDIF} {$IF TGCpuWidth=32}Memory.Write32(PC, Data);{$ENDIF} {$IF TGCpuWidth=64}Memory.Write64(PC, Data);{$ENDIF} Inc(PC, SizeOf(TGCpuData)); end; procedure TGCpu.Output(Address: TGCpuData; Data: TGCpuData); begin {$IF TGCpuWidth=8}IO.Write8(Address, Data);{$ENDIF} {$IF TGCpuWidth=16}IO.Write16(Address, Data);{$ENDIF} {$IF TGCpuWidth=32}IO.Write32(Address, Data);{$ENDIF} {$IF TGCpuWidth=64}IO.Write64(Address, Data);{$ENDIF} end; procedure TGCpu.WriteOpcode(Opcode: TOpcode); begin Write8(Byte(Opcode)); end; {$IF TGCpuWidth>=8} function TGCpu.Read8: Byte; begin Result := Memory.Read8(PC); Inc(PC); end; procedure TGCpu.Write8(Data: Byte); begin Memory.Write8(PC, Data); Inc(PC); end; procedure TGCpu.Output8(Address: TGCpuData; Data: Byte); begin IO.Write8(Address, Data); end; {$ENDIF} {$IF TGCpuWidth>=16} function TGCpu.Read16: Word; begin Result := Memory.Read16(PC); Inc(PC, SizeOf(Word)); end; procedure TGCpu.Write16(Data: Word); begin Memory.Write16(PC, Data); Inc(PC, SizeOf(Word)); end; procedure TGCpu.Output16(Address: TGCpuData; Data: Word); begin IO.Write16(Address, Data); end; {$ENDIF} {$IF TGCpuWidth>=32} function TGCpu.Read32: DWord; begin Result := Memory.Read32(PC); Inc(PC, SizeOf(DWord)); end; procedure TGCpu.Write32(Data: DWord); begin Memory.Write32(PC, Data); Inc(PC, SizeOf(DWord)); end; procedure TGCpu.Output32(Address: TGCpuData; Data: DWord); begin IO.Write32(Address, Data); end; {$ENDIF} {$IF TGCpuWidth>=64} function TGCpu.Read64: QWord; begin Result := Memory.Read64(PC); Inc(PC, SizeOf(QWord)); end; procedure TGCpu.Write64(Data: QWord); begin Memory.Write64(PC, Data); Inc(PC, SizeOf(QWord)); end; procedure TGCpu.Output64(Address: TGCpuData; Data: QWord); begin IO.Write64(Address, Data); end; {$ENDIF} {$UNDEF IMPLEMENTATION} {$ENDIF}