| 1 | unit Cpu;
|
|---|
| 2 |
|
|---|
| 3 | interface
|
|---|
| 4 |
|
|---|
| 5 | uses
|
|---|
| 6 | Classes, SysUtils;
|
|---|
| 7 |
|
|---|
| 8 | type
|
|---|
| 9 | TInstruction = (inNop, inHalt,
|
|---|
| 10 | inConstD, inConstA, inConstN,
|
|---|
| 11 | inLoadD, inLoadA, inLoadN,
|
|---|
| 12 | inStoreD, inStoreA, inStoreN,
|
|---|
| 13 | inInputD, inInputA, inInputN,
|
|---|
| 14 | inOutputD, inOutputA, inOutputN,
|
|---|
| 15 | inAdd, inSub);
|
|---|
| 16 |
|
|---|
| 17 | { TCpu }
|
|---|
| 18 |
|
|---|
| 19 | TCpu<TData,TAddr,TMax> = class
|
|---|
| 20 | type
|
|---|
| 21 | PData = ^TData;
|
|---|
| 22 | PAddr = ^TAddr;
|
|---|
| 23 | PMax = ^TMax;
|
|---|
| 24 | TRegIndex = 0..255;
|
|---|
| 25 | TOnInput = function (Addr: TAddr; Count: Byte): TData of object;
|
|---|
| 26 | TOnOutput = procedure (Addr: TAddr; Data: TData; Count: Byte) of object;
|
|---|
| 27 | private
|
|---|
| 28 | FOnInput: TOnInput;
|
|---|
| 29 | FOnOutput: TOnOutput;
|
|---|
| 30 | public
|
|---|
| 31 | Memory: array[0..$ffff] of Byte;
|
|---|
| 32 | PC: TAddr;
|
|---|
| 33 | SP: TAddr;
|
|---|
| 34 | R: array[TRegIndex] of TMax;
|
|---|
| 35 | Terminated: Boolean;
|
|---|
| 36 | procedure Run;
|
|---|
| 37 | procedure Step;
|
|---|
| 38 | procedure Reset;
|
|---|
| 39 | procedure AddConstD(Reg: TRegIndex; Value: TData);
|
|---|
| 40 | procedure AddConstA(Reg: TRegIndex; Value: TAddr);
|
|---|
| 41 | procedure AddConstN(Count: Byte; Reg: TRegIndex; Value: TMax);
|
|---|
| 42 | procedure AddOutputD(Addr: TAddr; Reg: TRegIndex);
|
|---|
| 43 | procedure AddOutputA(Addr: TAddr; Reg: TRegIndex);
|
|---|
| 44 | procedure AddOutputN(Count: Byte; Addr: TAddr; Reg: TRegIndex);
|
|---|
| 45 | procedure AddHalt;
|
|---|
| 46 | function ReadBytePC: Byte;
|
|---|
| 47 | function ReadDataPC: TData;
|
|---|
| 48 | function ReadAddrPC: TAddr;
|
|---|
| 49 | function ReadPC(Count: Byte): TMax;
|
|---|
| 50 | function ReadData(Addr: TAddr): TData;
|
|---|
| 51 | function ReadAddr(Addr: TAddr): TAddr;
|
|---|
| 52 | function Read(Addr: TAddr; Count: Byte): TMax;
|
|---|
| 53 | function ReadRegData(Reg: TRegIndex): TData;
|
|---|
| 54 | function ReadRegAddr(Reg: TRegIndex): TAddr;
|
|---|
| 55 | function ReadReg(Reg: TRegIndex; Count: Byte): TMax;
|
|---|
| 56 | procedure WriteBytePC(Data: Byte);
|
|---|
| 57 | procedure WriteRegPC(Reg: TRegIndex);
|
|---|
| 58 | procedure WriteDataPC(Data: TData);
|
|---|
| 59 | procedure WriteAddrPC(Addr: TAddr);
|
|---|
| 60 | procedure WritePC(Value: TMax; Count: Byte);
|
|---|
| 61 | procedure WriteData(Addr: TAddr; Value: TData);
|
|---|
| 62 | procedure WriteAddr(Addr, Value: TAddr);
|
|---|
| 63 | procedure WriteRegData(Reg: TRegIndex; Value: TData);
|
|---|
| 64 | procedure WriteRegAddr(Reg: TRegIndex; Value: TAddr);
|
|---|
| 65 | procedure WriteReg(Reg: TRegIndex; Value: TMax; Count: Byte);
|
|---|
| 66 | constructor Create;
|
|---|
| 67 | destructor Destroy; override;
|
|---|
| 68 | property OnInput: TOnInput read FOnInput write FOnInput;
|
|---|
| 69 | property OnOutput: TOnOutput read FOnOutput write FOnOutput;
|
|---|
| 70 | end;
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 | implementation
|
|---|
| 74 |
|
|---|
| 75 | { TCpu }
|
|---|
| 76 |
|
|---|
| 77 | procedure TCpu<TData,TAddr,TMax>.Run;
|
|---|
| 78 | begin
|
|---|
| 79 | Reset;
|
|---|
| 80 | while not Terminated do
|
|---|
| 81 | Step;
|
|---|
| 82 | end;
|
|---|
| 83 |
|
|---|
| 84 | procedure TCpu<TData,TAddr,TMax>.Step;
|
|---|
| 85 | var
|
|---|
| 86 | Instruction: TInstruction;
|
|---|
| 87 | I: TRegIndex;
|
|---|
| 88 | Addr: TAddr;
|
|---|
| 89 | N: Byte;
|
|---|
| 90 | M: TMax;
|
|---|
| 91 | begin
|
|---|
| 92 | Instruction := TInstruction(ReadBytePC);
|
|---|
| 93 | case Instruction of
|
|---|
| 94 | inNop: ;
|
|---|
| 95 | inHalt: Terminated := True;
|
|---|
| 96 | inConstD: PData(@R[ReadBytePC])^ := ReadDataPC;
|
|---|
| 97 | inConstA: PAddr(@R[ReadBytePC])^ := ReadAddrPC;
|
|---|
| 98 | inConstN: begin
|
|---|
| 99 | N := ReadBytePC;
|
|---|
| 100 | I := ReadBytePC;
|
|---|
| 101 | WriteReg(I, ReadPC(N), N);
|
|---|
| 102 | end;
|
|---|
| 103 | inLoadD: PData(@R[ReadBytePC])^ := ReadData(ReadAddrPC);
|
|---|
| 104 | inLoadA: PAddr(@R[ReadBytePC])^ := ReadAddr(ReadAddrPC);
|
|---|
| 105 | inLoadN: begin
|
|---|
| 106 | N := ReadBytePC;
|
|---|
| 107 | WriteReg(ReadBytePC, Read(ReadAddrPC, N), N);
|
|---|
| 108 | end;
|
|---|
| 109 | inStoreD: WriteData(ReadAddrPC, R[ReadBytePC]);
|
|---|
| 110 | inStoreA: WriteAddr(ReadAddrPC, R[ReadBytePC]);
|
|---|
| 111 | inStoreN: begin
|
|---|
| 112 | N := ReadBytePC;
|
|---|
| 113 | Write(ReadAddrPC, ReadReg(ReadBytePC, N), N);
|
|---|
| 114 | end;
|
|---|
| 115 | inInputD: begin
|
|---|
| 116 | I := ReadBytePC;
|
|---|
| 117 | Addr := ReadAddrPC;
|
|---|
| 118 | if Assigned(FOnInput) then PData(@R[I])^ := FOnInput(Addr, SizeOf(TData))
|
|---|
| 119 | else R[I] := 0;
|
|---|
| 120 | end;
|
|---|
| 121 | inInputA: begin
|
|---|
| 122 | I := ReadBytePC;
|
|---|
| 123 | Addr := ReadAddrPC;
|
|---|
| 124 | if Assigned(FOnInput) then PAddr(@R[I])^ := FOnInput(Addr, SizeOf(TAddr))
|
|---|
| 125 | else R[I] := 0;
|
|---|
| 126 | end;
|
|---|
| 127 | inInputN: begin
|
|---|
| 128 | N := ReadBytePC;
|
|---|
| 129 | I := ReadBytePC;
|
|---|
| 130 | Addr := ReadAddrPC;
|
|---|
| 131 | if Assigned(FOnInput) then begin
|
|---|
| 132 | M := FOnInput(Addr, N);
|
|---|
| 133 | Move(M, R[I], N);
|
|---|
| 134 | end else R[I] := 0;
|
|---|
| 135 | end;
|
|---|
| 136 | inOutputD: begin
|
|---|
| 137 | Addr := ReadAddrPC;
|
|---|
| 138 | I := ReadBytePC;
|
|---|
| 139 | if Assigned(FOnOutput) then FOnOutput(Addr, PData(@R[I])^, SizeOf(TData));
|
|---|
| 140 | end;
|
|---|
| 141 | inOutputA: begin
|
|---|
| 142 | Addr := ReadAddrPC;
|
|---|
| 143 | I := ReadBytePC;
|
|---|
| 144 | if Assigned(FOnOutput) then FOnOutput(Addr, PAddr(@R[I])^, SizeOf(TAddr));
|
|---|
| 145 | end;
|
|---|
| 146 | inOutputN: begin
|
|---|
| 147 | N := ReadBytePC;
|
|---|
| 148 | Addr := ReadAddrPC;
|
|---|
| 149 | I := ReadBytePC;
|
|---|
| 150 | M := 0;
|
|---|
| 151 | Move(R[I], M, N);
|
|---|
| 152 | if Assigned(FOnOutput) then FOnOutput(Addr, M, N);
|
|---|
| 153 | end;
|
|---|
| 154 | end;
|
|---|
| 155 | end;
|
|---|
| 156 |
|
|---|
| 157 | procedure TCpu<TData,TAddr,TMax>.Reset;
|
|---|
| 158 | begin
|
|---|
| 159 | SP := 0;
|
|---|
| 160 | PC := 0;
|
|---|
| 161 | Terminated := False;
|
|---|
| 162 | end;
|
|---|
| 163 |
|
|---|
| 164 | procedure TCpu<TData,TAddr,TMax>.AddConstD(Reg: TRegIndex; Value: TData);
|
|---|
| 165 | begin
|
|---|
| 166 | WriteBytePC(Byte(inConstD));
|
|---|
| 167 | WriteRegPC(Reg);
|
|---|
| 168 | WriteDataPC(Value);
|
|---|
| 169 | end;
|
|---|
| 170 |
|
|---|
| 171 | procedure TCpu<TData, TAddr, TMax>.AddConstA(Reg: TRegIndex; Value: TAddr);
|
|---|
| 172 | begin
|
|---|
| 173 | WriteBytePC(Byte(inConstA));
|
|---|
| 174 | WriteRegPC(Reg);
|
|---|
| 175 | WriteAddrPC(Value);
|
|---|
| 176 | end;
|
|---|
| 177 |
|
|---|
| 178 | procedure TCpu<TData, TAddr, TMax>.AddConstN(Count: Byte; Reg: TRegIndex;
|
|---|
| 179 | Value: TMax);
|
|---|
| 180 | begin
|
|---|
| 181 | WriteBytePC(Byte(inConstN));
|
|---|
| 182 | WriteBytePc(Count);
|
|---|
| 183 | WriteRegPC(Reg);
|
|---|
| 184 | WritePC(Value, Count);
|
|---|
| 185 | end;
|
|---|
| 186 |
|
|---|
| 187 | procedure TCpu<TData, TAddr, TMax>.AddOutputD(Addr: TAddr; Reg: TRegIndex);
|
|---|
| 188 | begin
|
|---|
| 189 | WriteBytePC(Byte(inOutputD));
|
|---|
| 190 | WriteAddrPC(Addr);
|
|---|
| 191 | WriteRegPC(Reg);
|
|---|
| 192 | end;
|
|---|
| 193 |
|
|---|
| 194 | procedure TCpu<TData, TAddr, TMax>.AddOutputA(Addr: TAddr; Reg: TRegIndex);
|
|---|
| 195 | begin
|
|---|
| 196 | WriteBytePC(Byte(inOutputA));
|
|---|
| 197 | WriteAddrPC(Addr);
|
|---|
| 198 | WriteRegPC(Reg);
|
|---|
| 199 | end;
|
|---|
| 200 |
|
|---|
| 201 | procedure TCpu<TData, TAddr, TMax>.AddOutputN(Count: Byte; Addr: TAddr;
|
|---|
| 202 | Reg: TRegIndex);
|
|---|
| 203 | begin
|
|---|
| 204 | WriteBytePC(Byte(inOutputN));
|
|---|
| 205 | WriteBytePC(Count);
|
|---|
| 206 | WriteAddrPC(Addr);
|
|---|
| 207 | WriteRegPC(Reg);
|
|---|
| 208 | end;
|
|---|
| 209 |
|
|---|
| 210 | procedure TCpu<TData,TAddr,TMax>.AddHalt;
|
|---|
| 211 | begin
|
|---|
| 212 | WriteBytePC(Byte(inHalt));
|
|---|
| 213 | end;
|
|---|
| 214 |
|
|---|
| 215 | function TCpu<TData,TAddr,TMax>.ReadBytePC: Byte;
|
|---|
| 216 | begin
|
|---|
| 217 | Result := Memory[PC];
|
|---|
| 218 | Inc(PC);
|
|---|
| 219 | end;
|
|---|
| 220 |
|
|---|
| 221 | function TCpu<TData,TAddr,TMax>.ReadDataPC: TData;
|
|---|
| 222 | begin
|
|---|
| 223 | Result := PData(@Memory[PC])^;
|
|---|
| 224 | Inc(PC, SizeOf(TData));
|
|---|
| 225 | end;
|
|---|
| 226 |
|
|---|
| 227 | function TCpu<TData,TAddr,TMax>.ReadAddrPC: TAddr;
|
|---|
| 228 | begin
|
|---|
| 229 | Result := PAddr(@Memory[PC])^;
|
|---|
| 230 | Inc(PC, SizeOf(TAddr));
|
|---|
| 231 | end;
|
|---|
| 232 |
|
|---|
| 233 | function TCpu<TData, TAddr, TMax>.ReadPC(Count: Byte): TMax;
|
|---|
| 234 | begin
|
|---|
| 235 | Move(PMax(@Memory[PC])^, Result, Count);
|
|---|
| 236 | Inc(PC, SizeOf(Count));
|
|---|
| 237 | end;
|
|---|
| 238 |
|
|---|
| 239 | function TCpu<TData,TAddr,TMax>.ReadData(Addr: TAddr): TData;
|
|---|
| 240 | begin
|
|---|
| 241 | Result := PData(@Memory[Addr])^;
|
|---|
| 242 | end;
|
|---|
| 243 |
|
|---|
| 244 | function TCpu<TData, TAddr, TMax>.ReadAddr(Addr: TAddr): TAddr;
|
|---|
| 245 | begin
|
|---|
| 246 | Result := PAddr(@Memory[Addr])^;
|
|---|
| 247 | end;
|
|---|
| 248 |
|
|---|
| 249 | function TCpu<TData, TAddr, TMax>.Read(Addr: TAddr; Count: Byte): TMax;
|
|---|
| 250 | begin
|
|---|
| 251 | Move(PMax(@Memory[Addr])^, Result, Count);
|
|---|
| 252 | end;
|
|---|
| 253 |
|
|---|
| 254 | function TCpu<TData, TAddr, TMax>.ReadRegData(Reg: TRegIndex): TData;
|
|---|
| 255 | begin
|
|---|
| 256 | Result := PData(@R[Reg])^;
|
|---|
| 257 | end;
|
|---|
| 258 |
|
|---|
| 259 | function TCpu<TData, TAddr, TMax>.ReadRegAddr(Reg: TRegIndex): TAddr;
|
|---|
| 260 | begin
|
|---|
| 261 | Result := PAddr(@R[Reg])^;
|
|---|
| 262 | end;
|
|---|
| 263 |
|
|---|
| 264 | function TCpu<TData, TAddr, TMax>.ReadReg(Reg: TRegIndex; Count: Byte): TMax;
|
|---|
| 265 | begin
|
|---|
| 266 | Move(PMax(@R[Reg])^, Result, Count);
|
|---|
| 267 | end;
|
|---|
| 268 |
|
|---|
| 269 | procedure TCpu<TData,TAddr,TMax>.WriteBytePC(Data: Byte);
|
|---|
| 270 | begin
|
|---|
| 271 | Memory[PC] := Data;
|
|---|
| 272 | Inc(PC);
|
|---|
| 273 | end;
|
|---|
| 274 |
|
|---|
| 275 | procedure TCpu<TData,TAddr,TMax>.WriteRegPC(Reg: TRegIndex);
|
|---|
| 276 | begin
|
|---|
| 277 | Memory[PC] := Reg;
|
|---|
| 278 | Inc(PC, SizeOf(Reg));
|
|---|
| 279 | end;
|
|---|
| 280 |
|
|---|
| 281 | procedure TCpu<TData,TAddr,TMax>.WriteDataPC(Data: TData);
|
|---|
| 282 | begin
|
|---|
| 283 | WriteData(PC, Data);
|
|---|
| 284 | Inc(PC, SizeOf(TData));
|
|---|
| 285 | end;
|
|---|
| 286 |
|
|---|
| 287 | procedure TCpu<TData,TAddr,TMax>.WriteAddrPC(Addr: TAddr);
|
|---|
| 288 | begin
|
|---|
| 289 | WriteAddr(PC, Addr);
|
|---|
| 290 | Inc(PC, SizeOf(TAddr));
|
|---|
| 291 | end;
|
|---|
| 292 |
|
|---|
| 293 | procedure TCpu<TData, TAddr, TMax>.WritePC(Value: TMax; Count: Byte);
|
|---|
| 294 | begin
|
|---|
| 295 | Move(Value, PMax(@Memory[PC])^, Count);
|
|---|
| 296 | Inc(PC, Count);
|
|---|
| 297 | end;
|
|---|
| 298 |
|
|---|
| 299 | procedure TCpu<TData,TAddr,TMax>.WriteData(Addr: TAddr; Value: TData);
|
|---|
| 300 | begin
|
|---|
| 301 | PData(@Memory[Addr])^ := Value;
|
|---|
| 302 | end;
|
|---|
| 303 |
|
|---|
| 304 | procedure TCpu<TData,TAddr,TMax>.WriteAddr(Addr, Value: TAddr);
|
|---|
| 305 | begin
|
|---|
| 306 | PAddr(@Memory[Addr])^ := Value;
|
|---|
| 307 | end;
|
|---|
| 308 |
|
|---|
| 309 | procedure TCpu<TData, TAddr, TMax>.WriteRegData(Reg: TRegIndex; Value: TData);
|
|---|
| 310 | begin
|
|---|
| 311 | PData(@R[Reg])^ := Value;
|
|---|
| 312 | end;
|
|---|
| 313 |
|
|---|
| 314 | procedure TCpu<TData, TAddr, TMax>.WriteRegAddr(Reg: TRegIndex; Value: TAddr);
|
|---|
| 315 | begin
|
|---|
| 316 | PAddr(@R[Reg])^ := Value;
|
|---|
| 317 | end;
|
|---|
| 318 |
|
|---|
| 319 | procedure TCpu<TData, TAddr, TMax>.WriteReg(Reg: TRegIndex; Value: TMax;
|
|---|
| 320 | Count: Byte);
|
|---|
| 321 | begin
|
|---|
| 322 | R[Reg] := 0;
|
|---|
| 323 | Move(Value, PMax(@R[Reg])^, Count);
|
|---|
| 324 | end;
|
|---|
| 325 |
|
|---|
| 326 | constructor TCpu<TData,TAddr,TMax>.Create;
|
|---|
| 327 | begin
|
|---|
| 328 | end;
|
|---|
| 329 |
|
|---|
| 330 | destructor TCpu<TData,TAddr,TMax>.Destroy;
|
|---|
| 331 | begin
|
|---|
| 332 | inherited;
|
|---|
| 333 | end;
|
|---|
| 334 |
|
|---|
| 335 | end.
|
|---|
| 336 |
|
|---|