
  {*********************************************************}
  {*                  TPINLINE.INC 4.03                    *}
  {*        Copyright (c) TurboPower Software 1987.        *}
  {* Portions copyright (c) Sunny Hill Software 1985, 1986 *}
  {*     and used under license to TurboPower Software     *}
  {*                 All rights reserved.                  *}
  {*********************************************************}

type
  JumpRecord = record
                 SpReg, BpReg : Word;
                 JmpPt : Pointer;
               end;

  procedure SetJump(var JumpDest : JumpRecord);
    {-Save current SP, BP, and a jump destination}
    inline(
      $5F/                   {pop di           ;di = Ofs(JmpDest)}
      $07/                   {pop es           ;es = Seg(JmpDest)}
      $26/$89/$25/           {mov es:[di],sp   ;save sp}
      $26/$89/$6D/$02/       {mov es:[di+2],bp ;save bp}
      $E8/$00/$00/           {call null        ;push IP onto stack}
                             {null:}
      $58/                   {pop ax           ;pop into ax}
      $05/$0C/$00/           {add ax,12        ;point to "next:"}
      $26/$89/$45/$04/       {mov es:[di+4],ax ;save jump offset}
      $26/$8C/$4D/$06);      {mov es:[di+6],cs ;save jump segment}
                             {next:}

  procedure LongJump(var JumpDest : JumpRecord);
    {-Restore SP, BP, and jump to JumpDest.JmpPt}
    inline(
      $5F/                   {pop di            ;di = Ofs(JumpDest)}
      $07/                   {pop es            ;es = Seg(JumpDest)}
      $26/$8B/$25/           {mov sp,es:[di]    ;restore sp}
      $26/$8B/$6D/$02/       {mov bp,es:[di+2]  ;restore bp}
      $26/$FF/$6D/$04);      {jmp far es:[di+4] ;jump far to JumpDest.JmpPt}

  procedure FarCall(ProcAddr : Pointer);
    {-ProcAddr is the address of a routine to be called far. Can be used to
      implement jump tables if procedures take no parameters.}
    inline(
      $89/$E3/               {mov bx,sp}
      $36/$FF/$1F/           {call far dword ptr ss:[bx]}
      $81/$C4/$04/$00);      {add sp,4}

  procedure NearCall(ProcOfs : Word);
    {-ProcOfs is the offset of a routine to be called near.}
    inline(
      $5B/                   {pop bx}
      $FF/$D3);              {call bx}

  procedure JumpToOldIsr(OldIsr : Pointer);
    {-Jump to previous ISR from an interrupt procedure.}
    inline(
      $5B/                   {pop bx          ;BX = Ofs(OldIsr)}
      $58/                   {pop ax          ;AX = Seg(OldIsr)}
      $87/$5E/$0E/           {xchg bx,[bp+14] ;Switch old BX and Ofs(OldIsr)}
      $87/$46/$10/           {xchg ax,[bp+16] ;Switch old AX and Seg(OldIsr)}
      $89/$EC/               {mov sp,bp       ;Restore SP}
      $5D/                   {pop bp          ;Restore BP}
      $07/                   {pop es          ;Restore ES}
      $1F/                   {pop ds          ;Restore DS}
      $5F/                   {pop di          ;Restore DI}
      $5E/                   {pop si          ;Restore SI}
      $5A/                   {pop dx          ;Restore DX}
      $59/                   {pop cx          ;Restore CX}
                             {;BX and AX restored earlier; their places on stack}
                             {;now have OldIsr, which is where return will go}
      $CB);                  {retf            ;Chain to OldIsr}

  procedure CallOldIsr(OldIsr : Pointer);
    {-Call previous ISR from an interrupt procedure. Destroys BX.}
    inline(
      $89/$E3/               {mov bx,sp        ;set up stack frame}
      $9C/                   {pushf            ;push flags to simulate int}
      $36/$FF/$1F/           {call far ss:[bx] ;call OldIsr}
      $81/$C4/$04/$00);      {add sp,4         ;get rid of OldIsr}

  function HiWord(L : LongInt) : Word;
    {-Return high-order word of L}
    inline(
      $44/                   {inc sp ;ignore low word}
      $44/                   {inc sp}
      $58);                  {pop ax ;pop high word into AX}

  function LoWord(L : LongInt) : Word;
    {-Return low-order word of L}
    inline(
      $58/                   {pop ax ;pop low word into AX}
      $44/                   {inc sp ;ignore high word}
      $44);                  {inc sp}

  function SwapWord(L : LongInt) : LongInt;
    {-Swap low- and high-order words of L}
    inline(
      $5A/                   {pop dx ;pop low word into DX}
      $58);                  {pop ax ;pop high word into AX}

  function Normalized(P : Pointer) : Pointer;
    {-Return P as a normalized pointer}
    inline(
      $58/                   {pop ax    ;pop offset into AX}
      $5A/                   {pop dx    ;pop segment into DX}
      $89/$C3/               {mov bx,ax ;BX = Ofs(P^)}
      $B1/$04/               {mov cl,4  ;CL = 4}
      $D3/$EB/               {shr bx,cl ;BX = Ofs(P^) div 16}
      $01/$DA/               {add dx,bx ;add BX to segment}
      $25/$0F/$00);          {and ax,$F ;mask out unwanted bits in offset}

  procedure SetFlag(var Flags : Word; FlagMask : Word);
    {-Set the bit(s) specified by FlagMask in Flags}
    inline(
      $58/                   {pop ax        ;FlagMask into AX}
      $5F/                   {pop di}
      $07/                   {pop es        ;ES:DI => Flags}
      $26/$09/$05);          {or es:[di],ax ;Flags := Flags or FlagMask}

  procedure ClearFlag(var Flags : Word; FlagMask : Word);
    {-Clear the bit(s) specified by FlagMask in Flags}
    inline(
      $58/                   {pop ax         ;FlagMask into AX}
      $5F/                   {pop di}
      $07/                   {pop es         ;ES:DI => Flags}
      $F7/$D0/               {not ax         ;AX := not AX}
      $26/$21/$05);          {and es:[di],ax ;Flags := Flags and not FlagMask}

  function FlagIsSet(Flags, FlagMask : Word) : Boolean;
    {-Returns True if the bit specified by FlagMask is set in Flags}
    inline(
      $5A/                   {pop dx    ;FlagMask into DX}
      $58/                   {pop ax    ;Flags into AX}
      $21/$D0/               {and ax,dx ;Mask out everything not in FlagMask}
      $74/$03/               {jz  Exit}
      $B8/$01/$00);          {mov ax,1  ;AX = Ord(True)}
                             {Exit:}

