OBJNAM EXIPCH.LIT ; Created 25-Dec-85, Last modified 26-Jan-87
; by Irv Bromberg, Medic/OS Consultants, 78 Wildginger Way, Toronto,
; CANADA  M3H 5X1
RADIX 10
VEDIT=4
VMINOR=3
VMAJOR=1
VSUB=0

IF EQ,1
Edit history:
26-Jan-87  1.3(4)  revised to work with AMOS/L 1.3B

Syntax: EXIPCH

Patches EXIT monitor call so that the WaitOIP loop time wasting is
drastically reduced. EXIPCH must be invoked before any SYSTEM commands
are used in AMOSL.INI file (preferably after the first TRMDEF).  Does
not install itself it beyond addressing range (message issued). With
this patch installed the EXIT WaitOIP loop pauses 50ms each time around
the loop (using a SLEEP instruction) instead of consuming all CPU time
waiting for output-in-progress to finish.  (EXIT waits for OIP to clear
before restoring the Terminal Status Word that existed before the last
executed command was invoked.)

EXIPCH can be used after system bootup to check if it has already installed
the EXIT patch.  The message will either be "%EXIT patch already installed"
or "?EXIT patch must be installed before any SYSTEM commands".

Installation tip:  Use early in the bootup INI file to prevent "out of
addressing range" condition.  Typically it may be necessary to put TINPCH
after the first TRMDEF (occasionally before the first TRMDEF) and to move
the JOBALC statements to a position following the TRMDEFs.

Tested under AMOS/L 1.2A and 1.3, 1.3B, operates correctly.

Essentially all AMOS/L installations will gain more CPU processing time
by installing this patch, but the benefit will be much more noticeable
when terminals are at a low baud rate and/or if multiplexor emulation is
being used on the CPU.  This patch to the operating system when used
together with the TINPCH command eliminates the CPU time wasting problem
that is experienced with heavy use of multiplexor emulation (see
AMUS.LOG Nov/85 report on Multiplexor Emulation using Alpha Micro Computers).

ENDC

SEARCH SYS
SEARCH SYSSYM
SEARCH TRM

JCB     =A0
Block   =A1
Table   =A2
Buffer  =A2
Patch   =A3
Target  =A4
TCB     =A5
Atemp   =A6

Number  =D1
Size    =D2

       PHDR    -1,0,PH$REE!PH$REU

       MOV     ^O50,Table              ; get address of EM1010 routine
Search: CMPW    (Table)+,#^O47165       ; search for RTN instruction, leaving
       BNE     Search                  ; Table register -->base of SVCA table
       ADD     #2*^O11,Table           ; add offset to EXIT SVCA
       SUB     Target,Target           ; search for target address
       ADDW    @Table,Target           ; =address of EXIT routine
10$:    CMPW    (Target)+,#^H4A12       ; find TSTB @A2 instruction
       BNE     10$
       CMPW    8.(Target),#^H0A046     ; is SLEEP monitor call here?
       BNE     ChkUp                   ; no, check if system has booted
       TYPECR  <%EXIT patch already installed>
       EXIT

ChkUp:  MOV     SYSTEM,D7               ; has final SYSTEM command been given?
       AND     #SY$UP,D7
       BEQ     ChkSYS                  ; if so abort with error message
Before: TYPECR  <?EXIT patch must be installed before any SYSTEM commands>
       EXIT
ChkSYS: TST     SYSBAS                  ; any SYSTEM commands executed?
       BNE     Before                  ; yes, abort with error message

ChkRng: ; Check if within addressing range (if not EXIPCH must be moved to
       ; earlier position in AMOSL.INI file)
       ; calculate value of displacement that will be needed
       SUBW    #2,Target               ; undo last post-increment
       MOV     MEMBAS,Block            ; index available memory
       MOV     Block,Number
       SUB     Target,Number
       SUB     #2,Number               ; slight adjustment
       CMP     Number,#^H7FFF          ; cannot exceed +32K distance
       BLO     Proceed                 ; all OK, proceed with patch
       TYPECR  <?Too late to install EXIT patch - out of addressing range>
       EXIT

Proceed:LEA     Patch,PRGBAS            ; index EXIT patch routine
       MOVW    #<PRGEND-PRGBAS-2>,Size ; get size of block (-2/2 for DBF loop)
       LSRW    Size                    ; /2 for 16-bit word block move

BlkMov: MOVW    (Patch)+,(Block)+       ; copy patch onto end of monitor
       DBF     Size,BlkMov
       MOV     Block,MEMBAS            ; update MEMBAS
       MOVW    #^H4EBA,(Target)+       ; change CMP to CALL
       MOVW    Number,(Target)+        ; follow with displacement
       TYPECR  <EXIT Wait OIP loop patched>    ; successfull!
       EXIT

; EXIPCH.LIT substitutes this WaitOIP loop for the time-wasting
; one originally in the EXIT monitor call:

PRGBAS:
WaitOIP:        ; patch to EXIT monitor call wait for OIP to finish loop
               ; passed A2=user's TCB
       TSTB    @A2                     ; output still in progress?
       BPL     Done                    ; no, done with WaitOIP routine
       SLEEP   #500                    ; wait 50ms
       BR      WaitOIP                 ; and go back to try again
Done:   RTN

PRGEND: NOP

       END