Ignore:
Timestamp:
Aug 19, 2020, 11:54:20 PM (4 years ago)
Author:
chronos
Message:
  • Added: TMachine class which contains CPU and peripherals.
  • Added: Execute TCpu inside background thread.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/virtcpu fixed int/UMachine.pas

    r168 r215  
    11unit UMachine;
    22
    3 {$DEFINE EXT_MEMORY}
    4 {$DEFINE EXT_IO}
    5 {$DEFINE EXT_ARITHMETIC}
    6 {$DEFINE EXT_CONDITIONAL}
    7 {$DEFINE EXT_LOGICAL}
    8 {$DEFINE EXT_STACK}
    9 {$DEFINE EXT_SUBROUTINE}
    10 {$DEFINE EXT_ROTATION}
    11 {$DEFINE EXT_MULTIPLICATION}
    12 {$DEFINE EXT_SHIFT}
    13 {$DEFINE EXT_BLOCK}
    14 {$DEFINE EXT_GENERAL}
    15 {$DEFINE EXT_BIT}
    16 {$DEFINE EXT_REL_JUMP}
    17 
    18 // Extension dependencies
    19 {$IFDEF EXT_SUBROUTINE}
    20 {$DEFINE EXT_STACK}
    21 {$ENDIF}
    22 {$IFDEF EXT_MULTIPLICATION}
    23 {$DEFINE EXT_ARITHMETIC}
    24 {$ENDIF}
    25 
    26 
    27 {$mode delphi}{$H+}
     3{$mode delphi}
    284
    295interface
    306
    317uses
    32   Classes, SysUtils;
     8  Classes, SysUtils, UCpu, syncobjs;
    339
    3410type
    35   T = Integer;
     11  { TMachine }
    3612
    37   TOpcode = (opNop, opLoad, opLoadConst, opNeg,
    38     opJump, {$IFDEF EXT_REL_JUMP}opJumpRel,{$ENDIF}
    39     opInc, opDec,
    40     {$IFDEF EXT_MEMORY}opLoadMem, opStoreMem,{$ENDIF}
    41     {$IFDEF EXT_ARITHMETIC}opAdd, opSub,{$ENDIF}
    42     {$IFDEF EXT_IO}opInput, opOutput,{$ENDIF}
    43     {$IFDEF EXT_SUBROUTINE}opCall,
    44     {$IFDEF EXT_REL_JUMP}opCallRel,{$ENDIF}
    45     opRet,{$ENDIF}
    46     {$IFDEF EXT_GENERAL}opExchg,{$ENDIF}
    47     {$IFDEF EXT_LOGICAL}opAnd, opOr, opXor,{$ENDIF}
    48     {$IFDEF EXT_SHIFT}opShl, opShr,{$ENDIF}
    49     {$IFDEF EXT_ROTATION}opRor, opRol,{$ENDIF}
    50     {$IFDEF EXT_STACK}opPush, opPop,{$ENDIF}
    51     {$IFDEF EXT_CONDITIONAL}
    52     {$IFDEF EXT_REL_JUMP}opJumpRelZero, opJumpRelNotZero,{$ENDIF}
    53     opJumpZero, opJumpNotZero, opTestEqual, opTestNotEqual, opTestLess,
    54     opTestLessEqual, opTestGreater, opTestGreaterEqual,
    55     {$ENDIF}
    56     {$IFDEF EXT_MULTIPLICATION}
    57     opMul, opDiv,
    58     {$ENDIF}
    59     opHalt
    60   );
    61 
    62   TOpcodeHandler = procedure of object;
    63   TInputEvent = function (Port: T): T of object;
    64   TOutputEvent = procedure (Port, Value: T) of object;
    65 
    66   { TCPU }
    67 
    68   TCPU = class(TComponent)
     13  TMachine = class(TComponent)
    6914  private
    70     FOnInput: TInputEvent;
    71     FOnOutput: TOutputEvent;
    72     OpcodeHandlers: array[TOpcode] of TOpcodeHandler;
    73     function ReadNext: T; inline;
    74     procedure OpcodeNop;
    75     procedure OpcodeHalt;
    76     procedure OpcodeLoad;
    77     procedure OpcodeLoadConst;
    78     procedure OpcodeJump;
    79     {$IFDEF EXT_REL_JUMP}
    80     procedure OpcodeJumpRel;
    81     {$ENDIF}
    82     procedure OpcodeNeg;
    83     procedure OpcodeInc;
    84     procedure OpcodeDec;
    85     {$IFDEF EXT_MEMORY}
    86     procedure OpcodeLoadMem;
    87     procedure OpcodeStoreMem;
    88     {$ENDIF}
    89     {$IFDEF EXT_GENERAL}
    90     procedure OpcodeExchange;
    91     {$ENDIF}
    92     {$IFDEF EXT_CONDITIONAL}
    93     procedure OpcodeTestEqual;
    94     procedure OpcodeTestNotEqual;
    95     procedure OpcodeTestGreatEqual;
    96     procedure OpcodeTestGreat;
    97     procedure OpcodeTestLessEqual;
    98     procedure OpcodeTestLess;
    99     procedure OpcodeJumpCondNotZero;
    100     procedure OpcodeJumpCondZero;
    101     {$IFDEF EXT_REL_JUMP}
    102     procedure OpcodeJumpRelCondNotZero;
    103     procedure OpcodeJumpRelCondZero;
    104     {$ENDIF}
    105     {$ENDIF}
    106     {$IFDEF EXT_SHIFT}
    107     procedure OpcodeShl;
    108     procedure OpcodeShr;
    109     {$ENDIF}
    110     {$IFDEF EXT_ROTATION}
    111     procedure OpcodeRor;
    112     procedure OpcodeRol;
    113     {$ENDIF}
    114     {$IFDEF EXT_LOGICAL}
    115     procedure OpcodeAnd;
    116     procedure OpcodeOr;
    117     procedure OpcodeXor;
    118     {$ENDIF}
    119     {$IFDEF EXT_STACK}
    120     procedure OpcodePush;
    121     procedure OpcodePop;
    122     {$ENDIF}
    123     {$IFDEF EXT_SUBROUTINE}
    124     procedure OpcodeCall;
    125     procedure OpcodeReturn;
    126     {$IFDEF EXT_REL_JUMP}
    127     procedure OpcodeCallRel;
    128     {$ENDIF}
    129     {$ENDIF}
    130     {$IFDEF EXT_IO}
    131     procedure OpcodeOutput;
    132     procedure OpcodeInput;
    133     {$ENDIF}
    134     {$IFDEF EXT_ARITHMETIC}
    135     procedure OpcodeAdd;
    136     procedure OpcodeSub;
    137     {$ENDIF}
    138     {$IFDEF EXT_MULTIPLICATION}
    139     procedure OpcodeMul;
    140     procedure OpcodeDiv;
    141     {$ENDIF}
     15    FOnSerialOutput: TNotifyEvent;
     16    function CpuInput(Port: T): T;
     17    procedure CpuOutput(Port, Value: T);
     18    procedure DoSerialOutput;
    14219  public
    143     Registers: array of T;
    144     IP: T;
    145     {$IFDEF EXT_STACK}
    146     SP: T;
    147     {$ENDIF}
    14820    Memory: array of T;
    149     Terminated: Boolean;
    150     Ticks: Integer;
    151     procedure Start;
    152     procedure Stop;
     21    Cpu: TCpu;
     22    VideoBase: T;
     23    VideoWidth: T;
     24    VideoHeight: T;
     25    SerialBufferInput: array of Char;
     26    SerialBufferOutput: array of Char;
     27    SerialBufferLock: TCriticalSection;
    15328    constructor Create(AOwner: TComponent); override;
    154   published
    155     property OnInput: TInputEvent read FOnInput write FOnInput;
    156     property OnOutput: TOutputEvent read FOnOutput write FOnOutput;
     29    destructor Destroy; override;
     30    procedure SerialInput(C: Char);
     31    property OnSerialOutput: TNotifyEvent read FOnSerialOutput write FOnSerialOutput;
    15732  end;
    158 
    15933
    16034implementation
    16135
    162 { TCPU }
     36{ TMachine }
    16337
    164 function TCPU.ReadNext: T;
     38constructor TMachine.Create(AOwner: TComponent);
    16539begin
    166   Result := Memory[IP];
    167   Inc(IP);
     40  inherited;
     41  SerialBufferLock := TCriticalSection.Create;
     42  Cpu := TCpu.Create(nil);
     43  Cpu.OnInput := CpuInput;
     44  Cpu.OnOutput := CpuOutput;
    16845end;
    16946
    170 procedure TCPU.OpcodeHalt;
     47destructor TMachine.Destroy;
    17148begin
    172   Terminated := True;
     49  Cpu.Stop;
     50  FreeAndNil(Cpu);
     51  FreeAndNil(SerialBufferLock);
     52  inherited;
    17353end;
    17454
    175 procedure TCPU.OpcodeNop;
     55procedure TMachine.SerialInput(C: Char);
    17656begin
    177   // Do nothing
    178 end;
    179 
    180 procedure TCPU.OpcodeLoad;
    181 var
    182   P1: T;
    183   P2: T;
    184 begin
    185   P1 := ReadNext;
    186   P2 := ReadNext;
    187   Registers[P1] := Registers[P2];
    188 end;
    189 
    190 procedure TCPU.OpcodeLoadConst;
    191 var
    192   P1: T;
    193   P2: T;
    194 begin
    195   P1 := ReadNext;
    196   P2 := ReadNext;
    197   Registers[P1] := P2;
    198 end;
    199 
    200 {$IFDEF EXT_MEMORY}
    201 procedure TCPU.OpcodeLoadMem;
    202 var
    203   P1: T;
    204   P2: T;
    205 begin
    206   P1 := ReadNext;
    207   P2 := ReadNext;
    208   Registers[P1] := Memory[Registers[P2]];
    209 end;
    210 
    211 procedure TCPU.OpcodeStoreMem;
    212 var
    213   P1: T;
    214   P2: T;
    215 begin
    216   P1 := ReadNext;
    217   P2 := ReadNext;
    218   Memory[Registers[P1]] := Registers[P2];
    219 end;
    220 {$ENDIF}
    221 
    222 procedure TCPU.OpcodeNeg;
    223 var
    224   P1: T;
    225 begin
    226   P1 := ReadNext;
    227   Registers[P1] := -Registers[P1];
    228 end;
    229 
    230 {$IFDEF EXT_GENERAL}
    231 procedure TCPU.OpcodeExchange;
    232 var
    233   P1, P2, Temp: T;
    234 begin
    235   P1 := ReadNext;
    236   P2 := ReadNext;
    237   Temp := Registers[P1];
    238   Registers[P1] := Registers[P2];
    239   Registers[P2] := Temp;
    240 end;
    241 {$ENDIF}
    242 
    243 procedure TCPU.OpcodeJump;
    244 begin
    245   IP := ReadNext;
    246 end;
    247 
    248 {$IFDEF EXT_REL_JUMP}
    249 procedure TCPU.OpcodeJumpRel;
    250 begin
    251   IP := IP + ReadNext;
    252 end;
    253 {$ENDIF}
    254 
    255 {$IFDEF EXT_CONDITIONAL}
    256 procedure TCPU.OpcodeTestEqual;
    257 var
    258   P1, P2: T;
    259 begin
    260   P1 := ReadNext;
    261   P2 := ReadNext;
    262   if Registers[P1] = Registers[P2] then Registers[P1] := 1
    263     else Registers[P1] := 0;
    264 end;
    265 
    266 procedure TCPU.OpcodeTestNotEqual;
    267 var
    268   P1, P2: T;
    269 begin
    270   P1 := ReadNext;
    271   P2 := ReadNext;
    272   if Registers[P1] <> Registers[P2] then Registers[P1] := 1
    273     else Registers[P1] := 0;
    274 end;
    275 
    276 procedure TCPU.OpcodeTestGreatEqual;
    277 var
    278   P1, P2: T;
    279 begin
    280   P1 := ReadNext;
    281   P2 := ReadNext;
    282   if Registers[P1] >= Registers[P2] then Registers[P1] := 1
    283     else Registers[P1] := 0;
    284 end;
    285 
    286 procedure TCPU.OpcodeTestGreat;
    287 var
    288   P1, P2: T;
    289 begin
    290   P1 := ReadNext;
    291   P2 := ReadNext;
    292   if Registers[P1] > Registers[P2] then Registers[P1] := 1
    293     else Registers[P1] := 0;
    294 end;
    295 
    296 procedure TCPU.OpcodeTestLessEqual;
    297 var
    298   P1, P2: T;
    299 begin
    300   P1 := ReadNext;
    301   P2 := ReadNext;
    302   if Registers[P1] <= Registers[P2] then Registers[P1] := 1
    303     else Registers[P1] := 0;
    304 end;
    305 
    306 procedure TCPU.OpcodeTestLess;
    307 var
    308   P1, P2: T;
    309 begin
    310   P1 := ReadNext;
    311   P2 := ReadNext;
    312   if Registers[P1] < Registers[P2] then Registers[P1] := 1
    313     else Registers[P1] := 0;
    314 end;
    315 
    316 procedure TCPU.OpcodeJumpCondNotZero;
    317 var
    318   P1, P2: T;
    319 begin
    320   P1 := ReadNext;
    321   P2 := ReadNext;
    322   if Registers[P1] <> 0 then IP := P2;
    323 end;
    324 
    325 procedure TCPU.OpcodeJumpCondZero;
    326 var
    327   P1, P2: T;
    328 begin
    329   P1 := ReadNext;
    330   P2 := ReadNext;
    331   if Registers[P1] = 0 then IP := P2;
    332 end;
    333 
    334 {$IFDEF EXT_REL_JUMP}
    335 procedure TCPU.OpcodeJumpRelCondZero;
    336 var
    337   P1, P2: T;
    338 begin
    339   P1 := ReadNext;
    340   P2 := ReadNext;
    341   if P1 = 0 then IP := IP + P2;
    342 end;
    343 
    344 procedure TCPU.OpcodeJumpRelCondNotZero;
    345 var
    346   P1, P2: T;
    347 begin
    348   P1 := ReadNext;
    349   P2 := ReadNext;
    350   if P1 <> 0 then IP := IP + P2;
    351 end;
    352 {$ENDIF}
    353 {$ENDIF}
    354 
    355 {$IFDEF EXT_ROTATION}
    356 procedure TCPU.OpcodeRor;
    357 var
    358   P1, P2: T;
    359 begin
    360   P1 := ReadNext;
    361   P2 := ReadNext;
    362   Registers[P1] := (Registers[P1] shr Registers[P2]) or
    363     ((Registers[P1] and ((1 shl Registers[P2]) - 1)) shl (SizeOf(T) * 8 - Registers[P2]));
    364 end;
    365 
    366 procedure TCPU.OpcodeRol;
    367 var
    368   P1, P2: T;
    369 begin
    370   P1 := ReadNext;
    371   P2 := ReadNext;
    372   Registers[P1] := (Registers[P1] shl Registers[P2]) or
    373     ((Registers[P1] shr (SizeOf(T) * 8 - Registers[P2])) and ((1 shl Registers[P2]) - 1));
    374 end;
    375 {$ENDIF}
    376 
    377 {$IFDEF EXT_SHIFT}
    378 procedure TCPU.OpcodeShl;
    379 var
    380   P1, P2: T;
    381 begin
    382   P1 := ReadNext;
    383   P2 := ReadNext;
    384   Registers[P1] := Registers[P1] shl Registers[P2];
    385 end;
    386 
    387 procedure TCPU.OpcodeShr;
    388 var
    389   P1, P2: T;
    390 begin
    391   P1 := ReadNext;
    392   P2 := ReadNext;
    393   Registers[P1] := Registers[P1] shr Registers[P2];
    394 end;
    395 {$ENDIF}
    396 
    397 {$IFDEF EXT_LOGICAL}
    398 procedure TCPU.OpcodeAnd;
    399 var
    400   P1, P2: T;
    401 begin
    402   P1 := ReadNext;
    403   P2 := ReadNext;
    404   Registers[P1] := Registers[P1] and Registers[P2];
    405 end;
    406 
    407 procedure TCPU.OpcodeOr;
    408 var
    409   P1, P2: T;
    410 begin
    411   P1 := ReadNext;
    412   P2 := ReadNext;
    413   Registers[P1] := Registers[P1] or Registers[P2];
    414 end;
    415 
    416 procedure TCPU.OpcodeXor;
    417 var
    418   P1, P2: T;
    419 begin
    420   P1 := ReadNext;
    421   P2 := ReadNext;
    422   Registers[P1] := Registers[P1] xor Registers[P2];
    423 end;
    424 {$ENDIF}
    425 
    426 {$IFDEF EXT_STACK}
    427 procedure TCPU.OpcodePush;
    428 begin
    429   Memory[SP] := Registers[ReadNext];
    430   Dec(SP);
    431 end;
    432 
    433 procedure TCPU.OpcodePop;
    434 begin
    435   Inc(SP);
    436   Registers[ReadNext] := Memory[SP];
    437 end;
    438 {$ENDIF}
    439 
    440 {$IFDEF EXT_SUBROUTINE}
    441 procedure TCPU.OpcodeCall;
    442 var
    443   Addr: T;
    444 begin
    445   Addr := ReadNext;
    446   Memory[SP] := IP;
    447   Dec(SP);
    448   IP := Addr;
    449 end;
    450 
    451 {$IFDEF EXT_REL_JUMP}
    452 procedure TCPU.OpcodeCallRel;
    453 var
    454   Addr: T;
    455 begin
    456   Addr := ReadNext;
    457   Memory[SP] := IP;
    458   Dec(SP);
    459   IP := IP + Addr;
    460 end;
    461 {$ENDIF}
    462 
    463 procedure TCPU.OpcodeReturn;
    464 begin
    465   Inc(SP);
    466   IP := Memory[SP];
    467 end;
    468 {$ENDIF}
    469 
    470 {$IFDEF EXT_IO}
    471 procedure TCPU.OpcodeOutput;
    472 var
    473   R1: T;
    474   R2: T;
    475 begin
    476   R1 := ReadNext;
    477   R2 := ReadNext;
    478   if Assigned(FOnOutput) then
    479     FOnOutput(Registers[R1], Registers[R2]);
    480 end;
    481 
    482 procedure TCPU.OpcodeInput;
    483 var
    484   R1: T;
    485   R2: T;
    486 begin
    487   R1 := ReadNext;
    488   R2 := ReadNext;
    489   if Assigned(FOnInput) then
    490     Registers[R1] := FOnInput(Registers[R2]);
    491 end;
    492 {$ENDIF}
    493 
    494 procedure TCPU.OpcodeInc;
    495 var
    496   R: T;
    497 begin
    498   R := ReadNext;
    499   Registers[R] := Registers[R] + 1;
    500 end;
    501 
    502 procedure TCPU.OpcodeDec;
    503 var
    504   R: T;
    505 begin
    506   R := ReadNext;
    507   Registers[R] := Registers[R] - 1;
    508 end;
    509 
    510 {$IFDEF EXT_ARITHMETIC}
    511 procedure TCPU.OpcodeAdd;
    512 var
    513   R1: T;
    514   R2: T;
    515 begin
    516   R1 := ReadNext;
    517   R2 := ReadNext;
    518   Registers[R1] := Registers[R1] + Registers[R2];
    519 end;
    520 
    521 procedure TCPU.OpcodeSub;
    522 var
    523   R1: T;
    524   R2: T;
    525 begin
    526   R1 := ReadNext;
    527   R2 := ReadNext;
    528   Registers[R1] := Registers[R1] - Registers[R2];
    529 end;
    530 {$ENDIF}
    531 
    532 {$IFDEF EXT_MULTIPLICATION}
    533 procedure TCPU.OpcodeMul;
    534 var
    535   R1: T;
    536   R2: T;
    537 begin
    538   R1 := ReadNext;
    539   R2 := ReadNext;
    540   Registers[R1] := Registers[R1] * Registers[R2];
    541 end;
    542 
    543 procedure TCPU.OpcodeDiv;
    544 var
    545   R1: T;
    546   R2: T;
    547 begin
    548   R1 := ReadNext;
    549   R2 := ReadNext;
    550   Registers[R1] := Registers[R1] div Registers[R2];
    551 end;
    552 {$ENDIF}
    553 
    554 procedure TCPU.Start;
    555 var
    556   Opcode: T;
    557 begin
    558   Terminated := False;
    559   IP := 0;
    560   Ticks := 0;
    561   {$IFDEF EXT_STACK}
    562   SP := Length(Memory);
    563   {$ENDIF}
    564   while not Terminated do begin
    565     Opcode := ReadNext;
    566     if (Opcode >= 0) and (Opcode <= T(High(TOpcode))) then
    567       OpcodeHandlers[TOpcode(Opcode)]
    568       else raise Exception.Create(Format('Unsupported instruction %d', [Opcode]));
    569     Inc(Ticks);
     57  SerialBufferLock.Acquire;
     58  try
     59    SetLength(SerialBufferInput, Length(SerialBufferInput) + 1);
     60    SerialBufferInput[High(SerialBufferInput)] := C;
     61  finally
     62    SerialBufferLock.Release;
    57063  end;
    57164end;
    57265
    573 procedure TCPU.Stop;
     66function TMachine.CpuInput(Port: T): T;
    57467begin
    575   Terminated := True;
     68  Result := 0;
     69  case Port of
     70    0: begin
     71      SerialBufferLock.Acquire;
     72      try
     73        while (Length(SerialBufferInput) = 0) and not Cpu.Terminated do begin
     74          try
     75            SerialBufferLock.Release;
     76            Sleep(10);
     77          finally
     78            SerialBufferLock.Acquire;
     79          end;
     80        end;
     81          if Length(SerialBufferInput) > 0 then begin
     82          Result := Ord(SerialBufferInput[0]);
     83          if Length(SerialBufferInput) > 1 then
     84            Move(SerialBufferInput[1], SerialBufferInput[0], Length(SerialBufferInput) - 1);
     85          SetLength(SerialBufferInput, Length(SerialBufferInput) - 1);
     86        end else Result := 0;
     87      finally
     88        SerialBufferLock.Release;
     89      end;
     90    end;
     91    1: begin
     92      Result := Length(SerialBufferInput);
     93    end;
     94  end;
    57695end;
    57796
    578 constructor TCPU.Create(AOwner: TComponent);
     97procedure TMachine.CpuOutput(Port, Value: T);
    57998begin
    580   inherited;
    581   SetLength(Registers, 16);
    582   SetLength(Memory, 1024);
    583   OpcodeHandlers[opNop] := OpcodeNop;
    584   OpcodeHandlers[opLoad] := OpcodeLoad;
    585   OpcodeHandlers[opHalt] := OpcodeHalt;
    586   OpcodeHandlers[opLoadConst] := OpcodeLoadConst;
    587   OpcodeHandlers[opNeg] := OpcodeNeg;
    588   OpcodeHandlers[opJump] := OpcodeJump;
    589   OpcodeHandlers[opInc] := OpcodeInc;
    590   OpcodeHandlers[opDec] := OpcodeDec;
    591   {$IFDEF EXT_REL_JUMP}
    592   OpcodeHandlers[opJumpRel] := OpcodeJumpRel;
    593   {$ENDIF}
    594   {$IFDEF EXT_MEMORY}
    595   OpcodeHandlers[opLoadMem] := OpcodeLoadMem;
    596   OpcodeHandlers[opStoreMem] := OpcodeStoreMem;
    597   {$ENDIF}
    598   {$IFDEF EXT_GENERAL}
    599   OpcodeHandlers[opExchg] := OpcodeExchange;
    600   {$ENDIF}
    601   {$IFDEF EXT_LOGICAL}
    602   OpcodeHandlers[opAnd] := OpcodeAnd;
    603   OpcodeHandlers[opOr] := OpcodeOr;
    604   OpcodeHandlers[opXor] := OpcodeXor;
    605   {$ENDIF}
    606   {$IFDEF EXT_SHIFT}
    607   OpcodeHandlers[opShl] := OpcodeShl;
    608   OpcodeHandlers[opShr] := OpcodeShr;
    609   {$ENDIF}
    610   {$IFDEF EXT_STACK}
    611   OpcodeHandlers[opPush] := OpcodePush;
    612   OpcodeHandlers[opPop] := OpcodePop;
    613   {$ENDIF}
    614   {$IFDEF EXT_SUBROUTINE}
    615   OpcodeHandlers[opCall] := OpcodeCall;
    616   {$IFDEF EXT_REL_JUMP}
    617   OpcodeHandlers[opCallRel] := OpcodeCallRel;
    618   {$ENDIF}
    619   OpcodeHandlers[opRet] := OpcodeReturn;
    620   {$ENDIF}
    621   {$IFDEF EXT_ROTATION}
    622   OpcodeHandlers[opRor] := OpcodeRor;
    623   OpcodeHandlers[opRol] := OpcodeRol;
    624   {$ENDIF}
    625   {$IFDEF EXT_IO}
    626   OpcodeHandlers[opInput] := OpcodeInput;
    627   OpcodeHandlers[opOutput] := OpcodeOutput;
    628   {$ENDIF}
    629   {$IFDEF EXT_ARITHMETIC}
    630   OpcodeHandlers[opAdd] := OpcodeAdd;
    631   OpcodeHandlers[opSub] := OpcodeSub;
    632   {$ENDIF}
    633   {$IFDEF EXT_CONDITIONAL}
    634   OpcodeHandlers[opJumpZero] := OpcodeJumpCondZero;
    635   OpcodeHandlers[opJumpNotZero] := OpcodeJumpCondNotZero;
    636   {$IFDEF EXT_REL_JUMP}
    637   OpcodeHandlers[opJumpRelZero] := OpcodeJumpRelCondZero;
    638   OpcodeHandlers[opJumpRelNotZero] := OpcodeJumpRelCondNotZero;
    639   {$ENDIF}
    640   OpcodeHandlers[opTestEqual] := OpcodeTestEqual;
    641   OpcodeHandlers[opTestNotEqual] := OpcodeTestNotEqual;
    642   OpcodeHandlers[opTestLess] := OpcodeTestLess;
    643   OpcodeHandlers[opTestLessEqual] := OpcodeTestLessEqual;
    644   OpcodeHandlers[opTestGreater] := OpcodeTestGreat;
    645   OpcodeHandlers[opTestGreaterEqual] := OpcodeTestGreatEqual;
    646   {$ENDIF}
    647   {$IFDEF EXT_MULTIPLICATION}
    648   OpcodeHandlers[opMul] := OpcodeMul;
    649   OpcodeHandlers[opDiv] := OpcodeDiv;
    650   {$ENDIF}
     99  case Port of
     100    0: begin
     101      SerialBufferLock.Acquire;
     102      try
     103        SetLength(SerialBufferOutput, Length(SerialBufferOutput) + 1);
     104        SerialBufferOutput[High(SerialBufferOutput)] := Chr(Value);
     105      finally
     106        SerialBufferLock.Release;
     107      end;
     108      TThread.Synchronize(Cpu.Thread, DoSerialOutput);
     109    end;
     110  end;
     111end;
     112
     113procedure TMachine.DoSerialOutput;
     114begin
     115  if Assigned(FOnSerialOutput) then
     116    FOnSerialOutput(Self);
    651117end;
    652118
Note: See TracChangeset for help on using the changeset viewer.