Ignore:
Timestamp:
Apr 10, 2019, 4:00:46 PM (6 years ago)
Author:
chronos
Message:
  • Added: Keyboard console.
  • Added: Show Hello World! message.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/virtualcpu4/UCpu.pas

    r170 r171  
    1313    opCall, opRet, opAdd, opAddc, opSub, opSubc, opInc, opDec, opIn, opOut, opShl,
    1414    opShr, opDataPrefix8, opDataPrefix16, opDataPrefix32, opDataPrefix64,
    15     opDataSize, opAddrSize);
     15    opDataSize, opAddrSize, opTest);
    1616  TAddress = QWord;
    1717  PAddress = ^TAddress;
     
    5353    procedure InstJumpNotZero;
    5454    procedure InstJumpRel;
     55    procedure InstTest;
    5556    procedure InstNeg;
    5657    procedure InstClear;
     
    7778    procedure InstDataSize;
    7879    procedure InstAddrSize;
     80    procedure InitInstructions;
    7981  public
    8082    Memory: array of Byte;
     
    9395    function Read32: DWord; inline;
    9496    function Read64: QWord; inline;
     97    function ReadAddress: TAddress; inline;
    9598    constructor Create;
    9699    property Ticks: Integer read FTicks;
     
    167170end;
    168171
     172procedure TCpu.InstTest;
     173var
     174  Reg: Byte;
     175begin
     176  Reg := Read8;
     177  case DataSize of
     178    bw8: Z := Registers[Reg].B = 0;
     179    bw16: Z := Registers[Reg].W = 0;
     180    bw32: Z := Registers[Reg].D = 0;
     181    bw64: Z := Registers[Reg].Q = 0;
     182  end;
     183end;
     184
    169185procedure TCpu.InstNeg;
    170186var
    171   Reg: Integer;
     187  Reg: Byte;
    172188begin
    173189  Reg := Read8;
     
    428444procedure TCpu.InstIn;
    429445var
    430   R: Integer;
    431   Port: Integer;
     446  R: Byte;
     447  Port: TAddress;
    432448begin
    433449  R := Read8;
    434   Port := Read8;
     450  Port := ReadAddress;
    435451  case DataSize of
    436452    bw8: begin
     
    455471procedure TCpu.InstOut;
    456472var
    457   R: Integer;
     473  R: Byte;
    458474  Port: TAddress;
    459475  Value: TRegister;
    460476begin
     477  Port := ReadAddress;
    461478  R := Read8;
    462   Port := Read8;
    463479  case DataSize of
    464480    bw8: begin
     
    541557end;
    542558
    543 procedure TCpu.Run;
    544 begin
    545   Terminated := False;
    546   FTicks := 0;
    547   DataSizeLast := bwNone;
    548   IP := 0;
    549   SP := Length(Memory);
    550   while not Terminated do
    551     Step;
    552 end;
    553 
    554 procedure TCpu.Step;
    555 var
    556   Opcode: Byte;
    557 begin
    558   if DataSizePrefix <> bwNone then begin
    559     DataSizeLast := DataSize;
    560     DataSize := DataSizePrefix;
    561     DataSizePrefix := bwNone;
    562   end;
    563   Opcode := Read8;
    564   if Opcode < Length(Instructions) then Instructions[TOpcode(Opcode)]
    565     else raise Exception.Create('Unsupported opcode ' + IntToStr(Opcode) + ' at address ' + IntToHex(IP, 8) + '.');
    566   if DataSizeLast <> bwNone then begin
    567     DataSize := DataSizeLast;
    568     DataSizeLast := bwNone;
    569   end;
    570   IP := IP mod Length(Memory);
    571   Inc(FTicks);
    572 end;
    573 
    574 procedure TCpu.Start;
    575 begin
    576   if not Running then begin
    577     Terminated := False;
    578     Thread := TCpuThread.Create(True);
    579     Thread.Cpu := Self;
    580     Thread.Start;
    581     FRunning := True;
    582   end;
    583 end;
    584 
    585 procedure TCpu.Stop;
    586 begin
    587   if Running then begin
    588     Terminated := True;
    589     Thread.Terminate;
    590     Thread.WaitFor;
    591     FreeAndNil(Thread);
    592     FRunning := False;
    593   end;
    594 end;
    595 
    596 function TCpu.Read8: Byte;
    597 begin
    598   Result := Memory[IP];
    599   Inc(IP);
    600 end;
    601 
    602 function TCpu.Read16: Word;
    603 begin
    604   Result := PWord(@Memory[IP])^;
    605   Inc(IP, SizeOf(Word));
    606 end;
    607 
    608 function TCpu.Read32: DWord;
    609 begin
    610   Result := PDWord(@Memory[IP])^;
    611   Inc(IP, SizeOf(DWord));
    612 end;
    613 
    614 function TCpu.Read64: QWord;
    615 begin
    616   Result := PQWord(@Memory[IP])^;
    617   Inc(IP, SizeOf(QWord));
    618 end;
    619 
    620 constructor TCpu.Create;
    621 begin
    622   DataSize := bw16;
    623   AddressSize := bw16;
    624   SetLength(Memory, 1000);
    625   SetLength(Registers, 32);
     559procedure TCpu.InitInstructions;
     560begin
    626561  Instructions[opNop] := InstNop;
    627562  Instructions[opHalt] := InstHalt;
     
    629564  Instructions[opLoadConst] := InstLoadConst;
    630565  Instructions[opJump] := InstJump;
     566  Instructions[opJumpNotZero] := InstJumpNotZero;
     567  Instructions[opJumpZero] := InstJumpZero;
    631568  Instructions[opJumpRel] := InstJumpRel;
    632569  Instructions[opLoadMem] := InstLoadMem;
     
    654591  Instructions[opDataPrefix32] := InstDataPrefix64;
    655592  Instructions[opAddrSize] := InstAddrSize;
     593  Instructions[opTest] := InstTest;
     594end;
     595
     596procedure TCpu.Run;
     597begin
     598  Terminated := False;
     599  FTicks := 0;
     600  DataSizeLast := bwNone;
     601  IP := 0;
     602  SP := Length(Memory);
     603  while not Terminated do
     604    Step;
     605end;
     606
     607procedure TCpu.Step;
     608var
     609  Opcode: Byte;
     610begin
     611  if DataSizePrefix <> bwNone then begin
     612    DataSizeLast := DataSize;
     613    DataSize := DataSizePrefix;
     614    DataSizePrefix := bwNone;
     615  end;
     616  Opcode := Read8;
     617  if Opcode < Length(Instructions) then begin
     618    if Assigned(Instructions[TOpcode(Opcode)]) then Instructions[TOpcode(Opcode)]
     619      else raise Exception.Create('Missing instruction handler for opcode '+ IntToStr(Opcode));
     620  end else raise Exception.Create('Unsupported opcode ' + IntToStr(Opcode) + ' at address ' + IntToHex(IP, 8) + '.');
     621  if DataSizeLast <> bwNone then begin
     622    DataSize := DataSizeLast;
     623    DataSizeLast := bwNone;
     624  end;
     625  IP := IP mod Length(Memory);
     626  Inc(FTicks);
     627end;
     628
     629procedure TCpu.Start;
     630begin
     631  if not Running then begin
     632    Terminated := False;
     633    Thread := TCpuThread.Create(True);
     634    Thread.Cpu := Self;
     635    Thread.Start;
     636    FRunning := True;
     637  end;
     638end;
     639
     640procedure TCpu.Stop;
     641begin
     642  if Running then begin
     643    Terminated := True;
     644    Thread.Terminate;
     645    Thread.WaitFor;
     646    FreeAndNil(Thread);
     647    FRunning := False;
     648  end;
     649end;
     650
     651function TCpu.Read8: Byte;
     652begin
     653  Result := Memory[IP];
     654  Inc(IP);
     655end;
     656
     657function TCpu.Read16: Word;
     658begin
     659  Result := PWord(@Memory[IP])^;
     660  Inc(IP, SizeOf(Word));
     661end;
     662
     663function TCpu.Read32: DWord;
     664begin
     665  Result := PDWord(@Memory[IP])^;
     666  Inc(IP, SizeOf(DWord));
     667end;
     668
     669function TCpu.Read64: QWord;
     670begin
     671  Result := PQWord(@Memory[IP])^;
     672  Inc(IP, SizeOf(QWord));
     673end;
     674
     675function TCpu.ReadAddress: TAddress;
     676begin
     677  case AddressSize of
     678    bw8: Result := Read8;
     679    bw16: Result := Read16;
     680    bw32: Result := Read32;
     681    bw64: Result := Read64;
     682  end;
     683end;
     684
     685constructor TCpu.Create;
     686begin
     687  DataSize := bw16;
     688  AddressSize := bw16;
     689  SetLength(Memory, 1000);
     690  SetLength(Registers, 32);
     691  InitInstructions;
    656692end;
    657693
Note: See TracChangeset for help on using the changeset viewer.