home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / at / atperf.arc / TIME.ASM < prev   
Encoding:
Assembly Source File  |  1988-04-07  |  42.6 KB  |  1,472 lines

  1.         NAME    TIME
  2.         include MASM.INC
  3.  
  4. _TEXT    SEGMENT  PARA PUBLIC 'CODE'
  5. _TEXT    ENDS
  6. CONST    SEGMENT  PARA PUBLIC 'CONST'
  7. CONST    ENDS
  8. _BSS    SEGMENT  PARA PUBLIC 'BSS'
  9. _BSS    ENDS
  10. _DATA    SEGMENT  PARA PUBLIC 'DATA'
  11. _DATA    ENDS
  12. DGROUP    GROUP    CONST,    _BSS,    _DATA
  13.     ASSUME    CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
  14. TESTSEG SEGMENT PARA PUBLIC 'TEST'
  15. TESTSEG_START    DW    32767 DUP (?)
  16. TESTSEG ENDS
  17. PPI_PORT    EQU    061H
  18. TIMER2_PORT    EQU    042H
  19. TIMER_CTRL    EQU    043H
  20. _DATA        SEGMENT
  21. VIDBASE     DW    0B800H
  22. EMMBASE     DW    9000H
  23. PID        DW    ?
  24. STATUSW     DW    ?
  25. EMM_NAME    DB    "EMMXXXX0"
  26.  
  27. ; Local flags for instruction relocation
  28. ; When set, instruction loop has been aligned on a dword boundary
  29.  
  30. LCL_FLAG    DW    0        ; Initially, none aligned
  31. @LCL_MUL    equ    8000h        ; _MULTIME
  32. @LCL_WMOV    equ    4000h        ; _WMOVTIME
  33. @LCL_DMOV    equ    2000h        ; _DMOVTIME
  34. @LCL_DLOD    equ    1000h        ; _DLODTIME
  35. @LCL_DRAM    equ    0800h        ; _DRAMTIME
  36. @LCL_DIMM    equ    0400h        ; _DIMMTIME
  37. @LCL_BCLC    equ    0200h        ; _BCLCTIME
  38. @LCL_BDAA    equ    0100h        ; _BDAATIME
  39. @LCL_WPSH    equ    0080h        ; _WPSHTIME
  40. @LCL_DPSH    equ    0040h        ; _DPSHTIME
  41. @LCL_FP     equ    0020h        ; _FPTIME
  42. @LCL_WEMP    equ    0010h        ; _WEMPTIME
  43. @LCL_DEMP    equ    0008h        ; _DEMPTIME
  44.  
  45. _DATA        ENDS
  46. _TEXT        SEGMENT para
  47. ;***************************************************************;
  48. ;    _MULTIME                        ;
  49. ;    TIME EXECUTION OF MULTIPLY INSTRUCTIONS         ;
  50. ;***************************************************************;
  51.         PUBLIC    _MULTIME
  52. _MULTIME    PROC    NEAR
  53.     PUSH    BP            ; SAVE FRAME
  54.     MOV    BP, SP            ;
  55.     PUSH    DI            ; SAVE DI
  56.  
  57.     ALIGN    MUL,M            ; Align instructions on dword boundary
  58.  
  59.     CALL    SETUP_TIMER        ; SET UP TIMER
  60.     MOV    DI, 08000H        ; SET DI
  61.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  62.     ADD    AX, 99            ; ROUND UP
  63.     MOV    CX, 100         ; DIVIDE BY 100 =
  64.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  65.     MOV    CL, AL            ;  PER PASS
  66.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  67.     MOV    BL, AL            ; SAVE IN BL
  68.     OR    AL, 1            ; SET TIMER ENABLE BIT
  69.     CLI                ; STOP INTERRUPTS
  70.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  71.     INSTR_ALIGN            ; Ensure instruction alignment
  72. ML:    REPT    100            ; DO 100 MULTIPLIES
  73.     MUL    DI            ;
  74.     ENDM                ; END MACRO
  75.     DEC    CX            ; COUNT THIS PASS
  76.     JZ    MD            ; JUMP IF COMPLETE
  77.     JMP    ML            ; LOOP BACK IF NOT DONE
  78. MD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  79.     OUT    PPI_PORT, AL        ;
  80.     STI                ; START INTERRUPTS
  81.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  82.     POP    DI            ; RESTORE DI
  83.     POP    BP            ; RESTORE BP
  84.     RET                ; RETURN
  85. _MULTIME    ENDP
  86. ;***************************************************************;
  87. ;    _WMOVTIME                        ;
  88. ;    TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME)    ;
  89. ;***************************************************************;
  90.         PUBLIC    _WMOVTIME
  91. _WMOVTIME    PROC    NEAR
  92.     PUSH    BP            ; SAVE FRAME
  93.     MOV    BP, SP            ;
  94.     PUSH    DI            ; SAVE DI
  95.  
  96.     ALIGN    WMOV,I            ; Align instructions on dword boundary
  97.  
  98.     CALL    SETUP_TIMER        ; SET UP TIMER
  99.     LEA    BX, IL            ; PRIME TEST AREA
  100.     MOV    CX, 200         ;
  101.     CALL    PRIME            ;
  102.     MOV    DI, 0            ; CLEAR DI
  103.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  104.     ADD    AX, 99            ; ROUND UP
  105.     MOV    CX, 100         ; DIVIDE BY 100 =
  106.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  107.     MOV    CL, AL            ;  PER PASS
  108.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  109.     MOV    BL, AL            ; SAVE IN BL
  110.     OR    AL, 1            ; SET TIMER ENABLE BIT
  111.     CLI                ; STOP INTERRUPTS
  112.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  113.     INSTR_ALIGN            ; Ensure instruction alignment
  114. IL:    REPT    100            ; DO 100 MOVES
  115.     MOV    DX, BX            ;
  116.     ENDM                ; END MACRO
  117.     DEC    CX            ; COUNT THIS PASS
  118.     JZ    ID            ; JUMP IF COMPLETE
  119.     JMP    IL            ; LOOP BACK IF NOT DONE
  120. ID:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  121.     OUT    PPI_PORT, AL        ;
  122.     STI                ; START INTERRUPTS
  123.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  124.     POP    DI            ; RESTORE DI
  125.     POP    BP            ; RESTORE BP
  126.     RET                ; RETURN
  127. _WMOVTIME    ENDP
  128. ;***************************************************************;
  129. ;    _DMOVTIME                        ;
  130. ;    TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME)    ;
  131. ;***************************************************************;
  132.         PUBLIC    _DMOVTIME
  133. _DMOVTIME    PROC    NEAR
  134.     PUSH    BP            ; SAVE FRAME
  135.     MOV    BP, SP            ;
  136.     PUSH    DI            ; SAVE DI
  137.  
  138.     ALIGN    DMOV,N            ; Align instructions on dword boundary
  139.  
  140.     CALL    SETUP_TIMER        ; SET UP TIMER
  141.     LEA    BX, NL            ; PRIME TEST AREA
  142.     MOV    CX, 400         ;
  143.     CALL    PRIME            ;
  144.     MOV    DI, 0            ; CLEAR DI
  145.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  146.     ADD    AX, 99            ; ROUND UP
  147.     MOV    CX, 100         ; DIVIDE BY 100 =
  148.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  149.     MOV    CL, AL            ;  PER PASS
  150.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  151.     MOV    BL, AL            ; SAVE IN BL
  152.     OR    AL, 1            ; SET TIMER ENABLE BIT
  153.     CLI                ; STOP INTERRUPTS
  154.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  155.     INSTR_ALIGN            ; Ensure instruction alignment
  156. NL:    REPT    100            ; DO 100 MOV DX,05555H
  157.     DB    0C7H, 0C2H, 055H, 055H    ;  THE LONG WAY (WITH MOD R/M)
  158.     ENDM                ; END MACRO
  159.     DEC    CX            ; COUNT THIS PASS
  160.     JZ    ND            ; JUMP IF COMPLETE
  161.     JMP    NL            ; LOOP BACK IF NOT DONE
  162. ND:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  163.     OUT    PPI_PORT, AL        ;
  164.     STI                ; START INTERRUPTS
  165.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  166.     POP    DI            ; RESTORE DI
  167.     POP    BP            ; RESTORE BP
  168.     RET                ; RETURN
  169. _DMOVTIME    ENDP
  170. ;***************************************************************;
  171. ;    _DLODTIME                        ;
  172. ;    TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME)    ;
  173. ;***************************************************************;
  174.  
  175.         PUBLIC    FIRSTSEG,NEXTSEG
  176. FIRSTSEG DW    0000h            ;  0 KB in paras
  177. NEXTSEG DW    1000h            ; 64 KB in paras
  178.  
  179.         PUBLIC    _DLODTIME
  180. _DLODTIME    PROC    NEAR
  181.     PUSH    BP            ; SAVE FRAME
  182.     MOV    BP, SP            ;
  183.     PUSH    DI            ; SAVE DI
  184.     PUSH    DS            ;
  185.  
  186.     ALIGN    DLOD,LOD        ; Align instructions on dword boundary
  187.  
  188.     CALL    SETUP_TIMER        ; SET UP TIMER
  189.     LEA    BX, LODL        ; PRIME TEST AREA
  190.     AND    BX, not (4-1)        ; Round down to dowrd boundary
  191.     MOV    CX, LODD-LODL        ; Length of test area
  192.     CALL    PRIME            ;
  193.     MOV    DI, 0            ; CLEAR DI
  194.     MOV    DS, FIRSTSEG        ; Set to initial segment
  195.     ASSUME    DS:NOTHING        ; Tell the assembler about it
  196.     DB    03EH            ; Use DS:
  197.     MOV    AX,DS:[0]        ; Ensure loop data value is cached
  198.  
  199.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  200.     ADD    AX, 99            ; ROUND UP
  201.     MOV    CX, 100         ; DIVIDE BY 100 =
  202.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  203.     MOV    CL, AL            ;  PER PASS
  204.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  205.     MOV    BL, AL            ; SAVE IN BL
  206.     OR    AL, 1            ; SET TIMER ENABLE BIT
  207.     CLI                ; STOP INTERRUPTS
  208.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  209.     INSTR_ALIGN            ; Ensure instruction alignment
  210. LODL:    REPT    100            ; DO 100:
  211.     DB    03EH            ; Use DS:
  212.     MOV    AX,DS:[0]        ; Read constant data item
  213.     ENDM                ; END MACRO
  214.     DEC    CX            ; COUNT THIS PASS
  215.     JZ    LODD            ; JUMP IF COMPLETE
  216.     JMP    LODL            ; LOOP BACK IF NOT DONE
  217. LODD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  218.     OUT    PPI_PORT, AL        ;
  219.     STI                ; START INTERRUPTS
  220.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  221.     POP    DS            ;
  222.     ASSUME    DS:DGROUP        ; Tell the assembler about it
  223.     POP    DI            ; RESTORE DI
  224.     POP    BP            ; RESTORE BP
  225.     RET                ; RETURN
  226. _DLODTIME    ENDP
  227. ;***************************************************************;
  228. ;    _DRAMTIME                        ;
  229. ;    TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME)    ;
  230. ;***************************************************************;
  231.  
  232.         PUBLIC    _DRAMTIME
  233. _DRAMTIME    PROC    NEAR
  234.     PUSH    BP            ; SAVE FRAME
  235.     MOV    BP, SP            ;
  236.     PUSH    DI            ; SAVE DI
  237.     PUSH    DS            ;
  238.     PUSH    ES            ;
  239.  
  240.     ALIGN    DRAM,RAM        ; Align instructions on dword boundary
  241.  
  242.     CALL    SETUP_TIMER        ; SET UP TIMER
  243.     LEA    BX, RAML        ; PRIME TEST AREA
  244.     AND    BX, not (4-1)        ; Round down to dowrd boundary
  245.     MOV    CX, RAMD-RAML        ; Length of test area
  246.     CALL    PRIME            ;
  247.     MOV    DI, FIRSTSEG        ; SET SEG REGS TO
  248.     MOV    DS, DI            ;  64K DISTANT LOCATIONS
  249.     ASSUME    DS:NOTHING        ; Tell the assembler about it
  250.     ADD    DI,NEXTSEG        ;
  251.     MOV    ES, DI            ; SET ES
  252.     ASSUME    ES:NOTHING        ; Tell the assembler about it
  253.     ADD    DI,NEXTSEG        ;
  254.     PUSH    DI            ;
  255.     DB    00FH, 0A1H        ; POP FS
  256.     ADD    DI,NEXTSEG        ;
  257.     PUSH    DI            ;
  258.     DB    00FH, 0A9H        ; POP GS
  259.     MOV    DI, 0            ; CLEAR DI
  260.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  261.     ADD    AX, 99            ; ROUND UP
  262.     MOV    CX, 100         ; DIVIDE BY 100 =
  263.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  264.     MOV    CL, AL            ;  PER PASS
  265.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  266.     MOV    BL, AL            ; SAVE IN BL
  267.     OR    AL, 1            ; SET TIMER ENABLE BIT
  268.     CLI                ; STOP INTERRUPTS
  269.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  270.     INSTR_ALIGN            ; Ensure instruction alignment
  271. RAML:    REPT    25            ; DO 100:
  272.     DB    03EH, 0A1H        ; MOV AX, DS:WORD PTR 0
  273.     DW    0            ;
  274.     DB    026H, 0A1H        ; MOV AX, ES:WORD PTR 0
  275.     DW    0            ;
  276.     DB    064H, 0A1H        ; MOV AX, FS:WORD PTR 0
  277.     DW    0            ;
  278.     DB    065H, 0A1H        ; MOV AX, GS:WORD PTR 0
  279.     DW    0            ;
  280.     ENDM                ; END MACRO
  281.     DEC    CX            ; COUNT THIS PASS
  282.     JZ    RAMD            ; JUMP IF COMPLETE
  283.     JMP    RAML            ; LOOP BACK IF NOT DONE
  284. RAMD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  285.     OUT    PPI_PORT, AL        ;
  286.     STI                ; START INTERRUPTS
  287.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  288.     POP    ES            ;
  289.     ASSUME    ES:DGROUP        ; Tell the assembler about it
  290.     POP    DS            ;
  291.     ASSUME    DS:DGROUP        ; Tell the assembler about it
  292.     POP    DI            ; RESTORE DI
  293.     POP    BP            ; RESTORE BP
  294.     RET                ; RETURN
  295. _DRAMTIME    ENDP
  296. ;***************************************************************;
  297. ;    _DIMMTIME                        ;
  298. ;    TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME)    ;
  299. ;***************************************************************;
  300.         PUBLIC    _DIMMTIME
  301. _DIMMTIME    PROC    NEAR
  302.     PUSH    BP            ; SAVE FRAME
  303.     MOV    BP, SP            ;
  304.     PUSH    DI            ; SAVE DI
  305.  
  306.     ALIGN    DIMM,IMM        ; Align instructions on dword boundary
  307.  
  308.     CALL    SETUP_TIMER        ; SET UP TIMER
  309.     LEA    BX, IMML        ; PRIME TEST AREA
  310.     MOV    CX, 400         ;
  311.     CALL    PRIME            ;
  312.     MOV    DI, 0            ; CLEAR DI
  313.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  314.     ADD    AX, 99            ; ROUND UP
  315.     MOV    CX, 100         ; DIVIDE BY 100 =
  316.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  317.     MOV    CL, AL            ;  PER PASS
  318.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  319.     MOV    BL, AL            ; SAVE IN BL
  320.     OR    AL, 1            ; SET TIMER ENABLE BIT
  321.     CLI                ; STOP INTERRUPTS
  322.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  323.     INSTR_ALIGN            ; Ensure instruction alignment
  324. IMML:    REPT    100            ; DO 100:
  325.     REPT    8            ; 8X:
  326.     DB    066H            ; MOV EDX, 00000000H
  327.     DB    0F7H, 0C2H, 0, 0, 0, 0    ;
  328.     ENDM                ; END MACRO
  329.     ENDM                ; END MACRO
  330.     DEC    CX            ; COUNT THIS PASS
  331.     JZ    IMMD            ; JUMP IF COMPLETE
  332.     JMP    IMML            ; LOOP BACK IF NOT DONE
  333. IMMD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  334.     OUT    PPI_PORT, AL        ;
  335.     STI                ; START INTERRUPTS
  336.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  337.     POP    DI            ; RESTORE DI
  338.     POP    BP            ; RESTORE BP
  339.     RET                ; RETURN
  340. _DIMMTIME    ENDP
  341. ;***************************************************************;
  342. ;    _BCLCTIME                        ;
  343. ;    TIME EXECUTION OF CLC INSTRUCTION (INSTR. READ TIME)    ;
  344. ;***************************************************************;
  345.         PUBLIC    _BCLCTIME
  346. _BCLCTIME    PROC    NEAR
  347.     PUSH    BP            ; SAVE FRAME
  348.     MOV    BP, SP            ;
  349.     PUSH    DI            ; SAVE DI
  350.  
  351.     ALIGN    BCLC,BI         ; Align instructions on dword boundary
  352.  
  353.     CALL    SETUP_TIMER        ; SET UP TIMER
  354.     LEA    BX, BIL         ; PRIME TEST AREA
  355.     MOV    CX, 100         ;
  356.     CALL    PRIME            ;
  357.     MOV    DI, 0            ; CLEAR DI
  358.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  359.     ADD    AX, 99            ; ROUND UP
  360.     MOV    CX, 100         ; DIVIDE BY 100 =
  361.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  362.     MOV    CL, AL            ;  PER PASS
  363.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  364.     MOV    BL, AL            ; SAVE IN BL
  365.     OR    AL, 1            ; SET TIMER ENABLE BIT
  366.     CLI                ; STOP INTERRUPTS
  367.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  368.     INSTR_ALIGN            ; Ensure instruction alignment
  369. BIL:    REPT    100            ; DO 100 INC'S
  370.     INC    DL            ;
  371.     ENDM                ; END MACRO
  372.     DEC    CX            ; COUNT THIS PASS
  373.     JZ    BID            ; JUMP IF COMPLETE
  374.     JMP    BIL            ; LOOP BACK IF NOT DONE
  375. BID:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  376.     OUT    PPI_PORT, AL        ;
  377.     STI                ; START INTERRUPTS
  378.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  379.     POP    DI            ; RESTORE DI
  380.     POP    BP            ; RESTORE BP
  381.     RET                ; RETURN
  382. _BCLCTIME    ENDP
  383. ;***************************************************************;
  384. ;    _BDAATIME                        ;
  385. ;    TIME EXECUTION OF DAA INSTRUCTION (INSTR. READ TIME)    ;
  386. ;***************************************************************;
  387.         PUBLIC    _BDAATIME
  388. _BDAATIME    PROC    NEAR
  389.     PUSH    BP            ; SAVE FRAME
  390.     MOV    BP, SP            ;
  391.     PUSH    DI            ; SAVE DI
  392.  
  393.     ALIGN    BDAA,BX         ; Align instructions on dword boundary
  394.  
  395.     CALL    SETUP_TIMER        ; SET UP TIMER
  396.     LEA    BX, BXL         ; PRIME TEST AREA
  397.     MOV    CX, 100         ;
  398.     CALL    PRIME            ;
  399.     MOV    DI, 0            ; CLEAR DI
  400.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  401.     ADD    AX, 99            ; ROUND UP
  402.     MOV    CX, 100         ; DIVIDE BY 100 =
  403.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  404.     MOV    CL, AL            ;  PER PASS
  405.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  406.     MOV    BL, AL            ; SAVE IN BL
  407.     OR    AL, 1            ; SET TIMER ENABLE BIT
  408.     CLI                ; STOP INTERRUPTS
  409.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  410.     INSTR_ALIGN            ; Ensure instruction alignment
  411. BXL:    REPT    100            ; DO 100 DAA'S
  412.     DAA                ;
  413.     ENDM                ; END MACRO
  414.     DEC    CX            ; COUNT THIS PASS
  415.     JZ    BXD            ; JUMP IF COMPLETE
  416.     JMP    BXL            ; LOOP BACK IF NOT DONE
  417. BXD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  418.     OUT    PPI_PORT, AL        ;
  419.     STI                ; START INTERRUPTS
  420.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  421.     POP    DI            ; RESTORE DI
  422.     POP    BP            ; RESTORE BP
  423.     RET                ; RETURN
  424. _BDAATIME    ENDP
  425. ;***************************************************************;
  426. ;    _BMVSTIME                        ;
  427. ;    TIME EXECUTION OF REP MOVSB INSTRUCTION         ;
  428. ;***************************************************************;
  429.         PUBLIC    _BMVSTIME
  430. _BMVSTIME    PROC    NEAR
  431.     PUSH    BP            ; SAVE FRAME
  432.     MOV    BP, SP            ;
  433.     PUSH    DS            ; SAVE DS
  434.     PUSH    ES            ; SAVE ES
  435.     PUSH    SI            ; SAVE SI
  436.     PUSH    DI            ; SAVE DI
  437.  
  438.     MOV    DI, TESTSEG        ;
  439.     MOV    ES, DI            ;
  440.     MOV    DS, DI            ;
  441.     LEA    SI, TESTSEG_START + 5    ; DS:SI -> TEST SEGMENT
  442.     LEA    DI, TESTSEG_START + 0    ; ES:DI -> TEST SEGMENT
  443.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  444.     CLD                ; SET FORWARD DIRECTION
  445.     REP MOVSB            ; RUN TEST
  446.  
  447.     CALL    SETUP_TIMER        ; SET UP TIMER
  448.     MOV    DI, TESTSEG        ;
  449.     MOV    ES, DI            ;
  450.     MOV    DS, DI            ;
  451.     LEA    SI, TESTSEG_START + 5    ; DS:SI -> TEST SEGMENT
  452.     LEA    DI, TESTSEG_START + 0    ; ES:DI -> TEST SEGMENT
  453.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  454.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  455.     MOV    BL, AL            ; SAVE IN BL
  456.     OR    AL, 1            ; SET TIMER ENABLE BIT
  457.     CLI                ; STOP INTERRUPTS
  458.     CLD                ; SET FORWARD DIRECTION
  459.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  460.     REP MOVSB            ; RUN TEST
  461.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  462.     OUT    PPI_PORT, AL        ;
  463.     STI                ; START INTERRUPTS
  464.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  465.  
  466.     POP    DI            ; RESTORE DI
  467.     POP    SI            ; RESTORE SI
  468.     POP    ES            ; RESTORE ES
  469.     POP    DS            ; RESTORE DS
  470.     POP    BP            ; RESTORE BP
  471.     RET                ; RETURN
  472. _BMVSTIME    ENDP
  473. ;***************************************************************;
  474. ;    _WMVSTIME                        ;
  475. ;    TIME EXECUTION OF REP MOVSW INSTRUCTION         ;
  476. ;***************************************************************;
  477.         PUBLIC    _WMVSTIME
  478. _WMVSTIME    PROC    NEAR
  479.     PUSH    BP            ; SAVE FRAME
  480.     MOV    BP, SP            ;
  481.     PUSH    DS            ; SAVE DS
  482.     PUSH    ES            ; SAVE ES
  483.     PUSH    SI            ; SAVE SI
  484.     PUSH    DI            ; SAVE DI
  485.  
  486.     MOV    DI, TESTSEG        ;
  487.     MOV    ES, DI            ;
  488.     MOV    DS, DI            ;
  489.     LEA    SI, TESTSEG_START + 6    ; DS:SI -> TEST SEGMENT
  490.     LEA    DI, TESTSEG_START + 0    ; ES:DI -> TEST SEGMENT
  491.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  492.     CLD                ; SET FORWARD DIRECTION
  493.     REP MOVSW            ; RUN TEST
  494.  
  495.     CALL    SETUP_TIMER        ; SET UP TIMER
  496.     MOV    DI, TESTSEG        ;
  497.     MOV    ES, DI            ;
  498.     MOV    DS, DI            ;
  499.     LEA    SI, TESTSEG_START + 6    ; DS:SI -> TEST SEGMENT
  500.     LEA    DI, TESTSEG_START + 0    ; ES:DI -> TEST SEGMENT
  501.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  502.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  503.     MOV    BL, AL            ; SAVE IN BL
  504.     OR    AL, 1            ; SET TIMER ENABLE BIT
  505.     CLI                ; STOP INTERRUPTS
  506.     CLD                ; SET FORWARD DIRECTION
  507.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  508.     REP MOVSW            ; RUN TEST
  509.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  510.     OUT    PPI_PORT, AL        ;
  511.     STI                ; START INTERRUPTS
  512.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  513.  
  514.     POP    DI            ; RESTORE DI
  515.     POP    SI            ; RESTORE SI
  516.     POP    ES            ; RESTORE ES
  517.     POP    DS            ; RESTORE DS
  518.     POP    BP            ; RESTORE BP
  519.     RET                ; RETURN
  520. _WMVSTIME    ENDP
  521. ;***************************************************************;
  522. ;    _DMVSTIME                        ;
  523. ;    TIME EXECUTION OF REP MOVSW INSTRUCTION         ;
  524. ;***************************************************************;
  525.         PUBLIC    _DMVSTIME
  526. _DMVSTIME    PROC    NEAR
  527.     PUSH    BP            ; SAVE FRAME
  528.     MOV    BP, SP            ;
  529.     PUSH    DS            ; SAVE DS
  530.     PUSH    ES            ; SAVE ES
  531.     PUSH    SI            ; SAVE SI
  532.     PUSH    DI            ; SAVE DI
  533.  
  534.     DB    066H            ; 32 BIT OPERANDS:
  535.     XOR    DI, DI            ; CLEAR EDI
  536.     DB    066H            ; 32 BIT OPERANDS:
  537.     XOR    SI, SI            ; CLEAR ESI
  538.     DB    066H            ; 32 BIT OPERANDS:
  539.     XOR    CX, CX            ; CLEAR ECX
  540.     MOV    DI, TESTSEG        ;
  541.     MOV    ES, DI            ;
  542.     MOV    DS, DI            ;
  543.     LEA    SI, TESTSEG_START    ; DS:SI -> TEST SEGMENT
  544.     LEA    DI, TESTSEG_START + 0    ; ES:DI -> TEST SEGMENT
  545.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  546.     CLD                ; SET FORWARD DIRECTION
  547.     DB    066H            ; 32 BIT OPERANDS:
  548.     REP MOVSW            ; RUN TEST
  549.  
  550.     CALL    SETUP_TIMER        ; SET UP TIMER
  551.     DB    066H            ; 32 BIT OPERANDS:
  552.     XOR    DI, DI            ; CLEAR EDI
  553.     DB    066H            ; 32 BIT OPERANDS:
  554.     XOR    SI, SI            ; CLEAR ESI
  555.     DB    066H            ; 32 BIT OPERANDS:
  556.     XOR    CX, CX            ; CLEAR ECX
  557.     MOV    DI, TESTSEG        ;
  558.     MOV    ES, DI            ;
  559.     MOV    DS, DI            ;
  560.     LEA    SI, TESTSEG_START    ; DS:SI -> TEST SEGMENT
  561.     LEA    DI, TESTSEG_START + 0    ; ES:DI -> TEST SEGMENT
  562.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  563.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  564.     MOV    BL, AL            ; SAVE IN BL
  565.     OR    AL, 1            ; SET TIMER ENABLE BIT
  566.     CLI                ; STOP INTERRUPTS
  567.     CLD                ; SET FORWARD DIRECTION
  568.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  569.     DB    066H            ; 32 BIT OPERANDS:
  570.     REP MOVSW            ; RUN TEST
  571.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  572.     OUT    PPI_PORT, AL        ;
  573.     STI                ; START INTERRUPTS
  574.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  575.     POP    DI            ; RESTORE DI
  576.     POP    SI            ; RESTORE SI
  577.     POP    ES            ; RESTORE ES
  578.     POP    DS            ; RESTORE DS
  579.     POP    BP            ; RESTORE BP
  580.     RET                ; RETURN
  581. _DMVSTIME    ENDP
  582. ;***************************************************************;
  583. ;    _WPSHTIME                        ;
  584. ;    TIME EXECUTION OF PUSHA INSTRUCTION            ;
  585. ;***************************************************************;
  586.         PUBLIC    _WPSHTIME
  587. _WPSHTIME    PROC    NEAR
  588.     PUSH    BP            ; SAVE FRAME
  589.     MOV    BP, SP            ;
  590.  
  591.     ALIGN    WPSH,WS         ; Align instructions on dword boundary
  592.  
  593.     CALL    SETUP_TIMER        ; SET UP TIMER
  594.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  595.     CWD                ; MAKE DOUBLE WORD
  596.     MOV    CX, 200         ;
  597.     DIV    CX            ; DIVIDE BY MOVS/LOOP
  598.     MOV    CX, AX            ;
  599.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  600.     MOV    BL, AL            ; SAVE IN BL
  601.     OR    AL, 1            ; SET TIMER ENABLE BIT
  602.     CLI                ; STOP INTERRUPTS
  603.     MOV    DX, SS            ; SAVE SS, SP
  604.     MOV    BX, TESTSEG        ; SET STACK TO TEST SEGMENT
  605.     MOV    SS, BX            ;
  606.     MOV    BX, SP            ;
  607.     MOV    SP, OFFSET TESTSEG_START + 4096
  608.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  609.     INSTR_ALIGN            ; Ensure instruction alignment
  610. WSL:    REPT    25            ; PUSH THE REGISTERS
  611.     DB    60H            ;
  612.     ENDM                ; END MACRO
  613.     LOOP    WSL            ; LOOP UNTIL DONE
  614. WSD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  615.     OUT    PPI_PORT, AL        ;
  616.     MOV    SS, DX            ; RESTORE SS, SP
  617.     MOV    SP, BX            ;
  618.     STI                ; START INTERRUPTS
  619.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  620.     MOV    SP, BP            ; PUT THE STACK BACK
  621.     POP    BP            ; RESTORE BP
  622.     RET                ; RETURN
  623. _WPSHTIME    ENDP
  624. ;***************************************************************;
  625. ;    _DPSHTIME                        ;
  626. ;    TIME EXECUTION OF PUSHA INSTRUCTION            ;
  627. ;***************************************************************;
  628.         PUBLIC    _DPSHTIME
  629. _DPSHTIME    PROC    NEAR
  630.     PUSH    BP            ; SAVE FRAME
  631.     MOV    BP, SP            ;
  632.  
  633.     ALIGN    DPSH,DS         ; Align instructions on dword boundary
  634.  
  635.     CALL    SETUP_TIMER        ; SET UP TIMER
  636.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  637.     CWD                ; MAKE DOUBLE WORD
  638.     MOV    CX, 200         ;
  639.     DIV    CX            ; DIVIDE BY MOVS/LOOP
  640.     MOV    CX, AX            ;
  641.     AND    SP, 0FFFCH        ; ALIGN SP
  642.     PUSH    AX            ; DUMMY
  643.     PUSH    BP            ; SAVE BP
  644.     MOV    BP, SP            ;
  645.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  646.     MOV    BL, AL            ; SAVE IN BL
  647.     OR    AL, 1            ; SET TIMER ENABLE BIT
  648.     CLI                ; STOP INTERRUPTS
  649.     MOV    DX, SS            ; SAVE SS, SP
  650.     MOV    BX, TESTSEG        ; SET STACK TO TEST SEGMENT
  651.     MOV    SS, BX            ;
  652.     MOV    BX, SP            ;
  653.     MOV    SP, OFFSET TESTSEG_START + 4096
  654.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  655.     INSTR_ALIGN            ; Ensure instruction alignment
  656. DSL:    REPT    25            ; PUSH THE BIG REGISTERS
  657.     DB    66H, 60H        ;
  658.     ENDM                ; END MACRO
  659.     LOOP    DSL            ; LOOP UNTIL DONE
  660. DSD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  661.     OUT    PPI_PORT, AL        ;
  662.     MOV    SS, DX            ; RESTORE SS, SP
  663.     MOV    SP, BX            ;
  664.     STI                ; START INTERRUPTS
  665.     POP    BP            ;
  666.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  667.     MOV    SP, BP            ; PUT THE STACK BACK
  668.     POP    BP            ; RESTORE BP
  669.     RET                ; RETURN
  670. _DPSHTIME    ENDP
  671. ;***************************************************************;
  672. ;    _BROMTIME                        ;
  673. ;    TIME EXECUTION OF REP MOVSB INSTRUCTION FROM ROM    ;
  674. ;***************************************************************;
  675.         PUBLIC    _BROMTIME
  676. _BROMTIME    PROC    NEAR
  677.     PUSH    BP            ; SAVE FRAME
  678.     MOV    BP, SP            ;
  679.     PUSH    DS            ; SAVE DS
  680.     PUSH    ES            ; SAVE ES
  681.     PUSH    SI            ; SAVE SI
  682.     PUSH    DI            ; SAVE DI
  683.     CALL    SETUP_TIMER        ; SET UP TIMER
  684.     MOV    DI, TESTSEG        ;
  685.     MOV    ES, DI            ;
  686.     MOV    DI, 0F000H        ; SET DS TO ROM START
  687.     MOV    DS, DI            ;
  688.     MOV    SI, 5            ; DS:SI -> ROM
  689.     LEA    DI, TESTSEG_START    ; ES:DI -> TEST SEGMENT
  690.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  691.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  692.     MOV    BL, AL            ; SAVE IN BL
  693.     OR    AL, 1            ; SET TIMER ENABLE BIT
  694.     CLI                ; STOP INTERRUPTS
  695.     CLD                ; SET FORWARD DIRECTION
  696.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  697.     REP MOVSB            ; RUN TEST
  698.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  699.     OUT    PPI_PORT, AL        ;
  700.     STI                ; START INTERRUPTS
  701.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  702.     POP    DI            ; RESTORE DI
  703.     POP    SI            ; RESTORE SI
  704.     POP    ES            ; RESTORE ES
  705.     POP    DS            ; RESTORE DS
  706.     POP    BP            ; RESTORE BP
  707.     RET                ; RETURN
  708. _BROMTIME    ENDP
  709. ;***************************************************************;
  710. ;    _WROMTIME                        ;
  711. ;    TIME EXECUTION OF REP MOVSW INSTRUCTION FROM ROM    ;
  712. ;***************************************************************;
  713.         PUBLIC    _WROMTIME
  714. _WROMTIME    PROC    NEAR
  715.     PUSH    BP            ; SAVE FRAME
  716.     MOV    BP, SP            ;
  717.     PUSH    DS            ; SAVE DS
  718.     PUSH    ES            ; SAVE ES
  719.     PUSH    SI            ; SAVE SI
  720.     PUSH    DI            ; SAVE DI
  721.     CALL    SETUP_TIMER        ; SET UP TIMER
  722.     MOV    DI, TESTSEG        ;
  723.     MOV    ES, DI            ;
  724.     MOV    DI, 0F000H        ; SET DS TO ROM START
  725.     MOV    DS, DI            ;
  726.     MOV    SI, 6            ; DS:SI -> ROM
  727.     LEA    DI, TESTSEG_START    ; ES:DI -> TEST SEGMENT
  728.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  729.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  730.     MOV    BL, AL            ; SAVE IN BL
  731.     OR    AL, 1            ; SET TIMER ENABLE BIT
  732.     CLI                ; STOP INTERRUPTS
  733.     CLD                ; SET FORWARD DIRECTION
  734.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  735.     REP MOVSW            ; RUN TEST
  736.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  737.     OUT    PPI_PORT, AL        ;
  738.     STI                ; START INTERRUPTS
  739.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  740.     POP    DI            ; RESTORE DI
  741.     POP    SI            ; RESTORE SI
  742.     POP    ES            ; RESTORE ES
  743.     POP    DS            ; RESTORE DS
  744.     POP    BP            ; RESTORE BP
  745.     RET                ; RETURN
  746. _WROMTIME    ENDP
  747. ;***************************************************************;
  748. ;    _DROMTIME                        ;
  749. ;    TIME EXECUTION OF REP MOVSW INSTRUCTION FROM ROM    ;
  750. ;***************************************************************;
  751.         PUBLIC    _DROMTIME
  752. _DROMTIME    PROC    NEAR
  753.     PUSH    BP            ; SAVE FRAME
  754.     MOV    BP, SP            ;
  755.     PUSH    DS            ; SAVE DS
  756.     PUSH    ES            ; SAVE ES
  757.     PUSH    SI            ; SAVE SI
  758.     PUSH    DI            ; SAVE DI
  759.     CALL    SETUP_TIMER        ; SET UP TIMER
  760.     DB    066H            ; 32 BIT OPERANDS:
  761.     XOR    DI, DI            ; CLEAR EDI
  762.     DB    066H            ; 32 BIT OPERANDS:
  763.     XOR    SI, SI            ; CLEAR ESI
  764.     DB    066H            ; 32 BIT OPERANDS:
  765.     XOR    CX, CX            ; CLEAR ECX
  766.     MOV    DI, TESTSEG        ;
  767.     MOV    ES, DI            ;
  768.     MOV    DI, 0F000H        ; SET DS TO ROM START
  769.     MOV    DS, DI            ;
  770.     MOV    SI, 0            ; DS:SI -> ROM
  771.     LEA    DI, TESTSEG_START    ; ES:DI -> TEST SEGMENT
  772.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  773.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  774.     MOV    BL, AL            ; SAVE IN BL
  775.     OR    AL, 1            ; SET TIMER ENABLE BIT
  776.     CLI                ; STOP INTERRUPTS
  777.     CLD                ; SET FORWARD DIRECTION
  778.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  779.     DB    066H            ; 32 BIT OPERANDS:
  780.     REP MOVSW            ; RUN TEST
  781.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  782.     OUT    PPI_PORT, AL        ;
  783.     STI                ; START INTERRUPTS
  784.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  785.     POP    DI            ; RESTORE DI
  786.     POP    SI            ; RESTORE SI
  787.     POP    ES            ; RESTORE ES
  788.     POP    DS            ; RESTORE DS
  789.     POP    BP            ; RESTORE BP
  790.     RET                ; RETURN
  791. _DROMTIME    ENDP
  792. ;***************************************************************;
  793. ;    _BVIDTIME                        ;
  794. ;    TIME EXECUTION OF REP STOSB INTO VIDEO MEMORY        ;
  795. ;***************************************************************;
  796.         PUBLIC    _BVIDTIME
  797. _BVIDTIME    PROC    NEAR
  798.     PUSH    BP            ; SAVE FRAME
  799.     MOV    BP, SP            ;
  800.     PUSH    ES            ; SAVE ES
  801.     PUSH    DI            ; SAVE DI
  802.     CALL    SETUP_TIMER        ; SET UP TIMER
  803.     MOV    AX, VIDBASE        ; GET BASE ADDRESS
  804.     MOV    ES, AX            ;
  805.     MOV    DI, 0            ; ES:DI -> VIDEO MEMORY
  806.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  807.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  808.     MOV    BL, AL            ; SAVE IN BL
  809.     OR    AL, 1            ; SET TIMER ENABLE BIT
  810.     CLI                ; STOP INTERRUPTS
  811.     CLD                ; SET FORWARD DIRECTION
  812.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  813.     REP STOSB            ; RUN TEST
  814.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  815.     OUT    PPI_PORT, AL        ;
  816.     STI                ; START INTERRUPTS
  817.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  818.     POP    DI            ; RESTORE DI
  819.     POP    ES            ; RESTORE ES
  820.     POP    BP            ; RESTORE BP
  821.     RET                ; RETURN
  822. _BVIDTIME    ENDP
  823. ;***************************************************************;
  824. ;    _WVIDTIME                        ;
  825. ;    TIME EXECUTION OF REP STOSW INTO VIDEO MEMORY        ;
  826. ;***************************************************************;
  827.         PUBLIC    _WVIDTIME
  828. _WVIDTIME    PROC    NEAR
  829.     PUSH    BP            ; SAVE FRAME
  830.     MOV    BP, SP            ;
  831.     PUSH    ES            ; SAVE ES
  832.     PUSH    DI            ; SAVE DI
  833.     CALL    SETUP_TIMER        ; SET UP TIMER
  834.     MOV    AX, VIDBASE        ; GET BASE ADDRESS
  835.     MOV    ES, AX            ;
  836.     MOV    DI, 0            ; ES:DI -> VIDEO MEMORY
  837.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  838.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  839.     MOV    BL, AL            ; SAVE IN BL
  840.     OR    AL, 1            ; SET TIMER ENABLE BIT
  841.     CLI                ; STOP INTERRUPTS
  842.     CLD                ; SET FORWARD DIRECTION
  843.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  844.     REP STOSW            ; RUN TEST
  845.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  846.     OUT    PPI_PORT, AL        ;
  847.     STI                ; START INTERRUPTS
  848.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  849.     POP    DI            ; RESTORE DI
  850.     POP    ES            ; RESTORE ES
  851.     POP    BP            ; RESTORE BP
  852.     RET                ; RETURN
  853. _WVIDTIME    ENDP
  854. ;***************************************************************;
  855. ;    _DVIDTIME                        ;
  856. ;    TIME EXECUTION OF REP STOSW INTO VIDEO MEMORY        ;
  857. ;***************************************************************;
  858.         PUBLIC    _DVIDTIME
  859. _DVIDTIME    PROC    NEAR
  860.     PUSH    BP            ; SAVE FRAME
  861.     MOV    BP, SP            ;
  862.     PUSH    ES            ; SAVE ES
  863.     PUSH    DI            ; SAVE DI
  864.     CALL    SETUP_TIMER        ; SET UP TIMER
  865.     DB    066H            ; 32 BIT OPERANDS:
  866.     XOR    DI, DI            ; CLEAR EDI
  867.     DB    066H            ; 32 BIT OPERANDS:
  868.     XOR    CX, CX            ; CLEAR ECX
  869.     MOV    AX, VIDBASE        ; GET BASE ADDRESS
  870.     MOV    ES, AX            ;
  871.     DB    066H            ; 32 BIT OPERANDS:
  872.     MOV    AX, 0700H        ;  MOV EAX, 07000700H
  873.     DW    0700H            ;
  874.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  875.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  876.     MOV    BL, AL            ; SAVE IN BL
  877.     OR    AL, 1            ; SET TIMER ENABLE BIT
  878.     CLI                ; STOP INTERRUPTS
  879.     CLD                ; SET FORWARD DIRECTION
  880.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  881.     DB    066H            ; 32 BIT OPERANDS:
  882.     REP STOSW            ; RUN TEST
  883.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  884.     OUT    PPI_PORT, AL        ;
  885.     STI                ; START INTERRUPTS
  886.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  887.     POP    DI            ; RESTORE DI
  888.     POP    ES            ; RESTORE ES
  889.     POP    BP            ; RESTORE BP
  890.     RET                ; RETURN
  891. _DVIDTIME    ENDP
  892. ;***************************************************************;
  893. ;    _SETUP_VIDEO                        ;
  894. ;    DETECT THE TYPE OF VIDEO CARD AND SAVE THE BASE     ;
  895. ;***************************************************************;
  896.         PUBLIC    _SETUP_VIDEO
  897. _SETUP_VIDEO    PROC    NEAR
  898.     PUSH    BP            ; SAVE REGISTERS
  899.     PUSH    ES            ;
  900.     PUSH    SI            ;
  901.     PUSH    DI            ;
  902.     INT    11H            ; EQUIPMENT DETERMINATION
  903.     AND    AL, 30H         ; MASK DISPLAY BITS
  904.     CMP    AL, 30H         ; CHECK FOR MONOCHROME
  905.     MOV    AX, 0B000H        ; MONOCHROME BASE
  906.     JE    SVM            ; JUMP IF MONOCHROME
  907.     MOV    AX, 0B800H        ; COLOR BASE
  908. SVM:    MOV    VIDBASE, AX        ; SAVE BASE ADDRESS
  909.     POP    DI            ; RESTORE REGISTERS
  910.     POP    SI            ;
  911.     POP    ES            ;
  912.     POP    BP            ;
  913.     RET                ; RETURN 0
  914. _SETUP_VIDEO    ENDP
  915. ;***************************************************************;
  916. ;    _FPTIME                         ;
  917. ;    TIME EXECUTION OF FLOATING POINT DIVIDE         ;
  918. ;***************************************************************;
  919.         PUBLIC    _FPTIME
  920. _FPTIME     PROC    NEAR
  921.     PUSH    BP            ; SAVE FRAME
  922.     MOV    BP, SP            ;
  923.     PUSH    DI            ; SAVE DI
  924.  
  925.     ALIGN    FP,F            ; Align instructions on dword boundary
  926.  
  927.     CALL    SETUP_TIMER        ; SET UP TIMER
  928.     LEA    BX, FL            ; UNPRIME TEST AREA
  929.     MOV    CX, 300         ;
  930.     CALL    UNPRIME         ;
  931.     MOV    DI, 0            ; CLEAR DI
  932.     MOV    AX, [BP+4]        ; GET COUNT ARGUMENT
  933.     ADD    AX, 99            ; ROUND UP
  934.     MOV    CX, 100         ; DIVIDE BY 100 =
  935.     DIV    CL            ;  NUMBER OF INSTRUCTIONS
  936.     MOV    CL, AL            ;  PER PASS
  937.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  938.     MOV    BL, AL            ; SAVE IN BL
  939.     OR    AL, 1            ; SET TIMER ENABLE BIT
  940.     FNINIT                ; INIT FP
  941.     FLD1                ; DIVIDE 1.0
  942.     FLD1                ; BY 1.0
  943.     CLI                ; STOP INTERRUPTS
  944.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  945.     INSTR_ALIGN            ; Ensure instruction alignment
  946. FL:    REPT    100            ; DO 100 DIVIDES
  947.     FDIV    ST(1), ST        ;
  948.     ENDM                ; END MACRO
  949.     DEC    CX            ; COUNT THIS PASS
  950.     JZ    FD            ; JUMP IF COMPLETE
  951.     JMP    FL            ; LOOP BACK IF NOT DONE
  952. FD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  953.     OUT    PPI_PORT, AL        ;
  954.     STI                ; START INTERRUPTS
  955.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  956.     POP    DI            ; RESTORE DI
  957.     POP    BP            ; RESTORE BP
  958.     RET                ; RETURN
  959. _FPTIME        ENDP
  960. ;***************************************************************;
  961. ;    _WEMPTIME                        ;
  962. ;    TIME EXECUTION OF PUSHA INSTRUCTION            ;
  963. ;***************************************************************;
  964.         PUBLIC    _WEMPTIME
  965. _WEMPTIME    PROC    NEAR
  966.     PUSH    BP            ; SAVE FRAME
  967.     PUSH    DI            ; SAVE DI
  968.     MOV    BP, SP            ;
  969.  
  970.     ALIGN    WEMP,EP         ; Align instructions on dword boundary
  971.  
  972.     CALL    SETUP_TIMER        ; SET UP TIMER
  973.     MOV    AX, [BP+6]        ; GET COUNT ARGUMENT
  974.     CWD                ; MAKE DOUBLE WORD
  975.     MOV    CX, 200         ;
  976.     DIV    CX            ; DIVIDE BY MOVS/LOOP
  977.     MOV    CX, AX            ;
  978.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  979.     MOV    BL, AL            ; SAVE IN BL
  980.     OR    AL, 1            ; SET TIMER ENABLE BIT
  981.     CLI                ; STOP INTERRUPTS
  982.     MOV    DX, SS            ; SAVE STACK SEGMENT
  983.     MOV    SS, EMMBASE        ; PUT STACK IN EMM
  984.     MOV    SP, 400         ; SET SP FOR PUSHES
  985.     MOV    DI, SP            ; SAVE THIS NUMBER
  986.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  987.     INSTR_ALIGN            ; Ensure instruction alignment
  988. EPL:    REPT    25            ; PUSH THE REGISTERS
  989.     DB    60H            ;
  990.     ENDM                ;
  991.     MOV    SP, DI            ; PUT THE STACK BACK
  992.     LOOP    EPL            ; LOOP UNTIL DONE
  993. EPD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  994.     OUT    PPI_PORT, AL        ;
  995.     MOV    SS, DX            ; RESTORE ORIGINAL STACK
  996.     MOV    SP, BP            ;
  997.     STI                ; START INTERRUPTS
  998.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  999.     POP    DI            ; RESTORE DI
  1000.     POP    BP            ; RESTORE BP
  1001.     RET                ; RETURN
  1002. _WEMPTIME    ENDP
  1003. ;***************************************************************;
  1004. ;    _DEMPTIME                        ;
  1005. ;    TIME EXECUTION OF PUSHA INSTRUCTION            ;
  1006. ;***************************************************************;
  1007.         PUBLIC    _DEMPTIME
  1008. _DEMPTIME    PROC    NEAR
  1009.     PUSH    BP            ; SAVE FRAME
  1010.     PUSH    DI            ; SAVE DI
  1011.     MOV    BP, SP            ;
  1012.  
  1013.     ALIGN    DEMP,ED         ; Align instructions on dword boundary
  1014.  
  1015.     CALL    SETUP_TIMER        ; SET UP TIMER
  1016.     MOV    AX, [BP+6]        ; GET COUNT ARGUMENT
  1017.     CWD                ; MAKE DOUBLE WORD
  1018.     MOV    CX, 200         ;
  1019.     DIV    CX            ; DIVIDE BY MOVS/LOOP
  1020.     MOV    CX, AX            ;
  1021.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  1022.     MOV    BL, AL            ; SAVE IN BL
  1023.     OR    AL, 1            ; SET TIMER ENABLE BIT
  1024.     CLI                ; STOP INTERRUPTS
  1025.     MOV    DX, SS            ; SAVE STACK SEGMENT
  1026.     MOV    SS, EMMBASE        ; PUT STACK IN EMM
  1027.     MOV    SP, 800         ; SET SP FOR PUSHES
  1028.     MOV    DI, SP            ; SAVE THIS NUMBER
  1029.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  1030.     INSTR_ALIGN            ; Ensure instruction alignment
  1031. EDL:    REPT    25            ; PUSH THE BIG REGISTERS
  1032.     DB    66H, 60H        ;
  1033.     ENDM                ; END MACRO
  1034.     MOV    SP, DI            ; PUT THE STACK BACK
  1035.     LOOP    EDL            ; LOOP UNTIL DONE
  1036. EDD:    MOV    AL, BL            ; RESTORE CONTROL VALUE
  1037.     OUT    PPI_PORT, AL        ;
  1038.     MOV    SS, DX            ; RESTORE ORIGINAL STACK
  1039.     MOV    SP, BP            ;
  1040.     STI                ; START INTERRUPTS
  1041.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  1042.     POP    DI            ; RESTORE DI
  1043.     POP    BP            ; RESTORE BP
  1044.     RET                ; RETURN
  1045. _DEMPTIME    ENDP
  1046. ;***************************************************************;
  1047. ;    _BEMMTIME                        ;
  1048. ;    TIME EXECUTION OF REP MOVSB INSTRUCTION         ;
  1049. ;***************************************************************;
  1050.         PUBLIC    _BEMMTIME
  1051. _BEMMTIME    PROC    NEAR
  1052.     PUSH    BP            ; SAVE FRAME
  1053.     MOV    BP, SP            ;
  1054.     PUSH    DS            ; SAVE DS
  1055.     PUSH    ES            ; SAVE ES
  1056.     PUSH    SI            ; SAVE SI
  1057.     PUSH    DI            ; SAVE DI
  1058.     CALL    SETUP_TIMER        ; SET UP TIMER
  1059.     MOV    DI, EMMBASE        ; SET UP EMM BASE ADDRESS
  1060.     MOV    ES, DI            ;
  1061.     MOV    DS, DI            ;
  1062.     MOV    SI, 5            ; ES:SI -> BYTE IN TEST SEGMENT
  1063.     XOR    DI, DI            ; ES:DI -> TEST SEGMENT
  1064.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  1065.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  1066.     MOV    BL, AL            ; SAVE IN BL
  1067.     OR    AL, 1            ; SET TIMER ENABLE BIT
  1068.     CLI                ; STOP INTERRUPTS
  1069.     CLD                ; SET FORWARD DIRECTION
  1070.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  1071.     REP MOVSB            ; RUN TEST
  1072.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  1073.     OUT    PPI_PORT, AL        ;
  1074.     STI                ; START INTERRUPTS
  1075.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  1076.     POP    DI            ; RESTORE DI
  1077.     POP    SI            ; RESTORE SI
  1078.     POP    ES            ; RESTORE ES
  1079.     POP    DS            ; RESTORE DS
  1080.     POP    BP            ; RESTORE BP
  1081.     RET                ; RETURN
  1082. _BEMMTIME    ENDP
  1083. ;***************************************************************;
  1084. ;    _WEMMTIME                        ;
  1085. ;    TIME EXECUTION OF REP MOVSW INSTRUCTION         ;
  1086. ;***************************************************************;
  1087.         PUBLIC    _WEMMTIME
  1088. _WEMMTIME    PROC    NEAR
  1089.     PUSH    BP            ; SAVE FRAME
  1090.     MOV    BP, SP            ;
  1091.     PUSH    DS            ; SAVE DS
  1092.     PUSH    ES            ; SAVE ES
  1093.     PUSH    SI            ; SAVE SI
  1094.     PUSH    DI            ; SAVE DI
  1095.     CALL    SETUP_TIMER        ; SET UP TIMER
  1096.     MOV    DI, EMMBASE        ; SET UP EMM BASE ADDRESS
  1097.     MOV    ES, DI            ;
  1098.     MOV    DS, DI            ;
  1099.     MOV    SI, 6            ; ES:SI -> WORD IN TEST SEGMENT
  1100.     XOR    DI, DI            ; ES:DI -> TEST SEGMENT
  1101.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  1102.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  1103.     MOV    BL, AL            ; SAVE IN BL
  1104.     OR    AL, 1            ; SET TIMER ENABLE BIT
  1105.     CLI                ; STOP INTERRUPTS
  1106.     CLD                ; SET FORWARD DIRECTION
  1107.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  1108.     REP MOVSW            ; RUN TEST
  1109.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  1110.     OUT    PPI_PORT, AL        ;
  1111.     STI                ; START INTERRUPTS
  1112.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  1113.     POP    DI            ; RESTORE DI
  1114.     POP    SI            ; RESTORE SI
  1115.     POP    ES            ; RESTORE ES
  1116.     POP    DS            ; RESTORE DS
  1117.     POP    BP            ; RESTORE BP
  1118.     RET                ; RETURN
  1119. _WEMMTIME    ENDP
  1120. ;***************************************************************;
  1121. ;    _DEMMTIME                        ;
  1122. ;    TIME EXECUTION OF REP MOVSW INSTRUCTION         ;
  1123. ;***************************************************************;
  1124.         PUBLIC    _DEMMTIME
  1125. _DEMMTIME    PROC    NEAR
  1126.     PUSH    BP            ; SAVE FRAME
  1127.     MOV    BP, SP            ;
  1128.     PUSH    DS            ; SAVE DS
  1129.     PUSH    ES            ; SAVE ES
  1130.     PUSH    SI            ; SAVE SI
  1131.     PUSH    DI            ; SAVE DI
  1132.     CALL    SETUP_TIMER        ; SET UP TIMER
  1133.     DB    066H            ; 32 BIT OPERANDS:
  1134.     XOR    DI, DI            ; CLEAR EDI
  1135.     DB    066H            ; 32 BIT OPERANDS:
  1136.     XOR    SI, SI            ; CLEAR ESI
  1137.     DB    066H            ; 32 BIT OPERANDS:
  1138.     XOR    CX, CX            ; CLEAR ECX
  1139.     MOV    DI, EMMBASE        ; SET UP EMM BASE ADDRESS
  1140.     MOV    ES, DI            ;
  1141.     MOV    DS, DI            ;
  1142.     XOR    DI, DI            ; ES:DI -> TEST SEGMENT
  1143.     XOR    SI, SI            ; DS:SI -> TEST SEGMENT
  1144.     MOV    CX, [BP+4]        ; GET COUNT ARGUMENT
  1145.     IN    AL, PPI_PORT        ; GET CURRENT CONTROL
  1146.     MOV    BL, AL            ; SAVE IN BL
  1147.     OR    AL, 1            ; SET TIMER ENABLE BIT
  1148.     CLI                ; STOP INTERRUPTS
  1149.     CLD                ; SET FORWARD DIRECTION
  1150.     OUT    PPI_PORT, AL        ; ENABLE TIMER
  1151.     DB    066H            ; 32 BIT OPERANDS:
  1152.     REP MOVSW            ; RUN TEST
  1153.     MOV    AL, BL            ; RESTORE CONTROL VALUE
  1154.     OUT    PPI_PORT, AL        ;
  1155.     STI                ; START INTERRUPTS
  1156.     CALL    GET_TIMER        ; OBTAIN FINAL COUNT
  1157.     POP    DI            ; RESTORE DI
  1158.     POP    SI            ; RESTORE SI
  1159.     POP    ES            ; RESTORE ES
  1160.     POP    DS            ; RESTORE DS
  1161.     POP    BP            ; RESTORE BP
  1162.     RET                ; RETURN
  1163. _DEMMTIME    ENDP
  1164. ;***************************************************************;
  1165. ;    _SETUP_EMM                        ;
  1166. ;    SET UP EXPANDED MEMORY AND RETURN THE BASE        ;
  1167. ;***************************************************************;
  1168.         PUBLIC    _SETUP_EMM
  1169. _SETUP_EMM    PROC    NEAR
  1170.     PUSH    BP            ; SAVE REGISTERS
  1171.     PUSH    ES            ;
  1172.     PUSH    SI            ;
  1173.     PUSH    DI            ;
  1174.     MOV    AH, 35H         ; GET EMM INTERRUPT
  1175.     MOV    AL, 67H         ; VECTOR
  1176.     INT    21H            ;
  1177.     MOV    DI, 000AH        ; OFFSET OF DRIVER NAME
  1178.     LEA    SI, EMM_NAME        ; COMPARE STRING
  1179.     MOV    CX, 8            ; LENGTH OF STRING
  1180.     CLD                ;
  1181.     REPE    CMPSB            ; COMPARE THE NAME
  1182.     JNE    SENO            ; JUMP IF NO GOOD
  1183. SE1:    MOV    AH, 40H         ; FUNCTION 1:
  1184.     INT    67H            ; GET MANAGER STATUS
  1185.     CMP    AH, 82H         ; CHECK FOR BUSY
  1186.     JE    SE1            ; TRY AGAIN IF BUSY
  1187.     OR    AH, AH            ; CHECK FOR ERROR
  1188.     JNZ    SENO            ; JUMP ON ERROR
  1189. SE2:    MOV    AH, 41H         ; FUNCTION 2:
  1190.     INT    67H            ; GET PAGE FRAME BASE
  1191.     CMP    AH, 82H         ; CHECK FOR BUSY
  1192.     JE    SE2            ; TRY AGAIN IF BUSY
  1193.     OR    AH, AH            ; CHECK FOR ERROR
  1194.     JNZ    SENO            ; JUMP ON ERROR
  1195.     MOV    EMMBASE, BX        ; SAVE THE BASE
  1196. SE3:    MOV    AH, 42H         ; FUNCTION 3:
  1197.     INT    67H            ; GET NUMBER OF PAGES
  1198.     CMP    AH, 82H         ; CHECK FOR BUSY
  1199.     JE    SE3            ; TRY AGAIN IF BUSY
  1200.     OR    AH, AH            ; CHECK FOR ERROR
  1201.     JNZ    SENO            ; JUMP ON ERROR
  1202.     OR    BX, BX            ; CHECK UNALLOCATED PAGES
  1203.     JZ    SENO            ; JUMP IF NONE AVAILABLE
  1204. SE4:    MOV    AH, 43H         ; FUNCTION 4:
  1205.     MOV    BX, 1            ; ALLOCATE ONE PAGE
  1206.     INT    67H            ;
  1207.     CMP    AH, 82H         ; CHECK FOR BUSY
  1208.     JE    SE4            ; TRY AGAIN IF BUSY
  1209.     OR    AH, AH            ; CHECK FOR ERROR
  1210.     JNZ    SENO            ; JUMP ON ERROR
  1211.     MOV    PID, DX         ; SAVE THE PROCESS ID
  1212. SE5:    MOV    AH, 44H         ; FUNCTION 5:
  1213.     XOR    BX, BX            ; MAP THE PAGE TO
  1214.     XOR    AL, AL            ;  FRAME BASE
  1215.     INT    67H            ;
  1216.     CMP    AH, 82H         ; CHECK FOR BUSY
  1217.     JE    SE5            ; TRY AGAIN IF BUSY
  1218.     OR    AH, AH            ; CHECK FOR ERROR
  1219.     JNZ    SENC            ; JUMP ON ERROR
  1220.     XOR    AX, AX            ;
  1221.     POP    DI            ; RESTORE REGISTERS
  1222.     POP    SI            ;
  1223.     POP    ES            ;
  1224.     POP    BP            ;
  1225.     RET                ; RETURN 0
  1226. SENC:    MOV    AH, 45H         ; FUNCTION 6:
  1227.     INT    67H            ; CLOSE EMM
  1228.     CMP    AH, 82H         ; CHECK FOR BUSY
  1229.     JE    SENC            ; TRY AGAIN IF BUSY
  1230. SENO:    MOV    AX, 0FFFFH        ;
  1231.     POP    DI            ; RESTORE REGISTERS
  1232.     POP    SI            ;
  1233.     POP    ES            ;
  1234.     POP    BP            ;
  1235.     RET                ; RETURN -1
  1236. _SETUP_EMM    ENDP
  1237. ;***************************************************************;
  1238. ;    _FINISH_EMM                        ;
  1239. ;    CLOSE THE EMM DEVICE, RELEASE THE PAGE            ;
  1240. ;***************************************************************;
  1241.         PUBLIC    _FINISH_EMM
  1242. _FINISH_EMM    PROC    NEAR
  1243.     PUSH    BP            ; SAVE REGISTERS
  1244.     PUSH    ES            ;
  1245.     PUSH    SI            ;
  1246.     PUSH    DI            ;
  1247. SE6:    MOV    AH, 45H         ; FUNCTION 6:
  1248.     MOV    DX, PID         ; CLOSE EMM
  1249.     INT    67H            ;
  1250.     CMP    AH, 82H         ; CHECK FOR BUSY
  1251.     JE    SE6            ; TRY AGAIN IF BUSY
  1252.     POP    DI            ; RESTORE REGISTERS
  1253.     POP    SI            ;
  1254.     POP    ES            ;
  1255.     POP    BP            ;
  1256.     RET                ; RETURN
  1257. _FINISH_EMM    ENDP
  1258. ;***************************************************************;
  1259. ;    PRIME                            ;
  1260. ;    PRIME THE CACHE, IF ANY, BY SCANNING TEST AREA        ;
  1261. ;***************************************************************;
  1262. PRIME    PROC    NEAR
  1263.     PUSH    AX            ; SAVE ALL REGISTERS USED
  1264.     PUSH    DI            ; SAVE SI (START ADDRESS)
  1265.     PUSH    CX            ; SAVE CX (COUNT)
  1266.     PUSH    ES            ; SAVE ES
  1267.     MOV    AX, CS            ; SET ES TO DS
  1268.     MOV    ES, AX            ;
  1269.     MOV    DI, BX            ; PUT ADDRESS IN DI
  1270.     MOV    AL, 111         ; USE UNLIKELY VALUE IN AL
  1271.     CLD                ; SET FORWARD DIRECTION
  1272. PL:    REPNE SCASB            ; SCAN MEMORY
  1273.     JCXZ    PE            ; JUMP IF DONE
  1274.     JMP    PL            ; JUMP BACK IF NOT DONE
  1275. PE:    POP    ES            ;
  1276.     POP    CX            ; RESTORE REGISTERS
  1277.     POP    DI            ;
  1278.     POP    AX            ;
  1279.     RET                ; RETURN
  1280. PRIME    ENDP
  1281. ;***************************************************************;
  1282. ;    UNPRIME                         ;
  1283. ;    PRIME THE CACHE, IF ANY, BY SCANNING AWAY FROM TEST AREA;
  1284. ;***************************************************************;
  1285. UNPRIME PROC    NEAR
  1286.     PUSH    AX            ; SAVE ALL REGISTERS USED
  1287.     PUSH    DI            ; SAVE SI (START ADDRESS)
  1288.     PUSH    CX            ; SAVE CX (COUNT)
  1289.     PUSH    ES            ; SAVE ES
  1290.     MOV    AX, CS            ; SET ES TO CS + 64K
  1291.     ADD    AX, 1000H        ;
  1292.     MOV    ES, AX            ;
  1293.     MOV    DI, BX            ; PUT ADDRESS IN DI
  1294.     MOV    AL, 111         ; USE UNLIKELY VALUE IN AL
  1295.     CLD                ; SET FORWARD DIRECTION
  1296. UPL:    REPNE SCASB            ; SCAN MEMORY
  1297.     JCXZ    UPE            ; JUMP IF DONE
  1298.     JMP    UPL            ; JUMP BACK IF NOT DONE
  1299. UPE:    POP    ES            ;
  1300.     POP    CX            ; RESTORE REGISTERS
  1301.     POP    DI            ;
  1302.     POP    AX            ;
  1303.     RET                ; RETURN
  1304. UNPRIME ENDP
  1305. ;***************************************************************;
  1306. ;    SETUP_TIMER                        ;
  1307. ;    SET UP THE TIMER FOR MAXIMUM COUNT, TO TIME A RUN    ;
  1308. ;***************************************************************;
  1309. SETUP_TIMER    PROC    NEAR
  1310.     PUSH    AX            ; SAVE AX
  1311.     IN    AL, PPI_PORT        ; STOP THE TIMER
  1312.     AND    AL, 0FCH        ;
  1313.     OUT    PPI_PORT, AL        ;
  1314.     MOV    AL, 0B4H        ; INITIALIZE THE TIMER
  1315.     OUT    TIMER_CTRL, AL        ;
  1316.     JMP    $+2            ; Drain PIQ
  1317.     MOV    AL, 0            ; CLEAR THE COUNT
  1318.     OUT    TIMER2_PORT, AL     ;
  1319.     JMP    $+2            ; Drain PIQ
  1320.     OUT    TIMER2_PORT, AL     ;
  1321.     POP    AX            ; RESTORE AX
  1322.     RET                ; RETURN
  1323. SETUP_TIMER    ENDP
  1324. ;***************************************************************;
  1325. ;    GET_TIMER                        ;
  1326. ;    TAKE THE COUNT FROM THE TIMER                ;
  1327. ;***************************************************************;
  1328. GET_TIMER    PROC    NEAR
  1329.     IN    AL, TIMER2_PORT     ; GET LOW BYTE OF TIME
  1330.     MOV    AH, AL            ;
  1331.     IN    AL, TIMER2_PORT     ; GET HIGH BYTE
  1332.     XCHG    AL, AH            ; TIME IN AX
  1333.     NEG    AX            ; CORRECT FOR COUNT-DOWN
  1334.     RET                ; RETURN
  1335. GET_TIMER    ENDP
  1336. ;***************************************************************;
  1337. ;    _NDP_PRESENT                        ;
  1338. ;    CHECK IF 80287 IS PRESENT                ;
  1339. ;***************************************************************;
  1340.         PUBLIC    _NDP_PRESENT
  1341. _NDP_PRESENT    PROC    NEAR
  1342.     PUSH    BP            ; SAVE FRAME
  1343.     MOV    BP, SP            ;
  1344.     INT    11H            ; BIOS EQUIP CHECK
  1345.     TEST    AL,02H            ; IS 80287 BIT SET?
  1346.     JZ    NO            ; NO MEANS NO 80287
  1347.     MOV    AX,01h            ; RETURN TRUE
  1348.     JMP    NDPEXIT         ; ALL DONE
  1349. NO:    XOR    AX,AX            ; SET AX TO FALSE
  1350. NDPEXIT:MOV    SP, BP            ; RESTORE SP
  1351.     POP    BP            ; RESTORE BP
  1352.     RET                ; RETURN
  1353. _NDP_PRESENT    ENDP
  1354. ;***************************************************************;
  1355. ;    _DETECT_387                        ;
  1356. ;    CHECK IF MATH COPROCESSOR IS 80387            ;
  1357. ;***************************************************************;
  1358.         PUBLIC    _DETECT_387
  1359. _DETECT_387    PROC    NEAR
  1360.     PUSH    BP            ; SAVE FRAME
  1361.     MOV    BP, SP            ;
  1362.     FINIT                ; USE DEFAULT INFINITY MODE
  1363.     FLD1                ; GENERATE INFINITY
  1364.     FLDZ                ;
  1365.     FDIV                ;
  1366.     FLD    ST            ; FORM NEGATIVE INFINITY
  1367.     FCHS                ; BY CHANGING SIGN
  1368.     FCOMPP                ; COMPARE +/-INFINITY
  1369.     FSTSW    STATUSW         ; EQUAL FOR 8087/287
  1370.     FWAIT                ; WAIT
  1371.     MOV    AX,STATUSW        ;
  1372.     SAHF                ; STORE RESULT IN FLAGS
  1373.     JZ    NO387            ; NOT A 80387
  1374.     MOV    AX,01h            ; RETURN TRUE
  1375.     JMP    D3EXIT            ; ALL DONE
  1376. NO387:    XOR    AX,AX            ; SET AX TO FALSE
  1377. D3EXIT: MOV    SP, BP            ; RESTORE SP
  1378.     POP    BP            ; RESTORE BP
  1379.     RET                ; RETURN
  1380. _DETECT_387    ENDP
  1381. ;***************************************************************;
  1382. ;    _CPU_TYPE                        ;
  1383. ;    CHECK IF CPU IS 8088/8086, 80188/80186, 80286, 80386    ;
  1384. ;***************************************************************;
  1385.         PUBLIC    _CPU_TYPE
  1386. _CPU_TYPE    PROC    NEAR
  1387.     PUSH    BP            ; SAVE FRAME
  1388.     MOV    BP, SP            ;
  1389.     PUSHF                ;
  1390.     MOV    CL,20H            ; INITIALIZE SHIFT COUNT
  1391.     MOV    AX,1            ; DESTINATION
  1392.     SHR    AX,CL            ; SHIFT RIGHT
  1393.     TEST    AX,1            ; IS AX THE SAME?
  1394.     JZ    _8X            ; IS 8086 OR 8088
  1395.     PUSH    SP            ; SEE IF SP IS UPDATED
  1396.     POP    BX            ; BEFORE OR AFTER IT IS
  1397.     CMP    BX,SP            ; PUSHED
  1398.     JNE    _18X            ; IS 80188 OR 80186
  1399.     MOV    AX,0F000H        ; TRY TO SET HIGH BITS
  1400.     PUSH    AX            ;
  1401.     POPF                ; IN THE FLAGS
  1402.     PUSHF                ;
  1403.     POP    AX            ; LOOK AT ACTUAL FLAGS
  1404.     AND    AX,0F000H        ; ANY HIGH BITS SET?
  1405.     JE    _286            ; IS 80286
  1406. _386:    MOV    AX,03            ; IS AN 80386
  1407.     JMP    CTEXIT            ;
  1408. _286:    MOV    AX,02            ; IS AN 80286
  1409.     JMP    CTEXIT            ;
  1410. _18X:    MOV    AX,01            ; IS AN 80188/80186
  1411.     JMP    CTEXIT            ;
  1412. _8X:    MOV    AX,00            ; IS AN 8088/8086
  1413. CTEXIT: POPF                ; RESTORE ORIGINAL FLAGS
  1414.     MOV    SP, BP            ; RESTORE SP
  1415.     POP    BP            ; RESTORE BP
  1416.     RET                ; RETURN
  1417. _CPU_TYPE    ENDP
  1418. ;***************************************************************;
  1419. ;    DD_ALIGN                        ;
  1420. ;    Ensure instruction fectches are on a dword boundary.    ;
  1421. ;***************************************************************;
  1422.         PUBLIC    DD_ALIGN
  1423. DD_ALIGN    PROC    NEAR
  1424.      assume  ds:nothing,es:nothing ; Tell the assembler about it
  1425.  
  1426. DD_ALIGN_STR struc
  1427.  
  1428.      dw     ?        ; Caller's BP
  1429.      dw     ?        ; Caller's IP
  1430. DD_ALIGN_START dw ?        ; Offset of alignment start
  1431. DD_ALIGN_LEN   dw ?        ; Length of alignment area
  1432.  
  1433. DD_ALIGN_STR ends
  1434.  
  1435.      push     bp        ; Prepare to address the stack
  1436.      mov     bp,sp        ; Hello, Mr. Stack
  1437.  
  1438.      REGSAVE <cx,si,di,ds,es> ; Save registers
  1439.  
  1440.      push     cs        ; Setup DS and ES for code references
  1441.      pop     ds
  1442.      assume  ds:_TEXT    ; Tell the assembler about it
  1443.      push     cs
  1444.      pop     es
  1445.      assume  es:_TEXT    ; Tell the assembler about it
  1446.  
  1447.      mov     si,[bp].DD_ALIGN_START ; Get source offset
  1448.      mov     di,si        ; Copy as destination offset
  1449.      and     di,not (4-1)    ; Round down to DD boundary
  1450.      mov     cx,[bp].DD_ALIGN_LEN ; Get length in bytes
  1451.      rep movsb            ; Move it down
  1452.  
  1453. ; Fill in the tail with NOPs
  1454.  
  1455.      mov     cx,si        ; Get current source offset
  1456.      sub     cx,di        ; Less current destin to get length of tail
  1457.      mov     al,90h     ; Fill with NOPs
  1458.      rep stosb            ; Fill it up
  1459.  
  1460.      REGREST <es,ds,di,si,cx> ; Restore
  1461.      assume  ds:nothing,es:nothing ; Tell the assembler about it
  1462.  
  1463.      pop     bp        ; Restore
  1464.  
  1465.      ret     2*2        ; Return to caller, popping arguments
  1466.  
  1467.      assume  ds:nothing,es:nothing ; Tell the assembler about it
  1468.  
  1469. DD_ALIGN    ENDP
  1470. _TEXT        ENDS
  1471.         END
  1472.