home *** CD-ROM | disk | FTP | other *** search
- NAME TIME
- include MASM.INC
-
- _TEXT SEGMENT PARA PUBLIC 'CODE'
- _TEXT ENDS
- CONST SEGMENT PARA PUBLIC 'CONST'
- CONST ENDS
- _BSS SEGMENT PARA PUBLIC 'BSS'
- _BSS ENDS
- _DATA SEGMENT PARA PUBLIC 'DATA'
- _DATA ENDS
- DGROUP GROUP CONST, _BSS, _DATA
- ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
- TESTSEG SEGMENT PARA PUBLIC 'TEST'
- TESTSEG_START DW 32767 DUP (?)
- TESTSEG ENDS
- PPI_PORT EQU 061H
- TIMER2_PORT EQU 042H
- TIMER_CTRL EQU 043H
- _DATA SEGMENT
- VIDBASE DW 0B800H
- EMMBASE DW 9000H
- PID DW ?
- STATUSW DW ?
- EMM_NAME DB "EMMXXXX0"
-
- ; Local flags for instruction relocation
- ; When set, instruction loop has been aligned on a dword boundary
-
- LCL_FLAG DW 0 ; Initially, none aligned
- @LCL_MUL equ 8000h ; _MULTIME
- @LCL_WMOV equ 4000h ; _WMOVTIME
- @LCL_DMOV equ 2000h ; _DMOVTIME
- @LCL_DLOD equ 1000h ; _DLODTIME
- @LCL_DRAM equ 0800h ; _DRAMTIME
- @LCL_DIMM equ 0400h ; _DIMMTIME
- @LCL_BCLC equ 0200h ; _BCLCTIME
- @LCL_BDAA equ 0100h ; _BDAATIME
- @LCL_WPSH equ 0080h ; _WPSHTIME
- @LCL_DPSH equ 0040h ; _DPSHTIME
- @LCL_FP equ 0020h ; _FPTIME
- @LCL_WEMP equ 0010h ; _WEMPTIME
- @LCL_DEMP equ 0008h ; _DEMPTIME
-
- _DATA ENDS
- _TEXT SEGMENT para
- ;***************************************************************;
- ; _MULTIME ;
- ; TIME EXECUTION OF MULTIPLY INSTRUCTIONS ;
- ;***************************************************************;
- PUBLIC _MULTIME
- _MULTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
-
- ALIGN MUL,M ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- MOV DI, 08000H ; SET DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- ML: REPT 100 ; DO 100 MULTIPLIES
- MUL DI ;
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ MD ; JUMP IF COMPLETE
- JMP ML ; LOOP BACK IF NOT DONE
- MD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _MULTIME ENDP
- ;***************************************************************;
- ; _WMOVTIME ;
- ; TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME) ;
- ;***************************************************************;
- PUBLIC _WMOVTIME
- _WMOVTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
-
- ALIGN WMOV,I ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, IL ; PRIME TEST AREA
- MOV CX, 200 ;
- CALL PRIME ;
- MOV DI, 0 ; CLEAR DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- IL: REPT 100 ; DO 100 MOVES
- MOV DX, BX ;
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ ID ; JUMP IF COMPLETE
- JMP IL ; LOOP BACK IF NOT DONE
- ID: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _WMOVTIME ENDP
- ;***************************************************************;
- ; _DMOVTIME ;
- ; TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME) ;
- ;***************************************************************;
- PUBLIC _DMOVTIME
- _DMOVTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
-
- ALIGN DMOV,N ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, NL ; PRIME TEST AREA
- MOV CX, 400 ;
- CALL PRIME ;
- MOV DI, 0 ; CLEAR DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- NL: REPT 100 ; DO 100 MOV DX,05555H
- DB 0C7H, 0C2H, 055H, 055H ; THE LONG WAY (WITH MOD R/M)
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ ND ; JUMP IF COMPLETE
- JMP NL ; LOOP BACK IF NOT DONE
- ND: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _DMOVTIME ENDP
- ;***************************************************************;
- ; _DLODTIME ;
- ; TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME) ;
- ;***************************************************************;
-
- PUBLIC FIRSTSEG,NEXTSEG
- FIRSTSEG DW 0000h ; 0 KB in paras
- NEXTSEG DW 1000h ; 64 KB in paras
-
- PUBLIC _DLODTIME
- _DLODTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
- PUSH DS ;
-
- ALIGN DLOD,LOD ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, LODL ; PRIME TEST AREA
- AND BX, not (4-1) ; Round down to dowrd boundary
- MOV CX, LODD-LODL ; Length of test area
- CALL PRIME ;
- MOV DI, 0 ; CLEAR DI
- MOV DS, FIRSTSEG ; Set to initial segment
- ASSUME DS:NOTHING ; Tell the assembler about it
- DB 03EH ; Use DS:
- MOV AX,DS:[0] ; Ensure loop data value is cached
-
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- LODL: REPT 100 ; DO 100:
- DB 03EH ; Use DS:
- MOV AX,DS:[0] ; Read constant data item
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ LODD ; JUMP IF COMPLETE
- JMP LODL ; LOOP BACK IF NOT DONE
- LODD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DS ;
- ASSUME DS:DGROUP ; Tell the assembler about it
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _DLODTIME ENDP
- ;***************************************************************;
- ; _DRAMTIME ;
- ; TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME) ;
- ;***************************************************************;
-
- PUBLIC _DRAMTIME
- _DRAMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
- PUSH DS ;
- PUSH ES ;
-
- ALIGN DRAM,RAM ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, RAML ; PRIME TEST AREA
- AND BX, not (4-1) ; Round down to dowrd boundary
- MOV CX, RAMD-RAML ; Length of test area
- CALL PRIME ;
- MOV DI, FIRSTSEG ; SET SEG REGS TO
- MOV DS, DI ; 64K DISTANT LOCATIONS
- ASSUME DS:NOTHING ; Tell the assembler about it
- ADD DI,NEXTSEG ;
- MOV ES, DI ; SET ES
- ASSUME ES:NOTHING ; Tell the assembler about it
- ADD DI,NEXTSEG ;
- PUSH DI ;
- DB 00FH, 0A1H ; POP FS
- ADD DI,NEXTSEG ;
- PUSH DI ;
- DB 00FH, 0A9H ; POP GS
- MOV DI, 0 ; CLEAR DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- RAML: REPT 25 ; DO 100:
- DB 03EH, 0A1H ; MOV AX, DS:WORD PTR 0
- DW 0 ;
- DB 026H, 0A1H ; MOV AX, ES:WORD PTR 0
- DW 0 ;
- DB 064H, 0A1H ; MOV AX, FS:WORD PTR 0
- DW 0 ;
- DB 065H, 0A1H ; MOV AX, GS:WORD PTR 0
- DW 0 ;
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ RAMD ; JUMP IF COMPLETE
- JMP RAML ; LOOP BACK IF NOT DONE
- RAMD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP ES ;
- ASSUME ES:DGROUP ; Tell the assembler about it
- POP DS ;
- ASSUME DS:DGROUP ; Tell the assembler about it
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _DRAMTIME ENDP
- ;***************************************************************;
- ; _DIMMTIME ;
- ; TIME EXECUTION OF MOV INSTRUCTION (INSTR. READ TIME) ;
- ;***************************************************************;
- PUBLIC _DIMMTIME
- _DIMMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
-
- ALIGN DIMM,IMM ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, IMML ; PRIME TEST AREA
- MOV CX, 400 ;
- CALL PRIME ;
- MOV DI, 0 ; CLEAR DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- IMML: REPT 100 ; DO 100:
- REPT 8 ; 8X:
- DB 066H ; MOV EDX, 00000000H
- DB 0F7H, 0C2H, 0, 0, 0, 0 ;
- ENDM ; END MACRO
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ IMMD ; JUMP IF COMPLETE
- JMP IMML ; LOOP BACK IF NOT DONE
- IMMD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _DIMMTIME ENDP
- ;***************************************************************;
- ; _BCLCTIME ;
- ; TIME EXECUTION OF CLC INSTRUCTION (INSTR. READ TIME) ;
- ;***************************************************************;
- PUBLIC _BCLCTIME
- _BCLCTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
-
- ALIGN BCLC,BI ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, BIL ; PRIME TEST AREA
- MOV CX, 100 ;
- CALL PRIME ;
- MOV DI, 0 ; CLEAR DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- BIL: REPT 100 ; DO 100 INC'S
- INC DL ;
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ BID ; JUMP IF COMPLETE
- JMP BIL ; LOOP BACK IF NOT DONE
- BID: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _BCLCTIME ENDP
- ;***************************************************************;
- ; _BDAATIME ;
- ; TIME EXECUTION OF DAA INSTRUCTION (INSTR. READ TIME) ;
- ;***************************************************************;
- PUBLIC _BDAATIME
- _BDAATIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
-
- ALIGN BDAA,BX ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, BXL ; PRIME TEST AREA
- MOV CX, 100 ;
- CALL PRIME ;
- MOV DI, 0 ; CLEAR DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- BXL: REPT 100 ; DO 100 DAA'S
- DAA ;
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ BXD ; JUMP IF COMPLETE
- JMP BXL ; LOOP BACK IF NOT DONE
- BXD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _BDAATIME ENDP
- ;***************************************************************;
- ; _BMVSTIME ;
- ; TIME EXECUTION OF REP MOVSB INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _BMVSTIME
- _BMVSTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
-
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DS, DI ;
- LEA SI, TESTSEG_START + 5 ; DS:SI -> TEST SEGMENT
- LEA DI, TESTSEG_START + 0 ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- CLD ; SET FORWARD DIRECTION
- REP MOVSB ; RUN TEST
-
- CALL SETUP_TIMER ; SET UP TIMER
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DS, DI ;
- LEA SI, TESTSEG_START + 5 ; DS:SI -> TEST SEGMENT
- LEA DI, TESTSEG_START + 0 ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP MOVSB ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
-
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _BMVSTIME ENDP
- ;***************************************************************;
- ; _WMVSTIME ;
- ; TIME EXECUTION OF REP MOVSW INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _WMVSTIME
- _WMVSTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
-
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DS, DI ;
- LEA SI, TESTSEG_START + 6 ; DS:SI -> TEST SEGMENT
- LEA DI, TESTSEG_START + 0 ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- CLD ; SET FORWARD DIRECTION
- REP MOVSW ; RUN TEST
-
- CALL SETUP_TIMER ; SET UP TIMER
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DS, DI ;
- LEA SI, TESTSEG_START + 6 ; DS:SI -> TEST SEGMENT
- LEA DI, TESTSEG_START + 0 ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP MOVSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
-
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _WMVSTIME ENDP
- ;***************************************************************;
- ; _DMVSTIME ;
- ; TIME EXECUTION OF REP MOVSW INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _DMVSTIME
- _DMVSTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
-
- DB 066H ; 32 BIT OPERANDS:
- XOR DI, DI ; CLEAR EDI
- DB 066H ; 32 BIT OPERANDS:
- XOR SI, SI ; CLEAR ESI
- DB 066H ; 32 BIT OPERANDS:
- XOR CX, CX ; CLEAR ECX
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DS, DI ;
- LEA SI, TESTSEG_START ; DS:SI -> TEST SEGMENT
- LEA DI, TESTSEG_START + 0 ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- CLD ; SET FORWARD DIRECTION
- DB 066H ; 32 BIT OPERANDS:
- REP MOVSW ; RUN TEST
-
- CALL SETUP_TIMER ; SET UP TIMER
- DB 066H ; 32 BIT OPERANDS:
- XOR DI, DI ; CLEAR EDI
- DB 066H ; 32 BIT OPERANDS:
- XOR SI, SI ; CLEAR ESI
- DB 066H ; 32 BIT OPERANDS:
- XOR CX, CX ; CLEAR ECX
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DS, DI ;
- LEA SI, TESTSEG_START ; DS:SI -> TEST SEGMENT
- LEA DI, TESTSEG_START + 0 ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- DB 066H ; 32 BIT OPERANDS:
- REP MOVSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _DMVSTIME ENDP
- ;***************************************************************;
- ; _WPSHTIME ;
- ; TIME EXECUTION OF PUSHA INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _WPSHTIME
- _WPSHTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
-
- ALIGN WPSH,WS ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- CWD ; MAKE DOUBLE WORD
- MOV CX, 200 ;
- DIV CX ; DIVIDE BY MOVS/LOOP
- MOV CX, AX ;
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- MOV DX, SS ; SAVE SS, SP
- MOV BX, TESTSEG ; SET STACK TO TEST SEGMENT
- MOV SS, BX ;
- MOV BX, SP ;
- MOV SP, OFFSET TESTSEG_START + 4096
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- WSL: REPT 25 ; PUSH THE REGISTERS
- DB 60H ;
- ENDM ; END MACRO
- LOOP WSL ; LOOP UNTIL DONE
- WSD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- MOV SS, DX ; RESTORE SS, SP
- MOV SP, BX ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- MOV SP, BP ; PUT THE STACK BACK
- POP BP ; RESTORE BP
- RET ; RETURN
- _WPSHTIME ENDP
- ;***************************************************************;
- ; _DPSHTIME ;
- ; TIME EXECUTION OF PUSHA INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _DPSHTIME
- _DPSHTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
-
- ALIGN DPSH,DS ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- CWD ; MAKE DOUBLE WORD
- MOV CX, 200 ;
- DIV CX ; DIVIDE BY MOVS/LOOP
- MOV CX, AX ;
- AND SP, 0FFFCH ; ALIGN SP
- PUSH AX ; DUMMY
- PUSH BP ; SAVE BP
- MOV BP, SP ;
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- MOV DX, SS ; SAVE SS, SP
- MOV BX, TESTSEG ; SET STACK TO TEST SEGMENT
- MOV SS, BX ;
- MOV BX, SP ;
- MOV SP, OFFSET TESTSEG_START + 4096
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- DSL: REPT 25 ; PUSH THE BIG REGISTERS
- DB 66H, 60H ;
- ENDM ; END MACRO
- LOOP DSL ; LOOP UNTIL DONE
- DSD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- MOV SS, DX ; RESTORE SS, SP
- MOV SP, BX ;
- STI ; START INTERRUPTS
- POP BP ;
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- MOV SP, BP ; PUT THE STACK BACK
- POP BP ; RESTORE BP
- RET ; RETURN
- _DPSHTIME ENDP
- ;***************************************************************;
- ; _BROMTIME ;
- ; TIME EXECUTION OF REP MOVSB INSTRUCTION FROM ROM ;
- ;***************************************************************;
- PUBLIC _BROMTIME
- _BROMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DI, 0F000H ; SET DS TO ROM START
- MOV DS, DI ;
- MOV SI, 5 ; DS:SI -> ROM
- LEA DI, TESTSEG_START ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP MOVSB ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _BROMTIME ENDP
- ;***************************************************************;
- ; _WROMTIME ;
- ; TIME EXECUTION OF REP MOVSW INSTRUCTION FROM ROM ;
- ;***************************************************************;
- PUBLIC _WROMTIME
- _WROMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DI, 0F000H ; SET DS TO ROM START
- MOV DS, DI ;
- MOV SI, 6 ; DS:SI -> ROM
- LEA DI, TESTSEG_START ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP MOVSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _WROMTIME ENDP
- ;***************************************************************;
- ; _DROMTIME ;
- ; TIME EXECUTION OF REP MOVSW INSTRUCTION FROM ROM ;
- ;***************************************************************;
- PUBLIC _DROMTIME
- _DROMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- DB 066H ; 32 BIT OPERANDS:
- XOR DI, DI ; CLEAR EDI
- DB 066H ; 32 BIT OPERANDS:
- XOR SI, SI ; CLEAR ESI
- DB 066H ; 32 BIT OPERANDS:
- XOR CX, CX ; CLEAR ECX
- MOV DI, TESTSEG ;
- MOV ES, DI ;
- MOV DI, 0F000H ; SET DS TO ROM START
- MOV DS, DI ;
- MOV SI, 0 ; DS:SI -> ROM
- LEA DI, TESTSEG_START ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- DB 066H ; 32 BIT OPERANDS:
- REP MOVSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _DROMTIME ENDP
- ;***************************************************************;
- ; _BVIDTIME ;
- ; TIME EXECUTION OF REP STOSB INTO VIDEO MEMORY ;
- ;***************************************************************;
- PUBLIC _BVIDTIME
- _BVIDTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH ES ; SAVE ES
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- MOV AX, VIDBASE ; GET BASE ADDRESS
- MOV ES, AX ;
- MOV DI, 0 ; ES:DI -> VIDEO MEMORY
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP STOSB ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP ES ; RESTORE ES
- POP BP ; RESTORE BP
- RET ; RETURN
- _BVIDTIME ENDP
- ;***************************************************************;
- ; _WVIDTIME ;
- ; TIME EXECUTION OF REP STOSW INTO VIDEO MEMORY ;
- ;***************************************************************;
- PUBLIC _WVIDTIME
- _WVIDTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH ES ; SAVE ES
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- MOV AX, VIDBASE ; GET BASE ADDRESS
- MOV ES, AX ;
- MOV DI, 0 ; ES:DI -> VIDEO MEMORY
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP STOSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP ES ; RESTORE ES
- POP BP ; RESTORE BP
- RET ; RETURN
- _WVIDTIME ENDP
- ;***************************************************************;
- ; _DVIDTIME ;
- ; TIME EXECUTION OF REP STOSW INTO VIDEO MEMORY ;
- ;***************************************************************;
- PUBLIC _DVIDTIME
- _DVIDTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH ES ; SAVE ES
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- DB 066H ; 32 BIT OPERANDS:
- XOR DI, DI ; CLEAR EDI
- DB 066H ; 32 BIT OPERANDS:
- XOR CX, CX ; CLEAR ECX
- MOV AX, VIDBASE ; GET BASE ADDRESS
- MOV ES, AX ;
- DB 066H ; 32 BIT OPERANDS:
- MOV AX, 0700H ; MOV EAX, 07000700H
- DW 0700H ;
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- DB 066H ; 32 BIT OPERANDS:
- REP STOSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP ES ; RESTORE ES
- POP BP ; RESTORE BP
- RET ; RETURN
- _DVIDTIME ENDP
- ;***************************************************************;
- ; _SETUP_VIDEO ;
- ; DETECT THE TYPE OF VIDEO CARD AND SAVE THE BASE ;
- ;***************************************************************;
- PUBLIC _SETUP_VIDEO
- _SETUP_VIDEO PROC NEAR
- PUSH BP ; SAVE REGISTERS
- PUSH ES ;
- PUSH SI ;
- PUSH DI ;
- INT 11H ; EQUIPMENT DETERMINATION
- AND AL, 30H ; MASK DISPLAY BITS
- CMP AL, 30H ; CHECK FOR MONOCHROME
- MOV AX, 0B000H ; MONOCHROME BASE
- JE SVM ; JUMP IF MONOCHROME
- MOV AX, 0B800H ; COLOR BASE
- SVM: MOV VIDBASE, AX ; SAVE BASE ADDRESS
- POP DI ; RESTORE REGISTERS
- POP SI ;
- POP ES ;
- POP BP ;
- RET ; RETURN 0
- _SETUP_VIDEO ENDP
- ;***************************************************************;
- ; _FPTIME ;
- ; TIME EXECUTION OF FLOATING POINT DIVIDE ;
- ;***************************************************************;
- PUBLIC _FPTIME
- _FPTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DI ; SAVE DI
-
- ALIGN FP,F ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- LEA BX, FL ; UNPRIME TEST AREA
- MOV CX, 300 ;
- CALL UNPRIME ;
- MOV DI, 0 ; CLEAR DI
- MOV AX, [BP+4] ; GET COUNT ARGUMENT
- ADD AX, 99 ; ROUND UP
- MOV CX, 100 ; DIVIDE BY 100 =
- DIV CL ; NUMBER OF INSTRUCTIONS
- MOV CL, AL ; PER PASS
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- FNINIT ; INIT FP
- FLD1 ; DIVIDE 1.0
- FLD1 ; BY 1.0
- CLI ; STOP INTERRUPTS
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- FL: REPT 100 ; DO 100 DIVIDES
- FDIV ST(1), ST ;
- ENDM ; END MACRO
- DEC CX ; COUNT THIS PASS
- JZ FD ; JUMP IF COMPLETE
- JMP FL ; LOOP BACK IF NOT DONE
- FD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _FPTIME ENDP
- ;***************************************************************;
- ; _WEMPTIME ;
- ; TIME EXECUTION OF PUSHA INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _WEMPTIME
- _WEMPTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- PUSH DI ; SAVE DI
- MOV BP, SP ;
-
- ALIGN WEMP,EP ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- MOV AX, [BP+6] ; GET COUNT ARGUMENT
- CWD ; MAKE DOUBLE WORD
- MOV CX, 200 ;
- DIV CX ; DIVIDE BY MOVS/LOOP
- MOV CX, AX ;
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- MOV DX, SS ; SAVE STACK SEGMENT
- MOV SS, EMMBASE ; PUT STACK IN EMM
- MOV SP, 400 ; SET SP FOR PUSHES
- MOV DI, SP ; SAVE THIS NUMBER
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- EPL: REPT 25 ; PUSH THE REGISTERS
- DB 60H ;
- ENDM ;
- MOV SP, DI ; PUT THE STACK BACK
- LOOP EPL ; LOOP UNTIL DONE
- EPD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- MOV SS, DX ; RESTORE ORIGINAL STACK
- MOV SP, BP ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _WEMPTIME ENDP
- ;***************************************************************;
- ; _DEMPTIME ;
- ; TIME EXECUTION OF PUSHA INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _DEMPTIME
- _DEMPTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- PUSH DI ; SAVE DI
- MOV BP, SP ;
-
- ALIGN DEMP,ED ; Align instructions on dword boundary
-
- CALL SETUP_TIMER ; SET UP TIMER
- MOV AX, [BP+6] ; GET COUNT ARGUMENT
- CWD ; MAKE DOUBLE WORD
- MOV CX, 200 ;
- DIV CX ; DIVIDE BY MOVS/LOOP
- MOV CX, AX ;
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- MOV DX, SS ; SAVE STACK SEGMENT
- MOV SS, EMMBASE ; PUT STACK IN EMM
- MOV SP, 800 ; SET SP FOR PUSHES
- MOV DI, SP ; SAVE THIS NUMBER
- OUT PPI_PORT, AL ; ENABLE TIMER
- INSTR_ALIGN ; Ensure instruction alignment
- EDL: REPT 25 ; PUSH THE BIG REGISTERS
- DB 66H, 60H ;
- ENDM ; END MACRO
- MOV SP, DI ; PUT THE STACK BACK
- LOOP EDL ; LOOP UNTIL DONE
- EDD: MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- MOV SS, DX ; RESTORE ORIGINAL STACK
- MOV SP, BP ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP BP ; RESTORE BP
- RET ; RETURN
- _DEMPTIME ENDP
- ;***************************************************************;
- ; _BEMMTIME ;
- ; TIME EXECUTION OF REP MOVSB INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _BEMMTIME
- _BEMMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- MOV DI, EMMBASE ; SET UP EMM BASE ADDRESS
- MOV ES, DI ;
- MOV DS, DI ;
- MOV SI, 5 ; ES:SI -> BYTE IN TEST SEGMENT
- XOR DI, DI ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP MOVSB ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _BEMMTIME ENDP
- ;***************************************************************;
- ; _WEMMTIME ;
- ; TIME EXECUTION OF REP MOVSW INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _WEMMTIME
- _WEMMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- MOV DI, EMMBASE ; SET UP EMM BASE ADDRESS
- MOV ES, DI ;
- MOV DS, DI ;
- MOV SI, 6 ; ES:SI -> WORD IN TEST SEGMENT
- XOR DI, DI ; ES:DI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- REP MOVSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _WEMMTIME ENDP
- ;***************************************************************;
- ; _DEMMTIME ;
- ; TIME EXECUTION OF REP MOVSW INSTRUCTION ;
- ;***************************************************************;
- PUBLIC _DEMMTIME
- _DEMMTIME PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSH DS ; SAVE DS
- PUSH ES ; SAVE ES
- PUSH SI ; SAVE SI
- PUSH DI ; SAVE DI
- CALL SETUP_TIMER ; SET UP TIMER
- DB 066H ; 32 BIT OPERANDS:
- XOR DI, DI ; CLEAR EDI
- DB 066H ; 32 BIT OPERANDS:
- XOR SI, SI ; CLEAR ESI
- DB 066H ; 32 BIT OPERANDS:
- XOR CX, CX ; CLEAR ECX
- MOV DI, EMMBASE ; SET UP EMM BASE ADDRESS
- MOV ES, DI ;
- MOV DS, DI ;
- XOR DI, DI ; ES:DI -> TEST SEGMENT
- XOR SI, SI ; DS:SI -> TEST SEGMENT
- MOV CX, [BP+4] ; GET COUNT ARGUMENT
- IN AL, PPI_PORT ; GET CURRENT CONTROL
- MOV BL, AL ; SAVE IN BL
- OR AL, 1 ; SET TIMER ENABLE BIT
- CLI ; STOP INTERRUPTS
- CLD ; SET FORWARD DIRECTION
- OUT PPI_PORT, AL ; ENABLE TIMER
- DB 066H ; 32 BIT OPERANDS:
- REP MOVSW ; RUN TEST
- MOV AL, BL ; RESTORE CONTROL VALUE
- OUT PPI_PORT, AL ;
- STI ; START INTERRUPTS
- CALL GET_TIMER ; OBTAIN FINAL COUNT
- POP DI ; RESTORE DI
- POP SI ; RESTORE SI
- POP ES ; RESTORE ES
- POP DS ; RESTORE DS
- POP BP ; RESTORE BP
- RET ; RETURN
- _DEMMTIME ENDP
- ;***************************************************************;
- ; _SETUP_EMM ;
- ; SET UP EXPANDED MEMORY AND RETURN THE BASE ;
- ;***************************************************************;
- PUBLIC _SETUP_EMM
- _SETUP_EMM PROC NEAR
- PUSH BP ; SAVE REGISTERS
- PUSH ES ;
- PUSH SI ;
- PUSH DI ;
- MOV AH, 35H ; GET EMM INTERRUPT
- MOV AL, 67H ; VECTOR
- INT 21H ;
- MOV DI, 000AH ; OFFSET OF DRIVER NAME
- LEA SI, EMM_NAME ; COMPARE STRING
- MOV CX, 8 ; LENGTH OF STRING
- CLD ;
- REPE CMPSB ; COMPARE THE NAME
- JNE SENO ; JUMP IF NO GOOD
- SE1: MOV AH, 40H ; FUNCTION 1:
- INT 67H ; GET MANAGER STATUS
- CMP AH, 82H ; CHECK FOR BUSY
- JE SE1 ; TRY AGAIN IF BUSY
- OR AH, AH ; CHECK FOR ERROR
- JNZ SENO ; JUMP ON ERROR
- SE2: MOV AH, 41H ; FUNCTION 2:
- INT 67H ; GET PAGE FRAME BASE
- CMP AH, 82H ; CHECK FOR BUSY
- JE SE2 ; TRY AGAIN IF BUSY
- OR AH, AH ; CHECK FOR ERROR
- JNZ SENO ; JUMP ON ERROR
- MOV EMMBASE, BX ; SAVE THE BASE
- SE3: MOV AH, 42H ; FUNCTION 3:
- INT 67H ; GET NUMBER OF PAGES
- CMP AH, 82H ; CHECK FOR BUSY
- JE SE3 ; TRY AGAIN IF BUSY
- OR AH, AH ; CHECK FOR ERROR
- JNZ SENO ; JUMP ON ERROR
- OR BX, BX ; CHECK UNALLOCATED PAGES
- JZ SENO ; JUMP IF NONE AVAILABLE
- SE4: MOV AH, 43H ; FUNCTION 4:
- MOV BX, 1 ; ALLOCATE ONE PAGE
- INT 67H ;
- CMP AH, 82H ; CHECK FOR BUSY
- JE SE4 ; TRY AGAIN IF BUSY
- OR AH, AH ; CHECK FOR ERROR
- JNZ SENO ; JUMP ON ERROR
- MOV PID, DX ; SAVE THE PROCESS ID
- SE5: MOV AH, 44H ; FUNCTION 5:
- XOR BX, BX ; MAP THE PAGE TO
- XOR AL, AL ; FRAME BASE
- INT 67H ;
- CMP AH, 82H ; CHECK FOR BUSY
- JE SE5 ; TRY AGAIN IF BUSY
- OR AH, AH ; CHECK FOR ERROR
- JNZ SENC ; JUMP ON ERROR
- XOR AX, AX ;
- POP DI ; RESTORE REGISTERS
- POP SI ;
- POP ES ;
- POP BP ;
- RET ; RETURN 0
- SENC: MOV AH, 45H ; FUNCTION 6:
- INT 67H ; CLOSE EMM
- CMP AH, 82H ; CHECK FOR BUSY
- JE SENC ; TRY AGAIN IF BUSY
- SENO: MOV AX, 0FFFFH ;
- POP DI ; RESTORE REGISTERS
- POP SI ;
- POP ES ;
- POP BP ;
- RET ; RETURN -1
- _SETUP_EMM ENDP
- ;***************************************************************;
- ; _FINISH_EMM ;
- ; CLOSE THE EMM DEVICE, RELEASE THE PAGE ;
- ;***************************************************************;
- PUBLIC _FINISH_EMM
- _FINISH_EMM PROC NEAR
- PUSH BP ; SAVE REGISTERS
- PUSH ES ;
- PUSH SI ;
- PUSH DI ;
- SE6: MOV AH, 45H ; FUNCTION 6:
- MOV DX, PID ; CLOSE EMM
- INT 67H ;
- CMP AH, 82H ; CHECK FOR BUSY
- JE SE6 ; TRY AGAIN IF BUSY
- POP DI ; RESTORE REGISTERS
- POP SI ;
- POP ES ;
- POP BP ;
- RET ; RETURN
- _FINISH_EMM ENDP
- ;***************************************************************;
- ; PRIME ;
- ; PRIME THE CACHE, IF ANY, BY SCANNING TEST AREA ;
- ;***************************************************************;
- PRIME PROC NEAR
- PUSH AX ; SAVE ALL REGISTERS USED
- PUSH DI ; SAVE SI (START ADDRESS)
- PUSH CX ; SAVE CX (COUNT)
- PUSH ES ; SAVE ES
- MOV AX, CS ; SET ES TO DS
- MOV ES, AX ;
- MOV DI, BX ; PUT ADDRESS IN DI
- MOV AL, 111 ; USE UNLIKELY VALUE IN AL
- CLD ; SET FORWARD DIRECTION
- PL: REPNE SCASB ; SCAN MEMORY
- JCXZ PE ; JUMP IF DONE
- JMP PL ; JUMP BACK IF NOT DONE
- PE: POP ES ;
- POP CX ; RESTORE REGISTERS
- POP DI ;
- POP AX ;
- RET ; RETURN
- PRIME ENDP
- ;***************************************************************;
- ; UNPRIME ;
- ; PRIME THE CACHE, IF ANY, BY SCANNING AWAY FROM TEST AREA;
- ;***************************************************************;
- UNPRIME PROC NEAR
- PUSH AX ; SAVE ALL REGISTERS USED
- PUSH DI ; SAVE SI (START ADDRESS)
- PUSH CX ; SAVE CX (COUNT)
- PUSH ES ; SAVE ES
- MOV AX, CS ; SET ES TO CS + 64K
- ADD AX, 1000H ;
- MOV ES, AX ;
- MOV DI, BX ; PUT ADDRESS IN DI
- MOV AL, 111 ; USE UNLIKELY VALUE IN AL
- CLD ; SET FORWARD DIRECTION
- UPL: REPNE SCASB ; SCAN MEMORY
- JCXZ UPE ; JUMP IF DONE
- JMP UPL ; JUMP BACK IF NOT DONE
- UPE: POP ES ;
- POP CX ; RESTORE REGISTERS
- POP DI ;
- POP AX ;
- RET ; RETURN
- UNPRIME ENDP
- ;***************************************************************;
- ; SETUP_TIMER ;
- ; SET UP THE TIMER FOR MAXIMUM COUNT, TO TIME A RUN ;
- ;***************************************************************;
- SETUP_TIMER PROC NEAR
- PUSH AX ; SAVE AX
- IN AL, PPI_PORT ; STOP THE TIMER
- AND AL, 0FCH ;
- OUT PPI_PORT, AL ;
- MOV AL, 0B4H ; INITIALIZE THE TIMER
- OUT TIMER_CTRL, AL ;
- JMP $+2 ; Drain PIQ
- MOV AL, 0 ; CLEAR THE COUNT
- OUT TIMER2_PORT, AL ;
- JMP $+2 ; Drain PIQ
- OUT TIMER2_PORT, AL ;
- POP AX ; RESTORE AX
- RET ; RETURN
- SETUP_TIMER ENDP
- ;***************************************************************;
- ; GET_TIMER ;
- ; TAKE THE COUNT FROM THE TIMER ;
- ;***************************************************************;
- GET_TIMER PROC NEAR
- IN AL, TIMER2_PORT ; GET LOW BYTE OF TIME
- MOV AH, AL ;
- IN AL, TIMER2_PORT ; GET HIGH BYTE
- XCHG AL, AH ; TIME IN AX
- NEG AX ; CORRECT FOR COUNT-DOWN
- RET ; RETURN
- GET_TIMER ENDP
- ;***************************************************************;
- ; _NDP_PRESENT ;
- ; CHECK IF 80287 IS PRESENT ;
- ;***************************************************************;
- PUBLIC _NDP_PRESENT
- _NDP_PRESENT PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- INT 11H ; BIOS EQUIP CHECK
- TEST AL,02H ; IS 80287 BIT SET?
- JZ NO ; NO MEANS NO 80287
- MOV AX,01h ; RETURN TRUE
- JMP NDPEXIT ; ALL DONE
- NO: XOR AX,AX ; SET AX TO FALSE
- NDPEXIT:MOV SP, BP ; RESTORE SP
- POP BP ; RESTORE BP
- RET ; RETURN
- _NDP_PRESENT ENDP
- ;***************************************************************;
- ; _DETECT_387 ;
- ; CHECK IF MATH COPROCESSOR IS 80387 ;
- ;***************************************************************;
- PUBLIC _DETECT_387
- _DETECT_387 PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- FINIT ; USE DEFAULT INFINITY MODE
- FLD1 ; GENERATE INFINITY
- FLDZ ;
- FDIV ;
- FLD ST ; FORM NEGATIVE INFINITY
- FCHS ; BY CHANGING SIGN
- FCOMPP ; COMPARE +/-INFINITY
- FSTSW STATUSW ; EQUAL FOR 8087/287
- FWAIT ; WAIT
- MOV AX,STATUSW ;
- SAHF ; STORE RESULT IN FLAGS
- JZ NO387 ; NOT A 80387
- MOV AX,01h ; RETURN TRUE
- JMP D3EXIT ; ALL DONE
- NO387: XOR AX,AX ; SET AX TO FALSE
- D3EXIT: MOV SP, BP ; RESTORE SP
- POP BP ; RESTORE BP
- RET ; RETURN
- _DETECT_387 ENDP
- ;***************************************************************;
- ; _CPU_TYPE ;
- ; CHECK IF CPU IS 8088/8086, 80188/80186, 80286, 80386 ;
- ;***************************************************************;
- PUBLIC _CPU_TYPE
- _CPU_TYPE PROC NEAR
- PUSH BP ; SAVE FRAME
- MOV BP, SP ;
- PUSHF ;
- MOV CL,20H ; INITIALIZE SHIFT COUNT
- MOV AX,1 ; DESTINATION
- SHR AX,CL ; SHIFT RIGHT
- TEST AX,1 ; IS AX THE SAME?
- JZ _8X ; IS 8086 OR 8088
- PUSH SP ; SEE IF SP IS UPDATED
- POP BX ; BEFORE OR AFTER IT IS
- CMP BX,SP ; PUSHED
- JNE _18X ; IS 80188 OR 80186
- MOV AX,0F000H ; TRY TO SET HIGH BITS
- PUSH AX ;
- POPF ; IN THE FLAGS
- PUSHF ;
- POP AX ; LOOK AT ACTUAL FLAGS
- AND AX,0F000H ; ANY HIGH BITS SET?
- JE _286 ; IS 80286
- _386: MOV AX,03 ; IS AN 80386
- JMP CTEXIT ;
- _286: MOV AX,02 ; IS AN 80286
- JMP CTEXIT ;
- _18X: MOV AX,01 ; IS AN 80188/80186
- JMP CTEXIT ;
- _8X: MOV AX,00 ; IS AN 8088/8086
- CTEXIT: POPF ; RESTORE ORIGINAL FLAGS
- MOV SP, BP ; RESTORE SP
- POP BP ; RESTORE BP
- RET ; RETURN
- _CPU_TYPE ENDP
- ;***************************************************************;
- ; DD_ALIGN ;
- ; Ensure instruction fectches are on a dword boundary. ;
- ;***************************************************************;
- PUBLIC DD_ALIGN
- DD_ALIGN PROC NEAR
- assume ds:nothing,es:nothing ; Tell the assembler about it
-
- DD_ALIGN_STR struc
-
- dw ? ; Caller's BP
- dw ? ; Caller's IP
- DD_ALIGN_START dw ? ; Offset of alignment start
- DD_ALIGN_LEN dw ? ; Length of alignment area
-
- DD_ALIGN_STR ends
-
- push bp ; Prepare to address the stack
- mov bp,sp ; Hello, Mr. Stack
-
- REGSAVE <cx,si,di,ds,es> ; Save registers
-
- push cs ; Setup DS and ES for code references
- pop ds
- assume ds:_TEXT ; Tell the assembler about it
- push cs
- pop es
- assume es:_TEXT ; Tell the assembler about it
-
- mov si,[bp].DD_ALIGN_START ; Get source offset
- mov di,si ; Copy as destination offset
- and di,not (4-1) ; Round down to DD boundary
- mov cx,[bp].DD_ALIGN_LEN ; Get length in bytes
- rep movsb ; Move it down
-
- ; Fill in the tail with NOPs
-
- mov cx,si ; Get current source offset
- sub cx,di ; Less current destin to get length of tail
- mov al,90h ; Fill with NOPs
- rep stosb ; Fill it up
-
- REGREST <es,ds,di,si,cx> ; Restore
- assume ds:nothing,es:nothing ; Tell the assembler about it
-
- pop bp ; Restore
-
- ret 2*2 ; Return to caller, popping arguments
-
- assume ds:nothing,es:nothing ; Tell the assembler about it
-
- DD_ALIGN ENDP
- _TEXT ENDS
- END