| 1 | unit Cpu;
|
|---|
| 2 |
|
|---|
| 3 | interface
|
|---|
| 4 |
|
|---|
| 5 | uses
|
|---|
| 6 | Classes, SysUtils, Channel;
|
|---|
| 7 |
|
|---|
| 8 | type
|
|---|
| 9 | TOpcode = (opNop, opHalt, opLoad, opLoadMem, opStoreMem,
|
|---|
| 10 | opInput, opOutput, opJump,
|
|---|
| 11 | opWidth8, opWidth16, opWidth24, opWidth32, opWidth64, opWidth128,
|
|---|
| 12 | opLoadSys, opStoreSys);
|
|---|
| 13 |
|
|---|
| 14 | { TCpu }
|
|---|
| 15 |
|
|---|
| 16 | TCpu = class
|
|---|
| 17 | private
|
|---|
| 18 | FDataWidth: TBitWidth;
|
|---|
| 19 | FAddressWidth: TBitWidth;
|
|---|
| 20 | FPrefixDataWidth: TBitWidth;
|
|---|
| 21 | public
|
|---|
| 22 | Memory: TChannel;
|
|---|
| 23 | IO: TChannel;
|
|---|
| 24 | Terminated: Boolean;
|
|---|
| 25 | PC: QWord;
|
|---|
| 26 | A: QWord;
|
|---|
| 27 | procedure ReadData(var Data: QWord); overload;
|
|---|
| 28 | procedure ReadData(Address: QWord; var Data: QWord); overload;
|
|---|
| 29 | procedure ReadAddress(var Address: QWord);
|
|---|
| 30 | function Read8: Byte;
|
|---|
| 31 | function Read16: Word;
|
|---|
| 32 | function Read24: DWord;
|
|---|
| 33 | function Read32: DWord;
|
|---|
| 34 | function Read64: QWord;
|
|---|
| 35 | function ReadOpcode: TOpcode;
|
|---|
| 36 | procedure WriteData(Data: QWord); overload;
|
|---|
| 37 | procedure WriteData(Address: QWord; Data: QWord); overload;
|
|---|
| 38 | procedure WriteAddress(Address: QWord);
|
|---|
| 39 | procedure Write8(Data: Byte);
|
|---|
| 40 | procedure Write16(Data: Word);
|
|---|
| 41 | procedure Write24(Data: DWord);
|
|---|
| 42 | procedure Write32(Data: DWord);
|
|---|
| 43 | procedure Write64(Data: QWord);
|
|---|
| 44 | procedure WriteOpcode(Opcode: TOpcode);
|
|---|
| 45 | procedure Reset;
|
|---|
| 46 | procedure Run;
|
|---|
| 47 | procedure Step;
|
|---|
| 48 | constructor Create;
|
|---|
| 49 | destructor Destroy; override;
|
|---|
| 50 | property AddressWidth: TBitWidth read FAddressWidth write FAddressWidth;
|
|---|
| 51 | end;
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 | implementation
|
|---|
| 55 |
|
|---|
| 56 | { TCpu }
|
|---|
| 57 |
|
|---|
| 58 | function TCpu.Read8: Byte;
|
|---|
| 59 | begin
|
|---|
| 60 | Result := Memory.Read8(PC);
|
|---|
| 61 | Inc(PC);
|
|---|
| 62 | end;
|
|---|
| 63 |
|
|---|
| 64 | function TCpu.Read16: Word;
|
|---|
| 65 | begin
|
|---|
| 66 | Result := Memory.Read16(PC);
|
|---|
| 67 | Inc(PC, SizeOf(Word));
|
|---|
| 68 | end;
|
|---|
| 69 |
|
|---|
| 70 | function TCpu.Read24: DWord;
|
|---|
| 71 | begin
|
|---|
| 72 | Result := Memory.Read24(PC);
|
|---|
| 73 | Inc(PC, 3);
|
|---|
| 74 | end;
|
|---|
| 75 |
|
|---|
| 76 | function TCpu.Read32: DWord;
|
|---|
| 77 | begin
|
|---|
| 78 | Result := Memory.Read32(PC);
|
|---|
| 79 | Inc(PC, SizeOf(DWord));
|
|---|
| 80 | end;
|
|---|
| 81 |
|
|---|
| 82 | function TCpu.Read64: QWord;
|
|---|
| 83 | begin
|
|---|
| 84 | Result := Memory.Read64(PC);
|
|---|
| 85 | Inc(PC, SizeOf(QWord));
|
|---|
| 86 | end;
|
|---|
| 87 |
|
|---|
| 88 | procedure TCpu.ReadData(var Data: QWord);
|
|---|
| 89 | begin
|
|---|
| 90 | ReadData(PC, Data);
|
|---|
| 91 | Inc(PC, Integer(FDataWidth));
|
|---|
| 92 | end;
|
|---|
| 93 |
|
|---|
| 94 | procedure TCpu.ReadData(Address: QWord; var Data: QWord);
|
|---|
| 95 | begin
|
|---|
| 96 | Memory.Read(FDataWidth, Address, Data);
|
|---|
| 97 | end;
|
|---|
| 98 |
|
|---|
| 99 | procedure TCpu.ReadAddress(var Address: QWord);
|
|---|
| 100 | begin
|
|---|
| 101 | Memory.Read(FAddressWidth, PC, Address);
|
|---|
| 102 | Inc(PC, Integer(FAddressWidth));
|
|---|
| 103 | end;
|
|---|
| 104 |
|
|---|
| 105 | function TCpu.ReadOpcode: TOpcode;
|
|---|
| 106 | begin
|
|---|
| 107 | Result := TOpcode(Memory.Read8(PC));
|
|---|
| 108 | Inc(PC);
|
|---|
| 109 | end;
|
|---|
| 110 |
|
|---|
| 111 | procedure TCpu.WriteData(Data: QWord);
|
|---|
| 112 | begin
|
|---|
| 113 | WriteData(PC, Data);
|
|---|
| 114 | Inc(PC, Integer(FDataWidth));
|
|---|
| 115 | end;
|
|---|
| 116 |
|
|---|
| 117 | procedure TCpu.WriteData(Address: QWord; Data: QWord);
|
|---|
| 118 | begin
|
|---|
| 119 | Memory.Write(FDataWidth, Address, Data);
|
|---|
| 120 | end;
|
|---|
| 121 |
|
|---|
| 122 | procedure TCpu.WriteAddress(Address: QWord);
|
|---|
| 123 | begin
|
|---|
| 124 | Memory.Write(FAddressWidth, PC, Address);
|
|---|
| 125 | Inc(PC, Integer(FAddressWidth));
|
|---|
| 126 | end;
|
|---|
| 127 |
|
|---|
| 128 | procedure TCpu.Write8(Data: Byte);
|
|---|
| 129 | begin
|
|---|
| 130 | Memory.Write8(PC, Data);
|
|---|
| 131 | Inc(PC);
|
|---|
| 132 | end;
|
|---|
| 133 |
|
|---|
| 134 | procedure TCpu.Write16(Data: Word);
|
|---|
| 135 | begin
|
|---|
| 136 | Memory.Write16(PC, Data);
|
|---|
| 137 | Inc(PC, SizeOf(Word));
|
|---|
| 138 | end;
|
|---|
| 139 |
|
|---|
| 140 | procedure TCpu.Write24(Data: DWord);
|
|---|
| 141 | begin
|
|---|
| 142 | Memory.Write24(PC, Data);
|
|---|
| 143 | Inc(PC, 3);
|
|---|
| 144 | end;
|
|---|
| 145 |
|
|---|
| 146 | procedure TCpu.Write32(Data: DWord);
|
|---|
| 147 | begin
|
|---|
| 148 | Memory.Write32(PC, Data);
|
|---|
| 149 | Inc(PC, SizeOf(DWord));
|
|---|
| 150 | end;
|
|---|
| 151 |
|
|---|
| 152 | procedure TCpu.Write64(Data: QWord);
|
|---|
| 153 | begin
|
|---|
| 154 | Memory.Write64(PC, Data);
|
|---|
| 155 | Inc(PC, SizeOf(QWord));
|
|---|
| 156 | end;
|
|---|
| 157 |
|
|---|
| 158 | procedure TCpu.WriteOpcode(Opcode: TOpcode);
|
|---|
| 159 | begin
|
|---|
| 160 | Memory.Write8(PC, Byte(Opcode));
|
|---|
| 161 | Inc(PC);
|
|---|
| 162 | end;
|
|---|
| 163 |
|
|---|
| 164 | procedure TCpu.Reset;
|
|---|
| 165 | begin
|
|---|
| 166 | Terminated := False;
|
|---|
| 167 | PC := 0;
|
|---|
| 168 | FPrefixDataWidth := bwNone;
|
|---|
| 169 | FDataWidth := FAddressWidth;
|
|---|
| 170 | end;
|
|---|
| 171 |
|
|---|
| 172 | procedure TCpu.Run;
|
|---|
| 173 | begin
|
|---|
| 174 | Reset;
|
|---|
| 175 | while not Terminated do
|
|---|
| 176 | Step;
|
|---|
| 177 | end;
|
|---|
| 178 |
|
|---|
| 179 | procedure TCpu.Step;
|
|---|
| 180 | var
|
|---|
| 181 | Opcode: TOpcode;
|
|---|
| 182 | Address: QWord;
|
|---|
| 183 | begin
|
|---|
| 184 | if FPrefixDataWidth <> bwNone then begin
|
|---|
| 185 | FDataWidth := FPrefixDataWidth;
|
|---|
| 186 | FPrefixDataWidth := bwNone;
|
|---|
| 187 | end;
|
|---|
| 188 | Opcode := TOpcode(Read8);
|
|---|
| 189 | case Opcode of
|
|---|
| 190 | opNop: ;
|
|---|
| 191 | opHalt: Terminated := True;
|
|---|
| 192 | opLoad: ReadData(A);
|
|---|
| 193 | opLoadMem: begin
|
|---|
| 194 | Address := 0;
|
|---|
| 195 | ReadAddress(Address);
|
|---|
| 196 | ReadData(Address, A);
|
|---|
| 197 | end;
|
|---|
| 198 | opStoreMem: begin
|
|---|
| 199 | Address := 0;
|
|---|
| 200 | ReadAddress(Address);
|
|---|
| 201 | WriteData(Address, A);
|
|---|
| 202 | end;
|
|---|
| 203 | opInput: begin
|
|---|
| 204 | Address := 0;
|
|---|
| 205 | ReadAddress(Address);
|
|---|
| 206 | IO.Read(FDataWidth, Address, A);
|
|---|
| 207 | end;
|
|---|
| 208 | opOutput: begin
|
|---|
| 209 | Address := 0;
|
|---|
| 210 | ReadAddress(Address);
|
|---|
| 211 | IO.Write(FDataWidth, Address, A);
|
|---|
| 212 | end;
|
|---|
| 213 | opJump: begin
|
|---|
| 214 | PC := 0;
|
|---|
| 215 | ReadData(PC);
|
|---|
| 216 | end;
|
|---|
| 217 | opWidth8: if FAddressWidth <= bw8 then FPrefixDataWidth := bw8;
|
|---|
| 218 | opWidth16: if FAddressWidth <= bw16 then FPrefixDataWidth := bw16;
|
|---|
| 219 | opWidth24: if FAddressWidth <= bw24 then FPrefixDataWidth := bw24;
|
|---|
| 220 | opWidth32: if FAddressWidth <= bw32 then FPrefixDataWidth := bw32;
|
|---|
| 221 | opWidth64: if FAddressWidth <= bw64 then FPrefixDataWidth := bw64;
|
|---|
| 222 | opWidth128: if FAddressWidth <= bw128 then FPrefixDataWidth := bw128;
|
|---|
| 223 | end;
|
|---|
| 224 | FDataWidth := FAddressWidth;
|
|---|
| 225 | end;
|
|---|
| 226 |
|
|---|
| 227 | constructor TCpu.Create;
|
|---|
| 228 | begin
|
|---|
| 229 | Memory := TChannel.Create;
|
|---|
| 230 | IO := TChannel.Create;
|
|---|
| 231 | FAddressWidth := bw8;
|
|---|
| 232 | Reset;
|
|---|
| 233 | end;
|
|---|
| 234 |
|
|---|
| 235 | destructor TCpu.Destroy;
|
|---|
| 236 | begin
|
|---|
| 237 | FreeAndNil(Memory);
|
|---|
| 238 | FreeAndNil(IO);
|
|---|
| 239 | inherited;
|
|---|
| 240 | end;
|
|---|
| 241 |
|
|---|
| 242 | end.
|
|---|
| 243 |
|
|---|