 { Ovladani kontrol }
{ define AddOverflow}
{ define SubOverflow}
{ define MulOverflow}
{ define DivByZero}
{ define ModByZero}
{ define MulV40Overflow}
{ define DivV40Overflow}
{ define ModV40Overflow}

program TestRetos;
{$I sets.inc}
uses
  Crt,
  NumToStr,
  Kernel,
  Timer,
  UInt32;


var
  OldExitProc:Pointer;

procedure Process(const str:String); far;
const
  cStack = 8000;
  cSPrio = 90;
  cDPrio = 254;
var
  bRot:Byte;
  dwCnt, _dwCnt, dwCnt1, _dwCnt1, dw8086, dw80386 : UNSIGNED32;
  fOverflow8086, fOverflow80386 : Boolean;
  theTimer:tTimer;
begin
  theTimer.Init;

  Start(str, cStack, cSPrio, cDPrio); exit;

  Writeln('Spusteni procesu: ', str);
  { testy na _IncUInt32 }
  if _IncUInt32(0) <> 1 then RunError(255);
  if _IncUInt32($4501) <> $4502 then RunError(255);
  if _IncUInt32($7FFFFFFF) <> $80000000 then RunError(255);
  if _IncUInt32($A0000000) <> $A0000001 then RunError(255);
  if _IncUInt32($FFFFFFFF) <> 0 then RunError(255);
  { testy na _IncUInt32Ex }
  if _IncUInt32Ex(0, 10) <> 10 then RunError(255);
  if _IncUInt32Ex($4501, $10) <> $4511 then RunError(255);
  if _IncUInt32Ex($7FFFFFFF, $10) <> $8000000F then RunError(255);
  if _IncUInt32Ex($A0000000, $10) <> $A0000010 then RunError(255);
  if _IncUInt32Ex($FFFFFFFF, $10) <> $0F then RunError(255);
  { testy na IncUInt32 }
  if IncUInt32(0) <> 1 then RunError(255);
  if IncUInt32($4501) <> $4502 then RunError(255);
  if IncUInt32($7FFFFFFF) <> $80000000 then RunError(255);
  if IncUInt32($A0000000) <> $A0000001 then RunError(255);
  if IncUInt32($FFFFFFFF) <> 0 then RunError(255);
  { testy na IncUInt32Ex }
  if IncUInt32Ex(0, 10) <> 10 then RunError(255);
  if IncUInt32Ex($4501, $10) <> $4511 then RunError(255);
  if IncUInt32Ex($7FFFFFFF, $10) <> $8000000F then RunError(255);
  if IncUInt32Ex($A0000000, $10) <> $A0000010 then RunError(255);
  if IncUInt32Ex($FFFFFFFF, $10) <> $0F then RunError(255);


  { testy na _DecUInt32 }
  if _DecUInt32(0) <> $FFFFFFFF then RunError(255);
  if _DecUInt32($4501) <> $4500 then RunError(255);
  if _DecUInt32($7FFFFFFF) <> $7FFFFFFE then RunError(255);
  if _DecUInt32($A0000000) <> $9FFFFFFF then RunError(255);

  { testy na _DecUInt32Ex }
  if _DecUInt32Ex(0, $10) <> $FFFFFFF0 then RunError(255);
  if _DecUInt32Ex($4501, $10) <> $44F1 then RunError(255);
  if _DecUInt32Ex($7FFFFFFF, $10) <> $7FFFFFEF then RunError(255);
  if _DecUInt32Ex($A0000000, $10) <> $9FFFFFF0 then RunError(255);

  { testy na AddUInt32 }
  if AddUInt32(5, 6) <> 11 then RunError(255);
  if AddUInt32($A0000000, $54300) <> $A0054300 then RunError(255);
 {$ifdef AddOverflow}
  writeln(str, ' - Vygenerovani RunError(215)');
  if AddUInt32($A0000000, $60000000) <> $00000000 then RunError(255);
 {$endif}
  if AddUInt32($A0000000, $5FFFFFFF) <> $FFFFFFFF then RunError(255);

  { testy na SubUInt32 }
 {$ifdef SubOverflow}
  writeln(str, ' - Vygenerovani RunError(215)');
  if SubUInt32(5, 6) <> $FFFFFFFF then RunError(255);
 {$endif}
  if SubUInt32(5, 5) <> $0 then RunError(255);
  if SubUInt32($A0000000, $54300) <> $9FFABD00 then RunError(255);
  if SubUInt32($A0000000, $60000000) <> $40000000 then RunError(255);
  if SubUInt32($A0000000, $70000000) <> $30000000 then RunError(255);

  { testy na A < B - TRUE }
  if not _IsLessUInt32(5, 6) then RunError(255);
  if _IsLessUInt32(5, 5) then RunError(255);
  if _IsLessUInt32(6, 4) then RunError(255);
  if _IsLessUInt32($A0000000, $60000000) then RunError(255);
  if not _IsLessUInt32($A0000000, $B0000000) then RunError(255);

  { testy na A < B - TRUE }
  if not IsLessUInt32(5, 6) then RunError(255);
  if IsLessUInt32(5, 5) then RunError(255);
  if IsLessUInt32(6, 4) then RunError(255);
  if IsLessUInt32($A0000000, $60000000) then RunError(255);
  if not IsLessUInt32($A0000000, $B0000000) then RunError(255);

  { testy na A <= B - TRUE }
  if not IsLessEqualUInt32(5, 6) then RunError(255);
  if not IsLessEqualUInt32(5, 5) then RunError(255);
  if IsLessEqualUInt32(6, 4) then RunError(255);
  if IsLessEqualUInt32($A0000000, $60000000) then RunError(255);
  if not IsLessEqualUInt32($A0000000, $B0000000) then RunError(255);

  { testy na A <= B - TRUE }
  if not _IsLessEqualUInt32(5, 6) then RunError(255);
  if not _IsLessEqualUInt32(5, 5) then RunError(255);
  if _IsLessEqualUInt32(6, 4) then RunError(255);
  if _IsLessEqualUInt32($A0000000, $60000000) then RunError(255);
  if not _IsLessEqualUInt32($A0000000, $B0000000) then RunError(255);

  { testy na A > B - TRUE }
  if IsGreaterUInt32(5, 6) then RunError(255);
  if IsGreaterUInt32(5, 5) then RunError(255);
  if not IsGreaterUInt32(6, 4) then RunError(255);
  if not IsGreaterUInt32($A0000000, $60000000) then RunError(255);
  if IsGreaterUInt32($A0000000, $B0000000) then RunError(255);

  { testy na A > B - TRUE }
  if _IsGreaterUInt32(5, 6) then RunError(255);
  if _IsGreaterUInt32(5, 5) then RunError(255);
  if not _IsGreaterUInt32(6, 4) then RunError(255);
  if not _IsGreaterUInt32($A0000000, $60000000) then RunError(255);
  if _IsGreaterUInt32($A0000000, $B0000000) then RunError(255);

  { testy na A = B - TRUE }
  if IsEqualUInt32(5, 6) then RunError(255);
  if not IsEqualUInt32(5, 5) then RunError(255);
  if not IsEqualUInt32($A0000000, $A0000000) then RunError(255);
  if IsEqualUInt32(6, 4) then RunError(255);
  if IsEqualUInt32($A0000000, $60000000) then RunError(255);
  if IsEqualUInt32($A0000000, $B0000000) then RunError(255);

  { testy na A = B - TRUE }
  if _IsEqualUInt32(5, 6) then RunError(255);
  if not _IsEqualUInt32(5, 5) then RunError(255);
  if not _IsEqualUInt32($A0000000, $A0000000) then RunError(255);
  if _IsEqualUInt32(6, 4) then RunError(255);
  if _IsEqualUInt32($A0000000, $60000000) then RunError(255);
  if _IsEqualUInt32($A0000000, $B0000000) then RunError(255);

  Test8086:=3;
  { testy na nasobeni }
  if MulUInt32(5, 6)<>30 then RunError(255);
  if MulUInt32(3000, 3000) <> 9000000 then RunError(255);
  if MulUInt32(300000, 6789) <> 2036700000 then RunError(255);
 {$ifdef MulOverflow}
  writeln(str, ' - Vygenerovani RunError(215)');
  if MulUInt32( 300000, 300000) <> 0 then RunError(255);
 {$endif}
(*
  writeln(str, ' - Testy na nasobeni');
  dwCnt:=0;
  _dwCnt:=0;
  theTimer.SaveTime;
  while TRUE do
  begin
    writeln(str, ' - dwCnt: ', dwCnt);
    dwCnt1:=0;
    _dwCnt1:=0;
    while TRUE do
    begin
     {$ifdef MulV40Overflow}
      {-+-+}
      fOverflow:=FALSE;
     {$endif}
      Test8086:=3;
      dw80386:=MulUInt32(dwCnt,dwCnt1);
     {$ifdef MulV40Overflow}
      fOverflow80386:=fOverflow;
      {-+-+}
      fOverflow:=FALSE;
     {$endif}
      Test8086:=0;
      dw8086:=MulUInt32(dwCnt,dwCnt1);
     {$ifdef MulV40Overflow}
      {-+-+}
      fOverflow8086:=fOverflow;
      if fOverflow8086<>fOverflow80386 then
      begin
        writeln(str, ' - Overflow');
        RunError(255);
      end;
     {$endif}
      if (not fOverflow8086) and
         (not _IsEqualUInt32(dw80386,dw8086)) then
      begin
        writeln(str, ' - Vysledek: (', dwCnt, '*', dwCnt1,')=', dw8086, ' x ', dw80386);
        RunError(255);
      end;
{
      if not _IsEqualUInt32(dw80386, dwCnt*dwCnt1) then
      begin
        writeln(str, ' - Vysledek: (', dwCnt, '*', dwCnt1,')=', dwCnt*dwCnt1, ' x ', dw80386);
        RunError(255);
      end;
}
     {$ifdef KEY}
      if keypressed then halt;
     {$endif}
     {$ifdef MulV40Overflow}
      dwCnt1:=_IncUInt32Ex(_dwCnt1, 139737);
     {$else}
      dwCnt1:=_IncUInt32Ex(_dwCnt1, 3);
      if not (dwCnt1<65548) then break;
      {$endif}
      if _IsLessUInt32(dwCnt1,_dwCnt1) then break;
      _dwCnt1:=dwCnt1;
      if theTimer.TstTime(100000{100s}) then
      begin
        Writeln(str, ' - ', LongIntStrHex(dwCnt1));
        theTimer.SaveTime;
      end;
    end;
   {$ifdef MulV40Overflow}
    dwCnt:=_IncUInt32Ex(_dwCnt, 61673);
   {$else}
    dwCnt:=_IncUInt32Ex(_dwCnt, 3);
    if not (dwCnt<65548) then break;
   {$endif}
    if _IsLessUInt32(dwCnt,_dwCnt) then break;
    _dwCnt:=dwCnt;
  end;
*)
  Test8086:=3;
  { testy na deleni }
  if DivUInt32(30, 6)<>5 then RunError(255);
  if DivUInt32(9000000, 3000) <> 3000 then RunError(255);
  if DivUInt32(2036700000, 6789) <> 300000 then RunError(255);
  if DivUInt32(300000, 300000) <> 1 then RunError(255);
 {$ifdef DivByZero}
  writeln(str, ' - Vygenerovani RunError(200)');
  if DivUInt32( 300000, 0) <> 0 then RunError(255);
 {$endif}
  writeln(str, ' - Testy na deleni');
  dwCnt:=0;
  _dwCnt:=0;
  theTimer.SaveTime;
  while TRUE do
  begin
    writeln(str, ' - dwCnt: ', dwCnt);
    dwCnt1:=1;
    _dwCnt1:=1;
    while TRUE do
    begin
      Test8086:=3;
      dw80386:=DivUInt32(dwCnt,dwCnt1);
      Test8086:=0;
      dw8086:=DivUInt32(dwCnt,dwCnt1);
      if (not _IsEqualUInt32(dw80386,dw8086)) then
      begin
        writeln(str, ' - Vysledek: (', dwCnt, 'div', dwCnt1,')=', dw8086, ' x ', dw80386);
        RunError(255);
      end;
      if not _IsEqualUInt32(dw80386, dwCnt div dwCnt1) then
      begin
        writeln(str, ' - Vysledek: (', dwCnt, '*', dwCnt1,')=', dwCnt div dwCnt1, ' x ', dw80386);
        RunError(255);
      end;
     {$ifdef KEY}
      if keypressed then halt;
     {$endif}
     {$ifdef DivV40Overflow}
      dwCnt1:=_IncUInt32Ex(_dwCnt1, 139737);
     {$else}
      dwCnt1:=_IncUInt32Ex(_dwCnt1, 3);
      if not (dwCnt1<65548) then break;
     {$endif}
      if _IsLessUInt32(dwCnt1,_dwCnt1) then break;
      _dwCnt1:=dwCnt1;
      if theTimer.TstTime(100000{100s}) then
      begin
        Writeln(str, ' - ', LongIntStrHex(dwCnt1));
        theTimer.SaveTime;
      end;
    end;
   {$ifdef DivV40Overflow}
    dwCnt:=_IncUInt32Ex(_dwCnt, 61673);
   {$else}
    dwCnt:=_IncUInt32Ex(_dwCnt, 3);
    if not (dwCnt<65548) then break;
   {$endif}
    if _IsLessUInt32(dwCnt,_dwCnt) then break;
    _dwCnt:=dwCnt;
  end;

  Test8086:=3;
  { testy na zbytek }
  if ModUInt32(33, 6)<>3 then RunError(255);
  if ModUInt32(9000123, 3000) <> 123 then RunError(255);
  if ModUInt32(203670234, 10000) <> 234 then RunError(255);
  if ModUInt32(300000, 300000) <> 0 then RunError(255);
 {$ifdef ModByZero}
  writeln(str, ' - Vygenerovani RunError(200)');
  if ModUInt32( 300000, 0) <> 0 then RunError(255);
 {$endif}
  writeln(str, ' - Testy na zbytek');
  dwCnt:=0;
  _dwCnt:=0;
  theTimer.SaveTime;
  while TRUE do
  begin
    writeln(str, ' - dwCnt: ', dwCnt);
    dwCnt1:=1;
    _dwCnt1:=1;
    while TRUE do
    begin
      Test8086:=3;
      dw80386:=ModUInt32(dwCnt,dwCnt1);
      Test8086:=0;
      dw8086:=ModUInt32(dwCnt,dwCnt1);
      if (not _IsEqualUInt32(dw80386,dw8086)) then
      begin
        writeln(str, ' - Vysledek: (', dwCnt, 'mod', dwCnt1,')=', dw8086, ' x ', dw80386);
        RunError(255);
      end;
      if not _IsEqualUInt32(dw80386, dwCnt mod dwCnt1) then
      begin
        writeln(str, ' - Vysledek: (', dwCnt, '*', dwCnt1,')=', dwCnt mod dwCnt1, ' x ', dw80386);
        RunError(255);
      end;
     {$ifdef KEY}
      if keypressed then halt;
     {$endif}
     {$ifdef ModV40Overflow}
      dwCnt1:=_IncUInt32Ex(_dwCnt1, 139737);
     {$else}
      dwCnt1:=_IncUInt32Ex(_dwCnt1, 3);
      if not (dwCnt1<65548) then break;
     {$endif}
      if _IsLessUInt32(dwCnt1,_dwCnt1) then break;
      _dwCnt1:=dwCnt1;
      end;
   {$ifdef ModV40Overflow}
    dwCnt:=_IncUInt32Ex(_dwCnt, 61673);
   {$else}
    dwCnt:=_IncUInt32Ex(_dwCnt, 3);
    if not (dwCnt<65548) then break;
   {$endif}
    if _IsLessUInt32(dwCnt,_dwCnt) then break;
    _dwCnt:=dwCnt;
  end;

  { testy na rotaci doleva }
  if ShlUInt32($1010, 6)<>$40400 then RunError(255);
  if ShlUInt32($4B, 10)<>$12C00 then RunError(255);
  if ShlUInt32($4B, 31)<>$80000000 then RunError(255);
  if ShlUInt32($4A, 31)<>$0 then RunError(255);
  { testy rotaci na 386 a V40 }
  dwCnt:=0;
  dwCnt1:=0;
  for bRot:=0 to 33 do
  begin
    dwCnt:=0;
    dwCnt1:=0;
    writeln(str, ' - Testy na rotaci doleva: ', bRot);
    while TRUE do
    begin
      Test8086:=3;
      dw80386:=ShlUInt32(dwCnt, bRot);
      {-+-+}
      Test8086:=0;
      dw8086:=ShlUInt32(dwCnt, bRot);
      {-+-+}
      if not _IsEqualUInt32(dw80386,dw8086) then
      begin
        writeln(str,' - Vysledek: (', dwCnt, 'shl', bRot,')=', dw8086, ' x ', dw80386);
        RunError(255);
      end;
     {$ifdef KEY}
      if keypressed then halt;
     {$endif}
      dwCnt:=_IncUInt32Ex(dwCnt1, 1);
      if dwCnt<dwCnt1 then break;
      dwCnt1:=dwCnt;
    end;
  end;

  { testy na rotaci doprava }
  if ShrUInt32($40400, 6)<>$1010 then RunError(255);
  if ShrUInt32($12C00, 10)<>$4B then RunError(255);
  if ShrUInt32($80000000, 31)<>$1 then RunError(255);
  if ShrUInt32($40000000, 31)<>$0 then RunError(255);
  { testy rotaci na 386 a V40 }
  dwCnt:=0;
  dwCnt1:=0;
  for bRot:=0 to 33 do
  begin
    dwCnt:=0;
    dwCnt1:=0;
    writeln(str, ' - Testy na rotaci doprava: ', bRot);
    while TRUE do
    begin
      Test8086:=3;
      dw80386:=ShrUInt32(dwCnt, bRot);
      Test8086:=0;
      dw8086:=ShrUInt32(dwCnt, bRot);
      if not _IsEqualUInt32(dw80386,dw8086) then
      begin
        writeln(str, ' - Vysledek: (', dwCnt, 'shr', bRot,')=', dw8086, ' x ', dw80386);
        RunError(255);
      end;
     {$ifdef KEY}
      if keypressed then halt;
     {$endif}
      dwCnt:=_IncUInt32Ex(dwCnt1, 1);
      if dwCnt<dwCnt1 then break;
      dwCnt1:=dwCnt;
     end;
  end;

  writeln(str, ' - Testy probehly bez chyby');

  Terminate;
end;


procedure MyExitProc; far;
begin
  ExitProc:=OldExitProc;

  if ExitCode<>0 then
  begin
    writeln('ExitCode: ',ExitCode, ', ErrAddr: ', PtrToStr(ErrorAddr));
  end;
 {$ifdef VerMC}
  repeat until false;
 {$endif}
end;


var
  key:Char;
begin
  clrscr;
  writeln('Spusteni programu - Retos');

  OldExitProc:=ExitProc;
  ExitProc:=@MyExitProc;

  StartMain(200, 254);
  InitInterruptStack(1, 254);
  StartTimeSlicing(8);


  Process('p1');
  Process('p2');

  repeat
    if KeyPressed then
    begin
      key:=ReadKey;
    end;
    Wait(1);
  until UpCase(key)='X';

  Abort('*');

  TerminateMain;

  writeln('Testy probehly bez chyby');
 {$ifdef VerMC}
  repeat until false;
 {$endif}

end.