- Timestamp:
- Jul 12, 2022, 10:43:40 PM (2 years ago)
- Location:
- branches/CpuSingleSize
- Files:
-
- 1 added
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/CpuSingleSize/CpuSingleSize.lpi
r220 r223 2 2 <CONFIG> 3 3 <ProjectOptions> 4 <Version Value="1 1"/>4 <Version Value="12"/> 5 5 <General> 6 <Flags> 7 <CompatibilityMode Value="True"/> 8 </Flags> 6 9 <SessionStorage Value="InProjectDir"/> 7 <MainUnit Value="0"/>8 10 <Title Value="CpuSingleSize"/> 9 11 <Scaled Value="True"/> … … 65 67 <RunParams> 66 68 <FormatVersion Value="2"/> 67 <Modes Count="0"/>68 69 </RunParams> 69 70 <RequiredPackages Count="2"> … … 75 76 </Item2> 76 77 </RequiredPackages> 77 <Units Count="2 0">78 <Units Count="21"> 78 79 <Unit0> 79 80 <Filename Value="CpuSingleSize.lpr"/> … … 189 190 <ResourceBaseClass Value="Form"/> 190 191 </Unit19> 192 <Unit20> 193 <Filename Value="Forms/UProject.pas"/> 194 <IsPartOfProject Value="True"/> 195 </Unit20> 191 196 </Units> 192 197 </ProjectOptions> -
branches/CpuSingleSize/CpuSingleSize.lpr
r220 r223 11 11 UFormCpu, UFormConsole, UFormAssembler, UCore, UFormDisassembler, 12 12 UDisassembler, UMemory, UFormMessages, UMessages, SysUtils, UFormHelp, 13 UParser, UFormDevices, UFormStorage ;13 UParser, UFormDevices, UFormStorage, UProject; 14 14 15 15 {$R *.res} -
branches/CpuSingleSize/Forms/UFormAssembler.lfm
r216 r223 9 9 DesignTimePPI = 144 10 10 OnShow = FormShow 11 LCLVersion = '2. 0.10.0'11 LCLVersion = '2.2.2.0' 12 12 inline SynEdit1: TSynEdit 13 13 Left = 16 … … 18 18 Color = clBlack 19 19 Font.Color = clWhite 20 Font.Height = 1 320 Font.Height = 16 21 21 Font.Name = 'Liberation Mono' 22 22 Font.Pitch = fpFixed … … 25 25 ParentFont = False 26 26 TabOrder = 0 27 Gutter.Width = 7727 Gutter.Width = 81 28 28 Gutter.MouseActions = <> 29 29 RightGutter.Width = 0 … … 481 481 end 482 482 object SynGutterLineNumber1: TSynGutterLineNumber 483 Width = 17483 Width = 21 484 484 MouseActions = <> 485 485 MarkupInfo.Background = clBtnFace -
branches/CpuSingleSize/Forms/UFormAssembler.pas
r216 r223 1 1 unit UFormAssembler; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/Forms/UFormConsole.pas
r220 r223 1 1 unit UFormConsole; 2 3 {$mode delphi}4 2 5 3 interface … … 24 22 procedure SetDevice(AValue: TDevice); override; 25 23 public 26 Console: T Console;24 Console: TDeviceConsole; 27 25 end; 28 26 … … 63 61 procedure TFormConsole.SetDevice(AValue: TDevice); 64 62 begin 65 if AValue is T Console then66 Console := T Console(AValue);63 if AValue is TDeviceConsole then 64 Console := TDeviceConsole(AValue); 67 65 end; 68 66 … … 75 73 Console.Lock.Release; 76 74 end; 77 Console. Cpu.Interrupt(Console.InterruptVector);75 Console.PulseInterrupt; 78 76 end; 79 77 -
branches/CpuSingleSize/Forms/UFormCpu.pas
r216 r223 1 1 unit UFormCpu; 2 3 {$mode delphi}4 2 5 3 interface … … 49 47 I: Integer; 50 48 begin 51 if Item.Index * DataPerLine < Length(Cpu. Data) then begin49 if Item.Index * DataPerLine < Length(Cpu.Memory) then begin 52 50 Item.Caption := IntToHex(Item.Index * DataPerLine, 8); 53 51 Line := ''; 54 52 for I := 0 to DataPerLine - 1 do 55 Line := Line + IntToHex(Cpu. Data[Item.Index * DataPerLine + I], 4) + ' ';53 Line := Line + IntToHex(Cpu.Memory[Item.Index * DataPerLine + I], 4) + ' '; 56 54 Item.SubItems.Add(Line); 57 55 end; … … 63 61 if Item.Index = 0 then begin 64 62 Item.Caption := 'IP'; 65 Item.SubItems.Add(IntToHex(Cpu.I P, 8));63 Item.SubItems.Add(IntToHex(Cpu.InstructionPointer, 8)); 66 64 end else 67 65 if Item.Index = 1 then begin 68 66 Item.Caption := 'SP'; 69 Item.SubItems.Add(IntToHex(Cpu.S P, 8));67 Item.SubItems.Add(IntToHex(Cpu.StackPointer, 8)); 70 68 end else begin 71 69 Item.Caption := 'R' + IntToStr(Item.Index - 2); … … 77 75 procedure TFormCpu.Timer1Timer(Sender: TObject); 78 76 begin 79 ListViewMemory.Items.Count := Length(Cpu. Data) div DataPerLine;77 ListViewMemory.Items.Count := Length(Cpu.Memory) div DataPerLine; 80 78 ListViewMemory.Refresh; 81 79 ListViewRegs.Items.Count := Length(Cpu.R) + 2; -
branches/CpuSingleSize/Forms/UFormDevices.lfm
r220 r223 9 9 DesignTimePPI = 144 10 10 OnShow = FormShow 11 LCLVersion = '2. 0.10.0'11 LCLVersion = '2.2.2.0' 12 12 object TreeView1: TTreeView 13 13 Left = 16 -
branches/CpuSingleSize/Forms/UFormDevices.pas
r220 r223 1 1 unit UFormDevices; 2 3 {$mode delphi}4 2 5 3 interface 6 4 7 5 uses 8 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, UMachine; 6 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls, 7 UMachine; 9 8 10 9 type … … 35 34 const 36 35 DeviceClassFormClasses: array[TDeviceClass] of TFormDeviceClass = ( 37 nil, nil, nil, TFormStorage, TFormScreen, TFormConsole );36 nil, nil, nil, TFormStorage, TFormScreen, TFormConsole, nil); 38 37 39 38 { TFormDevices } … … 55 54 FormClass := DeviceClassFormClasses[Device.DeviceClass]; 56 55 if Assigned(FormClass) then begin 57 Device.Form := TFormDevice(FormClass.Create(nil));56 Device.Form := FormClass.Create(nil); 58 57 Device.Form.Device := Device; 59 58 Device.Form.Show; -
branches/CpuSingleSize/Forms/UFormDisassembler.pas
r216 r223 1 1 unit UFormDisassembler; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/Forms/UFormHelp.pas
r216 r223 1 1 unit UFormHelp; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/Forms/UFormMain.lfm
r220 r223 12 12 OnDestroy = FormDestroy 13 13 OnShow = FormShow 14 LCLVersion = '2. 0.10.0'14 LCLVersion = '2.2.2.0' 15 15 object ButtonLoad: TButton 16 16 Left = 24 -
branches/CpuSingleSize/Forms/UFormMain.pas
r220 r223 1 1 unit UFormMain; 2 3 {$mode delphi}{$H+}4 2 5 3 interface -
branches/CpuSingleSize/Forms/UFormMessages.lfm
r217 r223 8 8 ClientWidth = 1113 9 9 DesignTimePPI = 144 10 LCLVersion = '2. 0.10.0'10 LCLVersion = '2.2.2.0' 11 11 object ListView1: TListView 12 12 Left = 0 -
branches/CpuSingleSize/Forms/UFormMessages.pas
r217 r223 1 1 unit UFormMessages; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/Forms/UFormScreen.lfm
r216 r223 10 10 OnCreate = FormCreate 11 11 OnDestroy = FormDestroy 12 LCLVersion = '2. 0.10.0'12 LCLVersion = '2.2.2.0' 13 13 object PaintBox1: TPaintBox 14 14 Left = 8 -
branches/CpuSingleSize/Forms/UFormScreen.pas
r220 r223 1 1 unit UFormScreen; 2 3 {$mode delphi}4 2 5 3 interface … … 25 23 procedure SetDevice(AValue: TDevice); override; 26 24 public 27 Screen: T Screen;25 Screen: TDeviceScreen; 28 26 end; 29 27 … … 65 63 procedure TFormScreen.SetDevice(AValue: TDevice); 66 64 begin 67 if AValue is T Screen then68 Screen := T Screen(AValue);65 if AValue is TDeviceScreen then 66 Screen := TDeviceScreen(AValue); 69 67 end; 70 68 -
branches/CpuSingleSize/Forms/UFormStorage.lfm
r220 r223 8 8 ClientWidth = 1153 9 9 DesignTimePPI = 144 10 LCLVersion = '2. 0.10.0'10 LCLVersion = '2.2.2.0' 11 11 object ListView1: TListView 12 12 Left = 17 -
branches/CpuSingleSize/Forms/UFormStorage.pas
r220 r223 1 1 unit UFormStorage; 2 3 {$mode delphi}4 2 5 3 interface … … 18 16 procedure SetDevice(AValue: TDevice); override; 19 17 public 20 Storage: T Storage;18 Storage: TDeviceStorage; 21 19 end; 22 20 … … 37 35 procedure TFormStorage.SetDevice(AValue: TDevice); 38 36 begin 39 if AValue is T Storage then40 Storage := T Storage(AValue);37 if AValue is TDeviceStorage then 38 Storage := TDeviceStorage(AValue); 41 39 end; 42 40 -
branches/CpuSingleSize/UAssembler.pas
r220 r223 1 1 unit UAssembler; 2 3 {$mode delphi}4 2 5 3 interface … … 142 140 TokenValue := Parser.ReadNext; 143 141 if TokenValue.Kind = tkNumber then begin 144 if not Labels.ContainsKey(TokenName.Value) then begin142 if not Labels.ContainsKey(TokenName.Value) and not Variables.ContainsKey(TokenName.Value) then begin 145 143 if TryStrToInt(TokenValue.Value, Number) then 146 144 Variables.Add(TokenName.Value, Number) -
branches/CpuSingleSize/UCore.pas
r220 r223 1 1 unit UCore; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/UCpu.pas
r220 r223 1 1 unit UCpu; 2 3 {$mode delphi}4 2 5 3 interface … … 12 10 inAdd, inSub, inIn, inOut, inJump, inJumpZero, inJumpNotZero, inPush, inPop, 13 11 inCall, inRet, inAnd, inOr, inXor, inShl, inShr, inMul, inDiv, inMod, 14 inJumpRel, inLoadIndex, inStoreIndex );12 inJumpRel, inLoadIndex, inStoreIndex, inLoadCpu, inStoreCpu, inEi, inDi); 15 13 16 14 TInteger = Integer; … … 20 18 TInputEvent = function (Device, Port: TInteger): TInteger of object; 21 19 20 { TCpuStatus } 21 22 TCpuStatus = packed record 23 InterruptEnabled: Boolean; 24 UserMode: Boolean; 25 UserModeWasActive: Boolean; 26 function GetInteger: TInteger; 27 procedure SetInteger(Value: TInteger); 28 end; 29 30 TIntegerArray = array of TInteger; 31 32 TMemoryBlock = record 33 Base: TIntegerArray; 34 Size: TInteger; 35 end; 36 37 TMemoryBlockIndex = (mbCode, mbData, mbStack, mbInterrupt); 38 TInstructionHandler = procedure of object; 39 TSystemInterrupt = (siReset, siUserIn, siUserOut, siUserInvalidMemory, 40 siPrivilegedInstruction); 41 TCpuRegister = (crIP, crSP, crStatusRegister, crUserMemoryBase, crUserMemorySize); 42 22 43 { TCpu } 23 44 24 45 TCpu = class 25 46 private 47 FBaseMemory: TMemoryBlock; 48 FUserMemory: TMemoryBlock; 49 FMemory: TMemoryBlock; 26 50 FRunning: Boolean; 27 51 FThread: TCpuThread; … … 30 54 FNextInterupt: TInteger; 31 55 FHalted: Boolean; 56 FTicks: Integer; 57 FInstructionHandlers: array[TInstruction] of TInstructionHandler; 58 function GetMemory: TIntegerArray; 59 procedure InstructionNop; 60 procedure InstructionHalt; 61 procedure InstructionSet; 62 procedure InstructionCopy; 63 procedure InstructionLoad; 64 procedure InstructionStore; 65 procedure InstructionInc; 66 procedure InstructionDec; 67 procedure InstructionAdd; 68 procedure InstructionSub; 69 procedure InstructionIn; 70 procedure InstructionOut; 71 procedure InstructionJump; 72 procedure InstructionJumpRel; 73 procedure InstructionJumpZero; 74 procedure InstructionJumpNotZero; 75 procedure InstructionPush; 76 procedure InstructionPop; 77 procedure InstructionCall; 78 procedure InstructionRet; 79 procedure InstructionReti; 80 procedure InstructionAnd; 81 procedure InstructionOr; 82 procedure InstructionXor; 83 procedure InstructionShl; 84 procedure InstructionShr; 85 procedure InstructionMod; 86 procedure InstructionDiv; 87 procedure InstructionMul; 88 procedure InstructionLoadIndex; 89 procedure InstructionStoreIndex; 90 procedure InstructionLoadCpu; 91 procedure InstructionStoreCpu; 92 procedure InstructionEi; 93 procedure InstructionDi; 94 procedure SetMemory(AValue: TIntegerArray); 32 95 procedure SetRunning(AValue: Boolean); 33 96 procedure CheckInterreupts; 97 procedure Push(Value: TInteger); 98 function Pop: TInteger; 99 procedure StoreContext; 100 procedure LoadContext; 101 procedure InitInstructions; 102 procedure ActivateUserMode; 103 procedure DeactivateUserMode; 34 104 public 35 Ticks: Integer; 36 IP: TInteger; 37 SP: TInteger; 38 Data: array of TInteger; 105 InstructionPointer: TInteger; // Instruction Pointer 106 StackPointer: TInteger; // Stack Pointer 107 StatusRegister: TCpuStatus; // Status Register 39 108 R: array of TInteger; 40 109 function ReadNext: TInteger; … … 44 113 procedure Stop; 45 114 procedure Reset; 46 procedure Interrupt(Index: TInteger); 115 procedure Interrupt(Index: TSystemInterrupt); overload; 116 procedure Interrupt(Index: TInteger); overload; 47 117 constructor Create; 48 118 destructor Destroy; override; 119 property Ticks: Integer read FTicks; 120 property Memory: TIntegerArray read GetMemory write SetMemory; 49 121 property OnInput: TInputEvent read FOnInput write FOnInput; 50 122 property OnOutput: TOutputEvent read FOnOutput write FOnOutput; … … 62 134 63 135 implementation 136 137 { TCpuStatus } 138 139 function TCpuStatus.GetInteger: TInteger; 140 begin 141 142 end; 143 144 procedure TCpuStatus.SetInteger(Value: TInteger); 145 begin 146 147 end; 64 148 65 149 { TCpuThread } … … 83 167 end; 84 168 169 procedure TCpu.InstructionNop; 170 begin 171 // No operation 172 end; 173 174 function TCpu.GetMemory: TIntegerArray; 175 begin 176 Result := FBaseMemory.Base; 177 end; 178 179 procedure TCpu.InstructionHalt; 180 begin 181 FHalted := True; 182 end; 183 184 procedure TCpu.InstructionSet; 185 begin 186 R[ReadNext] := ReadNext; 187 end; 188 189 procedure TCpu.InstructionCopy; 190 begin 191 R[ReadNext] := R[ReadNext]; 192 end; 193 194 procedure TCpu.InstructionLoad; 195 begin 196 R[ReadNext] := FMemory.Base[R[ReadNext]]; 197 end; 198 199 procedure TCpu.InstructionStore; 200 begin 201 FMemory.Base[R[ReadNext]] := R[ReadNext]; 202 end; 203 204 procedure TCpu.InstructionInc; 205 begin 206 Inc(R[ReadNext]); 207 end; 208 209 procedure TCpu.InstructionDec; 210 begin 211 Dec(R[ReadNext]); 212 end; 213 214 procedure TCpu.InstructionAdd; 215 var 216 Index: TInteger; 217 begin 218 Index := ReadNext; 219 R[Index] := R[Index] + R[ReadNext]; 220 end; 221 222 procedure TCpu.InstructionSub; 223 var 224 Index: TInteger; 225 begin 226 Index := ReadNext; 227 R[Index] := R[Index] - R[ReadNext]; 228 end; 229 230 procedure TCpu.InstructionIn; 231 var 232 Index: TInteger; 233 Device: TInteger; 234 Port: TInteger; 235 begin 236 Index := ReadNext; 237 Device := R[ReadNext]; 238 Port := R[ReadNext]; 239 if StatusRegister.UserMode then begin 240 Interrupt(siUserIn); 241 end else begin 242 if Assigned(FOnInput) then R[Index] := FOnInput(Device, Port); 243 end; 244 end; 245 246 procedure TCpu.InstructionOut; 247 var 248 Device: TInteger; 249 Port: TInteger; 250 Index: TInteger; 251 begin 252 Device := R[ReadNext]; 253 Port := R[ReadNext]; 254 Index := ReadNext; 255 if StatusRegister.UserMode then begin 256 Interrupt(siUserOut); 257 end else begin 258 if Assigned(FOnOutput) then FOnOutput(Device, Port, R[Index]); 259 end; 260 end; 261 262 procedure TCpu.InstructionJump; 263 begin 264 InstructionPointer := ReadNext; 265 end; 266 267 procedure TCpu.InstructionJumpRel; 268 begin 269 InstructionPointer := InstructionPointer + ReadNext; 270 end; 271 272 procedure TCpu.InstructionJumpZero; 273 var 274 Index: TInteger; 275 Address: TInteger; 276 begin 277 Index := ReadNext; 278 Address := ReadNext; 279 if R[Index] = 0 then InstructionPointer := Address; 280 end; 281 282 procedure TCpu.InstructionJumpNotZero; 283 var 284 Index: TInteger; 285 Address: TInteger; 286 begin 287 Index := ReadNext; 288 Address := ReadNext; 289 if R[Index] <> 0 then InstructionPointer := Address; 290 end; 291 292 procedure TCpu.InstructionPush; 293 begin 294 Push(R[ReadNext]); 295 end; 296 297 procedure TCpu.InstructionPop; 298 begin 299 R[ReadNext] := Pop; 300 end; 301 302 procedure TCpu.InstructionCall; 303 var 304 Address: TInteger; 305 begin 306 Address := ReadNext; 307 Push(InstructionPointer); 308 InstructionPointer := Address; 309 end; 310 311 procedure TCpu.InstructionRet; 312 begin 313 InstructionPointer := Pop; 314 end; 315 316 procedure TCpu.InstructionReti; 317 begin 318 if StatusRegister.UserMode then begin 319 Interrupt(siPrivilegedInstruction); 320 Exit; 321 end; 322 if StatusRegister.UserModeWasActive then ActivateUserMode; 323 StatusRegister.InterruptEnabled := True; 324 InstructionPointer := Pop; 325 end; 326 327 procedure TCpu.InstructionAnd; 328 var 329 Index: TInteger; 330 begin 331 Index := ReadNext; 332 R[Index] := R[Index] and R[ReadNext]; 333 end; 334 335 procedure TCpu.InstructionOr; 336 var 337 Index: TInteger; 338 begin 339 Index := ReadNext; 340 R[Index] := R[Index] or R[ReadNext]; 341 end; 342 343 procedure TCpu.InstructionXor; 344 var 345 Index: TInteger; 346 begin 347 Index := ReadNext; 348 R[Index] := R[Index] xor R[ReadNext]; 349 end; 350 351 procedure TCpu.InstructionShl; 352 var 353 Index: TInteger; 354 begin 355 Index := ReadNext; 356 R[Index] := R[Index] shl R[ReadNext]; 357 end; 358 359 procedure TCpu.InstructionShr; 360 var 361 Index: TInteger; 362 begin 363 Index := ReadNext; 364 R[Index] := R[Index] shr R[ReadNext]; 365 end; 366 367 procedure TCpu.InstructionMod; 368 var 369 Index: TInteger; 370 begin 371 Index := ReadNext; 372 R[Index] := R[Index] mod R[ReadNext]; 373 end; 374 375 procedure TCpu.InstructionDiv; 376 var 377 Index: TInteger; 378 begin 379 Index := ReadNext; 380 R[Index] := R[Index] div R[ReadNext]; 381 end; 382 383 procedure TCpu.InstructionMul; 384 var 385 Index: TInteger; 386 begin 387 Index := ReadNext; 388 R[Index] := R[Index] * R[ReadNext]; 389 end; 390 391 procedure TCpu.InstructionLoadIndex; 392 begin 393 R[ReadNext] := FMemory.Base[R[ReadNext] + ReadNext]; 394 end; 395 396 procedure TCpu.InstructionStoreIndex; 397 begin 398 FMemory.Base[R[ReadNext] + ReadNext] := R[ReadNext]; 399 end; 400 401 procedure TCpu.InstructionLoadCpu; 402 var 403 Index: TInteger; 404 I: TInteger; 405 begin 406 R[ReadNext] := FMemory.Base[R[ReadNext]]; 407 Index := ReadNext; 408 I := ReadNext; 409 case TCpuRegister(I) of 410 crIP: R[Index] := InstructionPointer; 411 crSP: R[Index] := StackPointer; 412 crStatusRegister: R[Index] := StatusRegister.GetInteger; 413 crUserMemoryBase: R[Index] := Pointer(FUserMemory.Base) - Pointer(FBaseMemory.Base); 414 crUserMemorySize: R[Index] := FUserMemory.Size; 415 end; 416 end; 417 418 procedure TCpu.InstructionStoreCpu; 419 var 420 Index: TInteger; 421 I: TInteger; 422 begin 423 if StatusRegister.UserMode then begin 424 Interrupt(siPrivilegedInstruction); 425 Exit; 426 end; 427 R[ReadNext] := FMemory.Base[R[ReadNext]]; 428 Index := ReadNext; 429 I := ReadNext; 430 case TCpuRegister(I) of 431 crIP: InstructionPointer := R[Index]; 432 crSP: StackPointer := R[Index]; 433 crStatusRegister: StatusRegister.SetInteger(R[Index]); 434 crUserMemoryBase: FUserMemory.Base := Pointer(FBaseMemory.Base) + R[Index]; 435 crUserMemorySize: FUserMemory.Size := R[Index]; 436 end; 437 end; 438 439 procedure TCpu.InstructionEi; 440 begin 441 if StatusRegister.UserMode then begin 442 Interrupt(siPrivilegedInstruction); 443 Exit; 444 end; 445 StatusRegister.InterruptEnabled := True; 446 end; 447 448 procedure TCpu.InstructionDi; 449 begin 450 if StatusRegister.UserMode then begin 451 Interrupt(siPrivilegedInstruction); 452 Exit; 453 end; 454 StatusRegister.InterruptEnabled := False; 455 end; 456 457 procedure TCpu.SetMemory(AValue: TIntegerArray); 458 begin 459 if (FBaseMemory.Base = AValue) and (FBaseMemory.Size = Length(AValue)) then Exit; 460 FBaseMemory.Base := AValue; 461 FBaseMemory.Size := Length(AValue); 462 end; 463 85 464 procedure TCpu.CheckInterreupts; 86 465 begin 87 if FNextInterupt <> -1 then begin 88 Dec(SP); 89 Data[SP] := IP; 90 IP := Data[FNextInterupt]; 466 if StatusRegister.InterruptEnabled and (FNextInterupt <> -1) then begin 467 Push(InstructionPointer); 468 if StatusRegister.UserMode then DeactivateUserMode; 469 InstructionPointer := FMemory.Base[FNextInterupt]; 470 StatusRegister.InterruptEnabled := False; 91 471 FNextInterupt := -1; 92 472 FHalted := False; … … 94 474 end; 95 475 476 procedure TCpu.Push(Value: TInteger); 477 begin 478 Dec(StackPointer); 479 FMemory.Base[StackPointer] := Value; 480 end; 481 482 function TCpu.Pop: TInteger; 483 begin 484 Result := FMemory.Base[StackPointer]; 485 Inc(StackPointer); 486 end; 487 488 procedure TCpu.StoreContext; 489 var 490 I: Integer; 491 begin 492 for I := 0 to Length(R) - 1 do 493 Push(R[I]); 494 end; 495 496 procedure TCpu.LoadContext; 497 var 498 I: Integer; 499 begin 500 for I := Length(R) - 1 downto 0 do 501 R[I] := Pop; 502 end; 503 504 procedure TCpu.InitInstructions; 505 begin 506 FInstructionHandlers[inNop] := InstructionNop; 507 FInstructionHandlers[inHalt] := InstructionHalt; 508 FInstructionHandlers[inSet] := InstructionSet; 509 FInstructionHandlers[inCopy] := InstructionCopy; 510 FInstructionHandlers[inLoad] := InstructionLoad; 511 FInstructionHandlers[inStore] := InstructionStore; 512 FInstructionHandlers[inInc] := InstructionInc; 513 FInstructionHandlers[inDec] := InstructionDec; 514 FInstructionHandlers[inAdd] := InstructionAdd; 515 FInstructionHandlers[inSub] := InstructionSub; 516 FInstructionHandlers[inIn] := InstructionIn; 517 FInstructionHandlers[inOut] := InstructionOut; 518 FInstructionHandlers[inJump] := InstructionJump; 519 FInstructionHandlers[inJumpRel] := InstructionJumpRel; 520 FInstructionHandlers[inJumpZero] := InstructionJumpZero; 521 FInstructionHandlers[inJumpNotZero] := InstructionJumpNotZero; 522 FInstructionHandlers[inPush] := InstructionPush; 523 FInstructionHandlers[inPop] := InstructionPop; 524 FInstructionHandlers[inCall] := InstructionCall; 525 FInstructionHandlers[inRet] := InstructionRet; 526 FInstructionHandlers[inAnd] := InstructionAnd; 527 FInstructionHandlers[inOr] := InstructionOr; 528 FInstructionHandlers[inXor] := InstructionXor; 529 FInstructionHandlers[inShl] := InstructionShl; 530 FInstructionHandlers[inShr] := InstructionShr; 531 FInstructionHandlers[inMul] := InstructionMul; 532 FInstructionHandlers[inDiv] := InstructionDiv; 533 FInstructionHandlers[inMod] := InstructionMod; 534 FInstructionHandlers[inLoadIndex] := InstructionLoadIndex; 535 FInstructionHandlers[inStoreIndex] := InstructionStoreIndex; 536 FInstructionHandlers[inLoadCpu] := InstructionLoadCpu; 537 FInstructionHandlers[inStoreCpu] := InstructionStoreCpu; 538 FInstructionHandlers[inEi] := InstructionEi; 539 FInstructionHandlers[inDi] := InstructionDi; 540 end; 541 542 procedure TCpu.ActivateUserMode; 543 begin 544 StatusRegister.UserMode := True; 545 FMemory := FUserMemory; 546 end; 547 548 procedure TCpu.DeactivateUserMode; 549 begin 550 FMemory := FBaseMemory; 551 StatusRegister.UserModeWasActive := StatusRegister.UserMode; 552 StatusRegister.UserMode := False; 553 end; 554 96 555 function TCpu.ReadNext: TInteger; 97 556 begin 98 if I P >= Length(Data) then IP:= 0;99 Result := Data[IP];100 Inc(I P);557 if InstructionPointer >= FMemory.Size then InstructionPointer := 0; 558 Result := FMemory.Base[InstructionPointer]; 559 Inc(InstructionPointer); 101 560 end; 102 561 103 562 procedure TCpu.WriteNext(Value: TInteger); 104 563 begin 105 if I P >= Length(Data) then IP:= 0;106 Data[IP] := Value;107 Inc(I P);564 if InstructionPointer >= FMemory.Size then InstructionPointer := 0; 565 FMemory.Base[InstructionPointer] := Value; 566 Inc(InstructionPointer); 108 567 end; 109 568 … … 111 570 var 112 571 Instruction: TInstruction; 113 Address: TInteger;114 Index: TInteger;115 Port: TInteger;116 Dest: TInteger;117 Device: TInteger;118 572 begin 119 573 Instruction := TInstruction(ReadNext); 120 case Instruction of 121 inNop: ; 122 inHalt: FHalted := True; 123 inSet: R[ReadNext] := ReadNext; 124 inCopy: R[ReadNext] := R[ReadNext]; 125 inLoad: R[ReadNext] := Data[R[ReadNext]]; 126 inStore: Data[R[ReadNext]] := R[ReadNext]; 127 inInc: Inc(R[ReadNext]); 128 inDec: Dec(R[ReadNext]); 129 inAdd: begin 130 Index := ReadNext; 131 R[Index] := R[Index] + R[ReadNext]; 132 end; 133 inSub: begin 134 Index := ReadNext; 135 R[Index] := R[Index] - R[ReadNext]; 136 end; 137 inIn: begin 138 Index := ReadNext; 139 Device := R[ReadNext]; 140 Port := R[ReadNext]; 141 if Assigned(FOnInput) then R[Index] := FOnInput(Device, Port); 142 end; 143 inOut: begin 144 Device := R[ReadNext]; 145 Port := R[ReadNext]; 146 if Assigned(FOnOutput) then FOnOutput(Device, Port, R[ReadNext]); 147 end; 148 inJump: IP := ReadNext; 149 inJumpRel: begin 150 Address := ReadNext; 151 IP := IP + Address; 152 end; 153 inJumpZero: begin 154 Index := ReadNext; 155 Address := ReadNext; 156 if R[Index] = 0 then IP := Address; 157 end; 158 inJumpNotZero: begin 159 Index := ReadNext; 160 Address := ReadNext; 161 if R[Index] <> 0 then IP := Address; 162 end; 163 inPush: begin 164 Dec(SP); 165 Data[SP] := R[ReadNext]; 166 end; 167 inPop: begin 168 R[ReadNext] := Data[SP]; 169 Inc(SP); 170 end; 171 inCall: begin 172 Address := ReadNext; 173 Dec(SP); 174 Data[SP] := IP; 175 IP := Address; 176 end; 177 inRet: begin 178 IP := Data[SP]; 179 Inc(SP); 180 end; 181 inAnd: begin 182 Index := ReadNext; 183 R[Index] := R[Index] and R[ReadNext]; 184 end; 185 inOr: begin 186 Index := ReadNext; 187 R[Index] := R[Index] or R[ReadNext]; 188 end; 189 inXor: begin 190 Index := ReadNext; 191 R[Index] := R[Index] xor R[ReadNext]; 192 end; 193 inShl: begin 194 Index := ReadNext; 195 R[Index] := R[Index] shl R[ReadNext]; 196 end; 197 inShr: begin 198 Index := ReadNext; 199 R[Index] := R[Index] shr R[ReadNext]; 200 end; 201 inMul: begin 202 Index := ReadNext; 203 R[Index] := R[Index] * R[ReadNext]; 204 end; 205 inDiv: begin 206 Index := ReadNext; 207 R[Index] := R[Index] div R[ReadNext]; 208 end; 209 inMod: begin 210 Index := ReadNext; 211 R[Index] := R[Index] mod R[ReadNext]; 212 end; 213 inLoadIndex: R[ReadNext] := Data[R[ReadNext] + ReadNext]; 214 inStoreIndex: Data[R[ReadNext] + ReadNext] := R[ReadNext]; 215 end; 216 Inc(Ticks); 574 if Assigned(FInstructionHandlers[Instruction]) then 575 FInstructionHandlers[Instruction] 576 else raise Exception.Create('Missing handler for instruction ' + IntToStr(Integer(Instruction))); 577 Inc(FTicks); 217 578 end; 218 579 … … 243 604 I: Integer; 244 605 begin 606 FMemory := FBaseMemory; 245 607 FNextInterupt := -1; 246 608 FHalted := False; 247 Ticks := 0;248 I P := Data[0]; // Reset interrupt vector249 S P := Length(Data);609 FTicks := 0; 610 InstructionPointer := FMemory.Base[Integer(siReset)]; 611 StackPointer := FMemory.Size; 250 612 for I := 0 to Length(R) - 1 do 251 613 R[I] := 0; 252 614 end; 253 615 616 procedure TCpu.Interrupt(Index: TSystemInterrupt); 617 begin 618 Interrupt(TInteger(Index)); 619 end; 620 254 621 procedure TCpu.Interrupt(Index: TInteger); 255 622 begin … … 260 627 begin 261 628 SetLength(R, 16); 262 SetLength(Data, 0); 629 Memory := nil; 630 InitInstructions; 263 631 end; 264 632 -
branches/CpuSingleSize/UDisassembler.pas
r220 r223 1 1 unit UDisassembler; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/UInstructions.pas
r220 r223 1 1 unit UInstructions; 2 3 {$mode delphi}4 2 5 3 interface … … 102 100 AddNew(inJumpRel, 'JR', [ptNumber], 'Unconditional relative jump to defined address.'); 103 101 AddNew(inLoadIndex, 'LDI', [ptReg, ptRegIndirectIndex], 'Loads value from memory with numeric index to register.'); 104 AddNew(inStoreIndex, 'STI', [ptRegIndirectIndex, ptReg], 'Stores value from register to memory with numeric index .'); 102 AddNew(inStoreIndex, 'STI', [ptRegIndirectIndex, ptReg], 'Stores value from register to memory with numeric index.'); 103 AddNew(inLoadCpu, 'LDC', [], 'Loads value from system register.'); 104 AddNew(inStoreCpu, 'STC', [], 'Stores value to system register.'); 105 AddNew(inEi, 'EI', [], 'Enables interrupts.'); 106 AddNew(inDi, 'DI', [], 'Disables interrupts.'); 105 107 end; 106 108 -
branches/CpuSingleSize/UMachine.pas
r220 r223 1 1 unit UMachine; 2 3 {$mode delphi}4 2 5 3 interface … … 9 7 10 8 type 11 TDeviceClass = (dcNone, dcKeyboard, dcMouse, dcStorage, dcScreen, dcConsole); 9 TDeviceClass = (dcNone, dcKeyboard, dcMouse, dcStorage, dcScreen, dcConsole, 10 dcTimer); 12 11 TDeviceClassSet = set of TDeviceClass; 13 12 … … 35 34 InterruptVector: Integer; 36 35 Form: TFormDevice; 36 procedure PulseInterrupt; 37 37 procedure OutputHandler(Port, Data: TInteger); virtual; 38 38 function InputHandler(Port: TInteger): TInteger; virtual; … … 64 64 TConsoleOutputPort = (opConsoleWriteChar); 65 65 66 { T Console }67 68 T Console = class(TDevice)66 { TDeviceConsole } 67 68 TDeviceConsole = class(TDevice) 69 69 Lock: TCriticalSection; 70 70 InputBuffer: TQueue<TInteger>; … … 79 79 TScreenOutputPort = (opScreenSetAddr, opScreenWrite); 80 80 81 { T Screen }82 83 T Screen = class(TDevice)81 { TDeviceScreen } 82 83 TDeviceScreen = class(TDevice) 84 84 private 85 85 FSize: TPoint; … … 97 97 TKeyboardInputPort = (ipKeyboardRead); 98 98 99 { T Keyboard }100 101 T Keyboard = class(TDevice)99 { TDeviceKeyboard } 100 101 TDeviceKeyboard = class(TDevice) 102 102 constructor Create; 103 103 function ReadKey: TInteger; … … 108 108 TStorageOutputPort = (opStorageSetAddr, opStorageWrite); 109 109 110 { T Storage }111 112 T Storage = class(TDevice)110 { TDeviceStorage } 111 112 TDeviceStorage = class(TDevice) 113 113 public 114 114 F: TFileStream; … … 119 119 end; 120 120 121 { TMouse } 122 123 TMouse = class(TDevice) 124 constructor Create; 121 { TDeviceMouse } 122 123 TDeviceMouse = class(TDevice) 124 constructor Create; 125 end; 126 127 TTimerOutputPort = (opTimerSetInterval, opTimerSetEnabled); 128 { TDeviceTimer } 129 130 TDeviceTimer = class(TDevice) 131 Interval: Integer; 132 Enabled: Boolean; 133 constructor Create; 134 procedure OutputHandler(Port, Data: TInteger); override; 125 135 end; 126 136 … … 144 154 145 155 const 146 DeviceClassText: array[TDeviceClass] of string = ('None', 'Keyboard', 'Mouse', 'Storage', 'Screen', 'Console' );156 DeviceClassText: array[TDeviceClass] of string = ('None', 'Keyboard', 'Mouse', 'Storage', 'Screen', 'Console', 'Timer'); 147 157 148 158 149 159 implementation 160 161 { TDeviceTimer } 162 163 constructor TDeviceTimer.Create; 164 begin 165 DeviceClass := dcTimer; 166 end; 167 168 procedure TDeviceTimer.OutputHandler(Port, Data: TInteger); 169 begin 170 case TTimerOutputPort(Port) of 171 opTimerSetInterval: Interval := Data; 172 opTimerSetEnabled: Enabled := Data > 0; 173 end; 174 end; 150 175 151 176 { TDeviceManager } … … 225 250 { TDevice } 226 251 252 procedure TDevice.PulseInterrupt; 253 begin 254 Cpu.Interrupt(InterruptVector); 255 end; 256 227 257 procedure TDevice.OutputHandler(Port, Data: TInteger); 228 258 begin … … 234 264 end; 235 265 236 { T Mouse }237 238 constructor T Mouse.Create;266 { TDeviceMouse } 267 268 constructor TDeviceMouse.Create; 239 269 begin 240 270 DeviceClass := dcMouse; 241 271 end; 242 272 243 { T Storage }244 245 constructor T Storage.Create;273 { TDeviceStorage } 274 275 constructor TDeviceStorage.Create; 246 276 begin 247 277 DeviceClass := dcStorage; 248 278 end; 249 279 250 procedure T Storage.OutputHandler(Port, Data: TInteger);280 procedure TDeviceStorage.OutputHandler(Port, Data: TInteger); 251 281 begin 252 282 case TStorageOutputPort(Port) of … … 258 288 end; 259 289 260 function T Storage.InputHandler(Port: TInteger): TInteger;290 function TDeviceStorage.InputHandler(Port: TInteger): TInteger; 261 291 begin 262 292 case TStorageInputPort(Port) of … … 268 298 end; 269 299 270 { T Console }271 272 constructor T Console.Create;300 { TDeviceConsole } 301 302 constructor TDeviceConsole.Create; 273 303 begin 274 304 DeviceClass := dcConsole; … … 278 308 end; 279 309 280 destructor T Console.Destroy;310 destructor TDeviceConsole.Destroy; 281 311 begin 282 312 InputBuffer.Free; … … 286 316 end; 287 317 288 procedure T Console.OutputHandler(Port, Data: TInteger);318 procedure TDeviceConsole.OutputHandler(Port, Data: TInteger); 289 319 begin 290 320 case TConsoleOutputPort(Port) of … … 300 330 end; 301 331 302 function T Console.InputHandler(Port: TInteger): TInteger;332 function TDeviceConsole.InputHandler(Port: TInteger): TInteger; 303 333 begin 304 334 case TConsoleInputPort(Port) of … … 324 354 end; 325 355 326 { T Screen }327 328 procedure T Screen.SetSize(AValue: TPoint);356 { TDeviceScreen } 357 358 procedure TDeviceScreen.SetSize(AValue: TPoint); 329 359 begin 330 360 if FSize = AValue then Exit; … … 333 363 end; 334 364 335 constructor T Screen.Create;365 constructor TDeviceScreen.Create; 336 366 begin 337 367 DeviceClass := dcScreen; … … 339 369 end; 340 370 341 procedure T Screen.OutputHandler(Port, Data: TInteger);371 procedure TDeviceScreen.OutputHandler(Port, Data: TInteger); 342 372 begin 343 373 case TScreenOutputPort(Port) of … … 351 381 end; 352 382 353 function T Screen.InputHandler(Port: TInteger): TInteger;383 function TDeviceScreen.InputHandler(Port: TInteger): TInteger; 354 384 begin 355 385 case TScreenInputPort(Port) of … … 359 389 end; 360 390 361 { T Keyboard }362 363 function T Keyboard.ReadKey: TInteger;391 { TDeviceKeyboard } 392 393 function TDeviceKeyboard.ReadKey: TInteger; 364 394 begin 365 395 Result := 0; 366 396 end; 367 397 368 function T Keyboard.InputHandler(Port: TInteger): TInteger;398 function TDeviceKeyboard.InputHandler(Port: TInteger): TInteger; 369 399 begin 370 400 case TKeyboardInputPort(Port) of … … 373 403 end; 374 404 375 constructor T Keyboard.Create;405 constructor TDeviceKeyboard.Create; 376 406 begin 377 407 DeviceClass := dcKeyboard; … … 404 434 procedure TMachine.InitDevices; 405 435 var 406 Screen: T Screen;407 Keyboard: T Keyboard;408 Console: T Console;409 Storage: T Storage;410 Mouse: T Mouse;436 Screen: TDeviceScreen; 437 Keyboard: TDeviceKeyboard; 438 Console: TDeviceConsole; 439 Storage: TDeviceStorage; 440 Mouse: TDeviceMouse; 411 441 DeviceManager: TDeviceManager; 442 Timer: TDeviceTimer; 412 443 begin 413 444 DeviceManager := TDeviceManager.Create; … … 415 446 RegisterDevice(DeviceManager); 416 447 417 Console := T Console.Create;448 Console := TDeviceConsole.Create; 418 449 RegisterDevice(Console); 419 450 Console.InterruptVector := 1; 420 451 421 Keyboard := TKeyboard.Create; 452 Keyboard := TDeviceKeyboard.Create; 453 Keyboard.InterruptVector := 4; 422 454 RegisterDevice(Keyboard); 423 455 424 Screen := T Screen.Create;456 Screen := TDeviceScreen.Create; 425 457 RegisterDevice(Screen); 426 458 427 Storage := T Storage.Create;459 Storage := TDeviceStorage.Create; 428 460 RegisterDevice(Storage); 429 461 430 Storage := T Storage.Create;462 Storage := TDeviceStorage.Create; 431 463 RegisterDevice(Storage); 432 464 433 Mouse := TMouse.Create; 465 Mouse := TDeviceMouse.Create; 466 Mouse.InterruptVector := 3; 434 467 RegisterDevice(Mouse); 468 469 Timer := TDeviceTimer.Create; 470 Timer.InterruptVector := 2; 471 RegisterDevice(Timer); 435 472 end; 436 473 437 474 procedure TMachine.PowerOn; 438 475 begin 439 Cpu. Data:= Memory.Data;476 Cpu.Memory := Memory.Data; 440 477 Cpu.Start; 441 478 end; -
branches/CpuSingleSize/UMemory.pas
r217 r223 1 1 unit UMemory; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/UMessages.pas
r216 r223 1 1 unit UMessages; 2 3 {$mode delphi}4 2 5 3 interface -
branches/CpuSingleSize/UParser.pas
r219 r223 1 1 unit UParser; 2 3 {$mode delphi}4 2 5 3 interface
Note:
See TracChangeset
for help on using the changeset viewer.