home *** CD-ROM | disk | FTP | other *** search
- (* Code from m274.
- (117) Thu 6 Jun 91 3:30a
- By: Robert Mashlan
- To: All
- Re: TEST286.PAS
- St: Reply in 118
- -----------------------------------------------------------------------------
- @EID:522d 16c61bcf
- @MSGID: 1:147/38 63036254
- Hello All,
-
- It was brought to my attention by Michelango Jones that Borland's Test286.pas
- demo program was provided by Borland such than you can provide a stub function
- for a program compiled with {$G+}. The problem with this code is that is
- unfairly leaves out lesser CPUs capable of running this code.
-
- If you use {$G+}, please feel free to use this code!
-
- ===========================================================
- *)
-
- {$G+}
- Unit Test186;
-
- (* test186.pas 6-6-91 Robert Mashlan
-
- license: to public domain
-
- This unit provides a stub function for code compiled with TP 6.0's
- "286" code generation directive {$G-}. Borland provides a demo
- program called TEST286.PAS that checks if the machine is a 286 or
- better, but leaves out the 80186/80188/V20/V30 machines perfectly
- capable of running code compiled in this mode.
-
- To use this unit, simply place it as the first unit listed in a {$G+}
- program's unit clause. If the CPU is not capable of running the
- program, it will abort.
-
- *)
-
-
- Interface
-
- Implementation
-
- Function Is186Able : boolean; assembler;
- (* This function returns true if the CPU is not a 8088/8086, which
- cannot run code compiled in {$G+} mode. A NEC V20, V30,
- Intel 80186, 80188, 286, 386, and 486 can all run TP 6.0's
- "286" code and return true.
- *)
- asm
- pushf ;(* save flags */
-
- (* This test differentiates between a 286 and up and an 80186 and below
- This is done by checking the value of bits 12-15 in the flag register
- when it is pushed onto the stack. If they are set, then the CPU
- is not a 286 and up.
-
- *)
-
- xor ax,ax ;(* set ax=0 *)
- push ax ;(* push onto stack *)
- popf ;(* pop flags *)
- pushf ;(* push flags *)
- pop ax ;(* pop into ax *)
- and ax,0f000h ;(* mask upper 4 bits *)
- cmp ax,0f000h ;(* are bits 12-15 set? *)
- jne @exit186 ;(* NO: is a 286 and up *)
-
-
- (* This test differentiates a 80186/80188 between a V20/V30/8088/8086.
- The 80186/80188 will clear the upper three bits of the shift count
- before executing a shift instruction using the cl register.
- *)
-
- mov al,0ffh ;(* set all bits in al *)
- mov cl,021h ;(* try shifting 21h times *)
- shr al,cl ;(* try shifting *)
- jne @exit186 ;(* if al!=0 then it is a 80186/80188 *)
-
- (* This test differentiates the NEC V20/V30 between the 8088/8086
-
- This is done by testing for a bug in the 8088/8086. In the
- Intel CPUs, if a repeated string instruction with a segment
- override is interrupted by a hardware interrupt, the
- instruction is not continued.
- *)
- sti ;(* enable interrupts *)
- push si ;(* save si ( could be a register variable) *)
- mov si,0 ;(* Starting with first byte in es *)
- mov cx,0ffffh ;(* read a complete segment *)
- db 0f3h, 26h, 0ach;
- { rep lodsb es:[si] } ;(* rep with a segment override *)
- (* hardware interrupt is sure to occur during the above instruction *)
- pop si ;(* restore si *)
- or cx,cx ;(* has entire segment been read? *)
- je @exit186 ;(* YES: V20 or V30 *)
- (* NO: must be 8088 or 8086 *)
-
- @exitnot186:
- mov ax, 0; ; (* return false *)
- jmp @exit
-
- @exit186:
- mov ax,01h ;(* return true *)
- @exit: ;
- popf ;(* restore flags *)
- end;
-
- begin
- if not Is186Able then
- begin
- Writeln('This program will not run on an 8088/8086.');
- Halt(1);
- end;
- end.
-