Changeset 223


Ignore:
Timestamp:
Jul 12, 2022, 10:43:40 PM (22 months ago)
Author:
chronos
Message:
  • Modified: More instructions.
  • Modified: Optimized instruction execution with procedure array instead case.
Location:
branches/CpuSingleSize
Files:
1 added
27 edited

Legend:

Unmodified
Added
Removed
  • branches/CpuSingleSize/CpuSingleSize.lpi

    r220 r223  
    22<CONFIG>
    33  <ProjectOptions>
    4     <Version Value="11"/>
     4    <Version Value="12"/>
    55    <General>
     6      <Flags>
     7        <CompatibilityMode Value="True"/>
     8      </Flags>
    69      <SessionStorage Value="InProjectDir"/>
    7       <MainUnit Value="0"/>
    810      <Title Value="CpuSingleSize"/>
    911      <Scaled Value="True"/>
     
    6567    <RunParams>
    6668      <FormatVersion Value="2"/>
    67       <Modes Count="0"/>
    6869    </RunParams>
    6970    <RequiredPackages Count="2">
     
    7576      </Item2>
    7677    </RequiredPackages>
    77     <Units Count="20">
     78    <Units Count="21">
    7879      <Unit0>
    7980        <Filename Value="CpuSingleSize.lpr"/>
     
    189190        <ResourceBaseClass Value="Form"/>
    190191      </Unit19>
     192      <Unit20>
     193        <Filename Value="Forms/UProject.pas"/>
     194        <IsPartOfProject Value="True"/>
     195      </Unit20>
    191196    </Units>
    192197  </ProjectOptions>
  • branches/CpuSingleSize/CpuSingleSize.lpr

    r220 r223  
    1111  UFormCpu, UFormConsole, UFormAssembler, UCore, UFormDisassembler,
    1212  UDisassembler, UMemory, UFormMessages, UMessages, SysUtils, UFormHelp,
    13   UParser, UFormDevices, UFormStorage;
     13  UParser, UFormDevices, UFormStorage, UProject;
    1414
    1515{$R *.res}
  • branches/CpuSingleSize/Forms/UFormAssembler.lfm

    r216 r223  
    99  DesignTimePPI = 144
    1010  OnShow = FormShow
    11   LCLVersion = '2.0.10.0'
     11  LCLVersion = '2.2.2.0'
    1212  inline SynEdit1: TSynEdit
    1313    Left = 16
     
    1818    Color = clBlack
    1919    Font.Color = clWhite
    20     Font.Height = 13
     20    Font.Height = 16
    2121    Font.Name = 'Liberation Mono'
    2222    Font.Pitch = fpFixed
     
    2525    ParentFont = False
    2626    TabOrder = 0
    27     Gutter.Width = 77
     27    Gutter.Width = 81
    2828    Gutter.MouseActions = <>
    2929    RightGutter.Width = 0
     
    481481      end
    482482      object SynGutterLineNumber1: TSynGutterLineNumber
    483         Width = 17
     483        Width = 21
    484484        MouseActions = <>
    485485        MarkupInfo.Background = clBtnFace
  • branches/CpuSingleSize/Forms/UFormAssembler.pas

    r216 r223  
    11unit UFormAssembler;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/Forms/UFormConsole.pas

    r220 r223  
    11unit UFormConsole;
    2 
    3 {$mode delphi}
    42
    53interface
     
    2422    procedure SetDevice(AValue: TDevice); override;
    2523  public
    26     Console: TConsole;
     24    Console: TDeviceConsole;
    2725  end;
    2826
     
    6361procedure TFormConsole.SetDevice(AValue: TDevice);
    6462begin
    65   if AValue is TConsole then
    66     Console := TConsole(AValue);
     63  if AValue is TDeviceConsole then
     64    Console := TDeviceConsole(AValue);
    6765end;
    6866
     
    7573    Console.Lock.Release;
    7674  end;
    77   Console.Cpu.Interrupt(Console.InterruptVector);
     75  Console.PulseInterrupt;
    7876end;
    7977
  • branches/CpuSingleSize/Forms/UFormCpu.pas

    r216 r223  
    11unit UFormCpu;
    2 
    3 {$mode delphi}
    42
    53interface
     
    4947  I: Integer;
    5048begin
    51   if Item.Index * DataPerLine < Length(Cpu.Data) then begin
     49  if Item.Index * DataPerLine < Length(Cpu.Memory) then begin
    5250    Item.Caption := IntToHex(Item.Index * DataPerLine, 8);
    5351    Line := '';
    5452    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) + ' ';
    5654    Item.SubItems.Add(Line);
    5755  end;
     
    6361    if Item.Index = 0 then begin
    6462      Item.Caption := 'IP';
    65       Item.SubItems.Add(IntToHex(Cpu.IP, 8));
     63      Item.SubItems.Add(IntToHex(Cpu.InstructionPointer, 8));
    6664    end else
    6765    if Item.Index = 1 then begin
    6866      Item.Caption := 'SP';
    69       Item.SubItems.Add(IntToHex(Cpu.SP, 8));
     67      Item.SubItems.Add(IntToHex(Cpu.StackPointer, 8));
    7068    end else begin
    7169      Item.Caption := 'R' + IntToStr(Item.Index - 2);
     
    7775procedure TFormCpu.Timer1Timer(Sender: TObject);
    7876begin
    79   ListViewMemory.Items.Count := Length(Cpu.Data) div DataPerLine;
     77  ListViewMemory.Items.Count := Length(Cpu.Memory) div DataPerLine;
    8078  ListViewMemory.Refresh;
    8179  ListViewRegs.Items.Count := Length(Cpu.R) + 2;
  • branches/CpuSingleSize/Forms/UFormDevices.lfm

    r220 r223  
    99  DesignTimePPI = 144
    1010  OnShow = FormShow
    11   LCLVersion = '2.0.10.0'
     11  LCLVersion = '2.2.2.0'
    1212  object TreeView1: TTreeView
    1313    Left = 16
  • branches/CpuSingleSize/Forms/UFormDevices.pas

    r220 r223  
    11unit UFormDevices;
    2 
    3 {$mode delphi}
    42
    53interface
    64
    75uses
    8   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, UMachine;
     6  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls,
     7  UMachine;
    98
    109type
     
    3534const
    3635  DeviceClassFormClasses: array[TDeviceClass] of TFormDeviceClass = (
    37     nil, nil, nil, TFormStorage, TFormScreen, TFormConsole);
     36    nil, nil, nil, TFormStorage, TFormScreen, TFormConsole, nil);
    3837
    3938{ TFormDevices }
     
    5554        FormClass := DeviceClassFormClasses[Device.DeviceClass];
    5655        if Assigned(FormClass) then begin
    57           Device.Form := TFormDevice(FormClass.Create(nil));
     56          Device.Form := FormClass.Create(nil);
    5857          Device.Form.Device := Device;
    5958          Device.Form.Show;
  • branches/CpuSingleSize/Forms/UFormDisassembler.pas

    r216 r223  
    11unit UFormDisassembler;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/Forms/UFormHelp.pas

    r216 r223  
    11unit UFormHelp;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/Forms/UFormMain.lfm

    r220 r223  
    1212  OnDestroy = FormDestroy
    1313  OnShow = FormShow
    14   LCLVersion = '2.0.10.0'
     14  LCLVersion = '2.2.2.0'
    1515  object ButtonLoad: TButton
    1616    Left = 24
  • branches/CpuSingleSize/Forms/UFormMain.pas

    r220 r223  
    11unit UFormMain;
    2 
    3 {$mode delphi}{$H+}
    42
    53interface
  • branches/CpuSingleSize/Forms/UFormMessages.lfm

    r217 r223  
    88  ClientWidth = 1113
    99  DesignTimePPI = 144
    10   LCLVersion = '2.0.10.0'
     10  LCLVersion = '2.2.2.0'
    1111  object ListView1: TListView
    1212    Left = 0
  • branches/CpuSingleSize/Forms/UFormMessages.pas

    r217 r223  
    11unit UFormMessages;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/Forms/UFormScreen.lfm

    r216 r223  
    1010  OnCreate = FormCreate
    1111  OnDestroy = FormDestroy
    12   LCLVersion = '2.0.10.0'
     12  LCLVersion = '2.2.2.0'
    1313  object PaintBox1: TPaintBox
    1414    Left = 8
  • branches/CpuSingleSize/Forms/UFormScreen.pas

    r220 r223  
    11unit UFormScreen;
    2 
    3 {$mode delphi}
    42
    53interface
     
    2523    procedure SetDevice(AValue: TDevice); override;
    2624  public
    27     Screen: TScreen;
     25    Screen: TDeviceScreen;
    2826  end;
    2927
     
    6563procedure TFormScreen.SetDevice(AValue: TDevice);
    6664begin
    67   if AValue is TScreen then
    68     Screen := TScreen(AValue);
     65  if AValue is TDeviceScreen then
     66    Screen := TDeviceScreen(AValue);
    6967end;
    7068
  • branches/CpuSingleSize/Forms/UFormStorage.lfm

    r220 r223  
    88  ClientWidth = 1153
    99  DesignTimePPI = 144
    10   LCLVersion = '2.0.10.0'
     10  LCLVersion = '2.2.2.0'
    1111  object ListView1: TListView
    1212    Left = 17
  • branches/CpuSingleSize/Forms/UFormStorage.pas

    r220 r223  
    11unit UFormStorage;
    2 
    3 {$mode delphi}
    42
    53interface
     
    1816    procedure SetDevice(AValue: TDevice); override;
    1917  public
    20     Storage: TStorage;
     18    Storage: TDeviceStorage;
    2119  end;
    2220
     
    3735procedure TFormStorage.SetDevice(AValue: TDevice);
    3836begin
    39   if AValue is TStorage then
    40     Storage := TStorage(AValue);
     37  if AValue is TDeviceStorage then
     38    Storage := TDeviceStorage(AValue);
    4139end;
    4240
  • branches/CpuSingleSize/UAssembler.pas

    r220 r223  
    11unit UAssembler;
    2 
    3 {$mode delphi}
    42
    53interface
     
    142140        TokenValue := Parser.ReadNext;
    143141        if TokenValue.Kind = tkNumber then begin
    144           if not Labels.ContainsKey(TokenName.Value) then begin
     142          if not Labels.ContainsKey(TokenName.Value) and not Variables.ContainsKey(TokenName.Value) then begin
    145143            if TryStrToInt(TokenValue.Value, Number) then
    146144              Variables.Add(TokenName.Value, Number)
  • branches/CpuSingleSize/UCore.pas

    r220 r223  
    11unit UCore;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/UCpu.pas

    r220 r223  
    11unit UCpu;
    2 
    3 {$mode delphi}
    42
    53interface
     
    1210    inAdd, inSub, inIn, inOut, inJump, inJumpZero, inJumpNotZero, inPush, inPop,
    1311    inCall, inRet, inAnd, inOr, inXor, inShl, inShr, inMul, inDiv, inMod,
    14     inJumpRel, inLoadIndex, inStoreIndex);
     12    inJumpRel, inLoadIndex, inStoreIndex, inLoadCpu, inStoreCpu, inEi, inDi);
    1513
    1614  TInteger = Integer;
     
    2018  TInputEvent = function (Device, Port: TInteger): TInteger of object;
    2119
     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
    2243  { TCpu }
    2344
    2445  TCpu = class
    2546  private
     47    FBaseMemory: TMemoryBlock;
     48    FUserMemory: TMemoryBlock;
     49    FMemory: TMemoryBlock;
    2650    FRunning: Boolean;
    2751    FThread: TCpuThread;
     
    3054    FNextInterupt: TInteger;
    3155    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);
    3295    procedure SetRunning(AValue: Boolean);
    3396    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;
    34104  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
    39108    R: array of TInteger;
    40109    function ReadNext: TInteger;
     
    44113    procedure Stop;
    45114    procedure Reset;
    46     procedure Interrupt(Index: TInteger);
     115    procedure Interrupt(Index: TSystemInterrupt); overload;
     116    procedure Interrupt(Index: TInteger); overload;
    47117    constructor Create;
    48118    destructor Destroy; override;
     119    property Ticks: Integer read FTicks;
     120    property Memory: TIntegerArray read GetMemory write SetMemory;
    49121    property OnInput: TInputEvent read FOnInput write FOnInput;
    50122    property OnOutput: TOutputEvent read FOnOutput write FOnOutput;
     
    62134
    63135implementation
     136
     137{ TCpuStatus }
     138
     139function TCpuStatus.GetInteger: TInteger;
     140begin
     141
     142end;
     143
     144procedure TCpuStatus.SetInteger(Value: TInteger);
     145begin
     146
     147end;
    64148
    65149{ TCpuThread }
     
    83167end;
    84168
     169procedure TCpu.InstructionNop;
     170begin
     171  // No operation
     172end;
     173
     174function TCpu.GetMemory: TIntegerArray;
     175begin
     176  Result := FBaseMemory.Base;
     177end;
     178
     179procedure TCpu.InstructionHalt;
     180begin
     181  FHalted := True;
     182end;
     183
     184procedure TCpu.InstructionSet;
     185begin
     186  R[ReadNext] := ReadNext;
     187end;
     188
     189procedure TCpu.InstructionCopy;
     190begin
     191  R[ReadNext] := R[ReadNext];
     192end;
     193
     194procedure TCpu.InstructionLoad;
     195begin
     196  R[ReadNext] := FMemory.Base[R[ReadNext]];
     197end;
     198
     199procedure TCpu.InstructionStore;
     200begin
     201  FMemory.Base[R[ReadNext]] := R[ReadNext];
     202end;
     203
     204procedure TCpu.InstructionInc;
     205begin
     206  Inc(R[ReadNext]);
     207end;
     208
     209procedure TCpu.InstructionDec;
     210begin
     211  Dec(R[ReadNext]);
     212end;
     213
     214procedure TCpu.InstructionAdd;
     215var
     216  Index: TInteger;
     217begin
     218  Index := ReadNext;
     219  R[Index] := R[Index] + R[ReadNext];
     220end;
     221
     222procedure TCpu.InstructionSub;
     223var
     224  Index: TInteger;
     225begin
     226  Index := ReadNext;
     227  R[Index] := R[Index] - R[ReadNext];
     228end;
     229
     230procedure TCpu.InstructionIn;
     231var
     232  Index: TInteger;
     233  Device: TInteger;
     234  Port: TInteger;
     235begin
     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;
     244end;
     245
     246procedure TCpu.InstructionOut;
     247var
     248  Device: TInteger;
     249  Port: TInteger;
     250  Index: TInteger;
     251begin
     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;
     260end;
     261
     262procedure TCpu.InstructionJump;
     263begin
     264  InstructionPointer := ReadNext;
     265end;
     266
     267procedure TCpu.InstructionJumpRel;
     268begin
     269  InstructionPointer := InstructionPointer + ReadNext;
     270end;
     271
     272procedure TCpu.InstructionJumpZero;
     273var
     274  Index: TInteger;
     275  Address: TInteger;
     276begin
     277  Index := ReadNext;
     278  Address := ReadNext;
     279  if R[Index] = 0 then InstructionPointer := Address;
     280end;
     281
     282procedure TCpu.InstructionJumpNotZero;
     283var
     284  Index: TInteger;
     285  Address: TInteger;
     286begin
     287  Index := ReadNext;
     288  Address := ReadNext;
     289  if R[Index] <> 0 then InstructionPointer := Address;
     290end;
     291
     292procedure TCpu.InstructionPush;
     293begin
     294  Push(R[ReadNext]);
     295end;
     296
     297procedure TCpu.InstructionPop;
     298begin
     299  R[ReadNext] := Pop;
     300end;
     301
     302procedure TCpu.InstructionCall;
     303var
     304  Address: TInteger;
     305begin
     306  Address := ReadNext;
     307  Push(InstructionPointer);
     308  InstructionPointer := Address;
     309end;
     310
     311procedure TCpu.InstructionRet;
     312begin
     313  InstructionPointer := Pop;
     314end;
     315
     316procedure TCpu.InstructionReti;
     317begin
     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;
     325end;
     326
     327procedure TCpu.InstructionAnd;
     328var
     329  Index: TInteger;
     330begin
     331  Index := ReadNext;
     332  R[Index] := R[Index] and R[ReadNext];
     333end;
     334
     335procedure TCpu.InstructionOr;
     336var
     337  Index: TInteger;
     338begin
     339  Index := ReadNext;
     340  R[Index] := R[Index] or R[ReadNext];
     341end;
     342
     343procedure TCpu.InstructionXor;
     344var
     345  Index: TInteger;
     346begin
     347  Index := ReadNext;
     348  R[Index] := R[Index] xor R[ReadNext];
     349end;
     350
     351procedure TCpu.InstructionShl;
     352var
     353  Index: TInteger;
     354begin
     355  Index := ReadNext;
     356  R[Index] := R[Index] shl R[ReadNext];
     357end;
     358
     359procedure TCpu.InstructionShr;
     360var
     361  Index: TInteger;
     362begin
     363  Index := ReadNext;
     364  R[Index] := R[Index] shr R[ReadNext];
     365end;
     366
     367procedure TCpu.InstructionMod;
     368var
     369  Index: TInteger;
     370begin
     371  Index := ReadNext;
     372  R[Index] := R[Index] mod R[ReadNext];
     373end;
     374
     375procedure TCpu.InstructionDiv;
     376var
     377  Index: TInteger;
     378begin
     379  Index := ReadNext;
     380  R[Index] := R[Index] div R[ReadNext];
     381end;
     382
     383procedure TCpu.InstructionMul;
     384var
     385  Index: TInteger;
     386begin
     387  Index := ReadNext;
     388  R[Index] := R[Index] * R[ReadNext];
     389end;
     390
     391procedure TCpu.InstructionLoadIndex;
     392begin
     393  R[ReadNext] := FMemory.Base[R[ReadNext] + ReadNext];
     394end;
     395
     396procedure TCpu.InstructionStoreIndex;
     397begin
     398  FMemory.Base[R[ReadNext] + ReadNext] := R[ReadNext];
     399end;
     400
     401procedure TCpu.InstructionLoadCpu;
     402var
     403  Index: TInteger;
     404  I: TInteger;
     405begin
     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;
     416end;
     417
     418procedure TCpu.InstructionStoreCpu;
     419var
     420  Index: TInteger;
     421  I: TInteger;
     422begin
     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;
     437end;
     438
     439procedure TCpu.InstructionEi;
     440begin
     441  if StatusRegister.UserMode then begin
     442    Interrupt(siPrivilegedInstruction);
     443    Exit;
     444  end;
     445  StatusRegister.InterruptEnabled := True;
     446end;
     447
     448procedure TCpu.InstructionDi;
     449begin
     450  if StatusRegister.UserMode then begin
     451    Interrupt(siPrivilegedInstruction);
     452    Exit;
     453  end;
     454  StatusRegister.InterruptEnabled := False;
     455end;
     456
     457procedure TCpu.SetMemory(AValue: TIntegerArray);
     458begin
     459  if (FBaseMemory.Base = AValue) and (FBaseMemory.Size = Length(AValue)) then Exit;
     460  FBaseMemory.Base := AValue;
     461  FBaseMemory.Size := Length(AValue);
     462end;
     463
    85464procedure TCpu.CheckInterreupts;
    86465begin
    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;
    91471    FNextInterupt := -1;
    92472    FHalted := False;
     
    94474end;
    95475
     476procedure TCpu.Push(Value: TInteger);
     477begin
     478  Dec(StackPointer);
     479  FMemory.Base[StackPointer] := Value;
     480end;
     481
     482function TCpu.Pop: TInteger;
     483begin
     484  Result := FMemory.Base[StackPointer];
     485  Inc(StackPointer);
     486end;
     487
     488procedure TCpu.StoreContext;
     489var
     490  I: Integer;
     491begin
     492  for I := 0 to Length(R) - 1 do
     493    Push(R[I]);
     494end;
     495
     496procedure TCpu.LoadContext;
     497var
     498  I: Integer;
     499begin
     500  for I := Length(R) - 1 downto 0 do
     501    R[I] := Pop;
     502end;
     503
     504procedure TCpu.InitInstructions;
     505begin
     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;
     540end;
     541
     542procedure TCpu.ActivateUserMode;
     543begin
     544  StatusRegister.UserMode := True;
     545  FMemory := FUserMemory;
     546end;
     547
     548procedure TCpu.DeactivateUserMode;
     549begin
     550  FMemory := FBaseMemory;
     551  StatusRegister.UserModeWasActive := StatusRegister.UserMode;
     552  StatusRegister.UserMode := False;
     553end;
     554
    96555function TCpu.ReadNext: TInteger;
    97556begin
    98   if IP >= Length(Data) then IP := 0;
    99   Result := Data[IP];
    100   Inc(IP);
     557  if InstructionPointer >= FMemory.Size then InstructionPointer := 0;
     558  Result := FMemory.Base[InstructionPointer];
     559  Inc(InstructionPointer);
    101560end;
    102561
    103562procedure TCpu.WriteNext(Value: TInteger);
    104563begin
    105   if IP >= Length(Data) then IP := 0;
    106   Data[IP] := Value;
    107   Inc(IP);
     564  if InstructionPointer >= FMemory.Size then InstructionPointer := 0;
     565  FMemory.Base[InstructionPointer] := Value;
     566  Inc(InstructionPointer);
    108567end;
    109568
     
    111570var
    112571  Instruction: TInstruction;
    113   Address: TInteger;
    114   Index: TInteger;
    115   Port: TInteger;
    116   Dest: TInteger;
    117   Device: TInteger;
    118572begin
    119573  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);
    217578end;
    218579
     
    243604  I: Integer;
    244605begin
     606  FMemory := FBaseMemory;
    245607  FNextInterupt := -1;
    246608  FHalted := False;
    247   Ticks := 0;
    248   IP := Data[0]; // Reset interrupt vector
    249   SP := Length(Data);
     609  FTicks := 0;
     610  InstructionPointer := FMemory.Base[Integer(siReset)];
     611  StackPointer := FMemory.Size;
    250612  for I := 0 to Length(R) - 1 do
    251613    R[I] := 0;
    252614end;
    253615
     616procedure TCpu.Interrupt(Index: TSystemInterrupt);
     617begin
     618  Interrupt(TInteger(Index));
     619end;
     620
    254621procedure TCpu.Interrupt(Index: TInteger);
    255622begin
     
    260627begin
    261628  SetLength(R, 16);
    262   SetLength(Data, 0);
     629  Memory := nil;
     630  InitInstructions;
    263631end;
    264632
  • branches/CpuSingleSize/UDisassembler.pas

    r220 r223  
    11unit UDisassembler;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/UInstructions.pas

    r220 r223  
    11unit UInstructions;
    2 
    3 {$mode delphi}
    42
    53interface
     
    102100  AddNew(inJumpRel, 'JR', [ptNumber], 'Unconditional relative jump to defined address.');
    103101  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.');
    105107end;
    106108
  • branches/CpuSingleSize/UMachine.pas

    r220 r223  
    11unit UMachine;
    2 
    3 {$mode delphi}
    42
    53interface
     
    97
    108type
    11   TDeviceClass = (dcNone, dcKeyboard, dcMouse, dcStorage, dcScreen, dcConsole);
     9  TDeviceClass = (dcNone, dcKeyboard, dcMouse, dcStorage, dcScreen, dcConsole,
     10    dcTimer);
    1211  TDeviceClassSet = set of TDeviceClass;
    1312
     
    3534    InterruptVector: Integer;
    3635    Form: TFormDevice;
     36    procedure PulseInterrupt;
    3737    procedure OutputHandler(Port, Data: TInteger); virtual;
    3838    function InputHandler(Port: TInteger): TInteger; virtual;
     
    6464  TConsoleOutputPort = (opConsoleWriteChar);
    6565
    66   { TConsole }
    67 
    68   TConsole = class(TDevice)
     66  { TDeviceConsole }
     67
     68  TDeviceConsole = class(TDevice)
    6969    Lock: TCriticalSection;
    7070    InputBuffer: TQueue<TInteger>;
     
    7979  TScreenOutputPort = (opScreenSetAddr, opScreenWrite);
    8080
    81   { TScreen }
    82 
    83   TScreen = class(TDevice)
     81  { TDeviceScreen }
     82
     83  TDeviceScreen = class(TDevice)
    8484  private
    8585    FSize: TPoint;
     
    9797  TKeyboardInputPort = (ipKeyboardRead);
    9898
    99   { TKeyboard }
    100 
    101   TKeyboard = class(TDevice)
     99  { TDeviceKeyboard }
     100
     101  TDeviceKeyboard = class(TDevice)
    102102    constructor Create;
    103103    function ReadKey: TInteger;
     
    108108  TStorageOutputPort = (opStorageSetAddr, opStorageWrite);
    109109
    110   { TStorage }
    111 
    112   TStorage = class(TDevice)
     110  { TDeviceStorage }
     111
     112  TDeviceStorage = class(TDevice)
    113113  public
    114114    F: TFileStream;
     
    119119  end;
    120120
    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;
    125135  end;
    126136
     
    144154
    145155const
    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');
    147157
    148158
    149159implementation
     160
     161{ TDeviceTimer }
     162
     163constructor TDeviceTimer.Create;
     164begin
     165  DeviceClass := dcTimer;
     166end;
     167
     168procedure TDeviceTimer.OutputHandler(Port, Data: TInteger);
     169begin
     170  case TTimerOutputPort(Port) of
     171    opTimerSetInterval: Interval := Data;
     172    opTimerSetEnabled: Enabled := Data > 0;
     173  end;
     174end;
    150175
    151176{ TDeviceManager }
     
    225250{ TDevice }
    226251
     252procedure TDevice.PulseInterrupt;
     253begin
     254  Cpu.Interrupt(InterruptVector);
     255end;
     256
    227257procedure TDevice.OutputHandler(Port, Data: TInteger);
    228258begin
     
    234264end;
    235265
    236 { TMouse }
    237 
    238 constructor TMouse.Create;
     266{ TDeviceMouse }
     267
     268constructor TDeviceMouse.Create;
    239269begin
    240270  DeviceClass := dcMouse;
    241271end;
    242272
    243 { TStorage }
    244 
    245 constructor TStorage.Create;
     273{ TDeviceStorage }
     274
     275constructor TDeviceStorage.Create;
    246276begin
    247277  DeviceClass := dcStorage;
    248278end;
    249279
    250 procedure TStorage.OutputHandler(Port, Data: TInteger);
     280procedure TDeviceStorage.OutputHandler(Port, Data: TInteger);
    251281begin
    252282  case TStorageOutputPort(Port) of
     
    258288end;
    259289
    260 function TStorage.InputHandler(Port: TInteger): TInteger;
     290function TDeviceStorage.InputHandler(Port: TInteger): TInteger;
    261291begin
    262292  case TStorageInputPort(Port) of
     
    268298end;
    269299
    270 { TConsole }
    271 
    272 constructor TConsole.Create;
     300{ TDeviceConsole }
     301
     302constructor TDeviceConsole.Create;
    273303begin
    274304  DeviceClass := dcConsole;
     
    278308end;
    279309
    280 destructor TConsole.Destroy;
     310destructor TDeviceConsole.Destroy;
    281311begin
    282312  InputBuffer.Free;
     
    286316end;
    287317
    288 procedure TConsole.OutputHandler(Port, Data: TInteger);
     318procedure TDeviceConsole.OutputHandler(Port, Data: TInteger);
    289319begin
    290320  case TConsoleOutputPort(Port) of
     
    300330end;
    301331
    302 function TConsole.InputHandler(Port: TInteger): TInteger;
     332function TDeviceConsole.InputHandler(Port: TInteger): TInteger;
    303333begin
    304334  case TConsoleInputPort(Port) of
     
    324354end;
    325355
    326 { TScreen }
    327 
    328 procedure TScreen.SetSize(AValue: TPoint);
     356{ TDeviceScreen }
     357
     358procedure TDeviceScreen.SetSize(AValue: TPoint);
    329359begin
    330360  if FSize = AValue then Exit;
     
    333363end;
    334364
    335 constructor TScreen.Create;
     365constructor TDeviceScreen.Create;
    336366begin
    337367  DeviceClass := dcScreen;
     
    339369end;
    340370
    341 procedure TScreen.OutputHandler(Port, Data: TInteger);
     371procedure TDeviceScreen.OutputHandler(Port, Data: TInteger);
    342372begin
    343373  case TScreenOutputPort(Port) of
     
    351381end;
    352382
    353 function TScreen.InputHandler(Port: TInteger): TInteger;
     383function TDeviceScreen.InputHandler(Port: TInteger): TInteger;
    354384begin
    355385  case TScreenInputPort(Port) of
     
    359389end;
    360390
    361 { TKeyboard }
    362 
    363 function TKeyboard.ReadKey: TInteger;
     391{ TDeviceKeyboard }
     392
     393function TDeviceKeyboard.ReadKey: TInteger;
    364394begin
    365395  Result := 0;
    366396end;
    367397
    368 function TKeyboard.InputHandler(Port: TInteger): TInteger;
     398function TDeviceKeyboard.InputHandler(Port: TInteger): TInteger;
    369399begin
    370400  case TKeyboardInputPort(Port) of
     
    373403end;
    374404
    375 constructor TKeyboard.Create;
     405constructor TDeviceKeyboard.Create;
    376406begin
    377407  DeviceClass := dcKeyboard;
     
    404434procedure TMachine.InitDevices;
    405435var
    406   Screen: TScreen;
    407   Keyboard: TKeyboard;
    408   Console: TConsole;
    409   Storage: TStorage;
    410   Mouse: TMouse;
     436  Screen: TDeviceScreen;
     437  Keyboard: TDeviceKeyboard;
     438  Console: TDeviceConsole;
     439  Storage: TDeviceStorage;
     440  Mouse: TDeviceMouse;
    411441  DeviceManager: TDeviceManager;
     442  Timer: TDeviceTimer;
    412443begin
    413444  DeviceManager := TDeviceManager.Create;
     
    415446  RegisterDevice(DeviceManager);
    416447
    417   Console := TConsole.Create;
     448  Console := TDeviceConsole.Create;
    418449  RegisterDevice(Console);
    419450  Console.InterruptVector := 1;
    420451
    421   Keyboard := TKeyboard.Create;
     452  Keyboard := TDeviceKeyboard.Create;
     453  Keyboard.InterruptVector := 4;
    422454  RegisterDevice(Keyboard);
    423455
    424   Screen := TScreen.Create;
     456  Screen := TDeviceScreen.Create;
    425457  RegisterDevice(Screen);
    426458
    427   Storage := TStorage.Create;
     459  Storage := TDeviceStorage.Create;
    428460  RegisterDevice(Storage);
    429461
    430   Storage := TStorage.Create;
     462  Storage := TDeviceStorage.Create;
    431463  RegisterDevice(Storage);
    432464
    433   Mouse := TMouse.Create;
     465  Mouse := TDeviceMouse.Create;
     466  Mouse.InterruptVector := 3;
    434467  RegisterDevice(Mouse);
     468
     469  Timer := TDeviceTimer.Create;
     470  Timer.InterruptVector := 2;
     471  RegisterDevice(Timer);
    435472end;
    436473
    437474procedure TMachine.PowerOn;
    438475begin
    439   Cpu.Data := Memory.Data;
     476  Cpu.Memory := Memory.Data;
    440477  Cpu.Start;
    441478end;
  • branches/CpuSingleSize/UMemory.pas

    r217 r223  
    11unit UMemory;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/UMessages.pas

    r216 r223  
    11unit UMessages;
    2 
    3 {$mode delphi}
    42
    53interface
  • branches/CpuSingleSize/UParser.pas

    r219 r223  
    11unit UParser;
    2 
    3 {$mode delphi}
    42
    53interface
Note: See TracChangeset for help on using the changeset viewer.