home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / pent_bug.zip / p87test.asm next >
Assembly Source File  |  1994-11-13  |  9KB  |  335 lines

  1.         .model tiny
  2.  
  3.         .data
  4. one     dt      1.0
  5. bugnr   dt      824633702449.0
  6. diff    dt      ?               ; Should be 0.0 after testing!
  7.  
  8. feature_bits dd ?
  9.  
  10. cpu_msg dw      I808x$, I186$, I286$, I386$, I486$, cpuid5$
  11. ndp_msg dw      No87$, I8087$, I287$, I387$
  12.  
  13. feature_list dw fpu$, vme$, iobrk$, pse$, tsc$, p5msr$, 0, mce$, cx8$
  14.  
  15. cprt    db      'Pentium FDIV bug finder.  (c) Terje Mathisen 1994'
  16.         db      13,10,13,10,'$'
  17.  
  18. I808x$  db      'This is an 808x cpu',13,10,'$'
  19. I186$   db      'This is a 186 cpu',13,10,'$'
  20. I286$   db      'This is a 286 cpu',13,10,'$'
  21. I386$   db      'This is a 386 cpu',13,10,'$'
  22. I486$   db      'This is a 486 cpu',13,10,'$'
  23. cpuid5$ db      'This is a Pentium or better cpu',13,10,'$'
  24.  
  25. No87$   db      'It has no ndp!',13,10,'$'
  26. I8087$  db      'It has an 8087 ndp',13,10,'$'
  27. I287$   db      'It has a 287 ndp',13,10,'$'
  28. I387$   db      'It has a 387 or later ndp',13,10,'$'
  29.  
  30. fpu$    db      '  1 : FPU (NDP) onchip',13,10,'$'
  31. vme$    db      '  2 : Virtual 86 Mode Extensions',13,10,'$'
  32. iobrk$  db      '  4 : I/O Breakpoints',13,10,'$'
  33. pse$    db      '  8 : Page Size Extensions',13,10,'$'
  34. tsc$    db      ' 10 : Time Stamp Counter',13,10,'$'
  35. p5msr$  db      ' 20 : Pentium stype MSRs',13,10,'$'
  36. mce$    db      ' 80 : Machine Check Exception',13,10,'$'
  37. cx8$    db      '100 : CMPXCHG8B instruction available',13,10,'$'
  38.  
  39. earlyP5$ db 'This is an early Pentium, with only partial CPUID support!',13,10,'$'
  40.  
  41. cpuid_result$   db 13,10,'CPUID reports back:',13,10
  42.         db      'Vendor id = "'
  43. vendor_id dd    3 dup (?)
  44.         db      '"',13,10
  45.         db      'Family (4=486, 5=Pentium etc.) = '
  46. make$   dw      '00'
  47.         db      ', stepping = '
  48. step$   dw      '00'
  49.         db      ', model = '
  50. model$  dw      '00'
  51.         db      13,10,'$'
  52.  
  53. feature_msg1$ db 13,10,'CPU feature list:',13,10
  54. feature_msg2$ db '$'
  55.  
  56. FPU_bug$ db     13,10,'It has the FDIV bug:',13,10
  57.    db  '(1.0/824633702449.0)*824633702449.0 is not equal to 1.0!',13,10,'$'
  58.  
  59. FPU_OK$ db      13,10,'It does not have the FDIV bug!',13,10,'$'
  60.  
  61. stepping db     ?
  62. CPUModel db     ?
  63. Cpu_Type db     ?       ; 0,1,2,3,4,5 etc
  64. Ndp_Type db     ?       ; None, 8087, 287, 387+
  65. have_cpuid db   0
  66.  
  67. Notp5$  db      'The FDIV bug occurs only on Pentium cpus!',13,10,'$'
  68.  
  69.         .code
  70.         org     100h
  71. start   proc    far
  72.  
  73.         lea     dx,[cprt]
  74.         mov     ah,9
  75.         int     21h
  76.  
  77.         call    getcpu
  78.  
  79.         mov     bl,[cpu_type]
  80.         cmp     bl,5
  81.          jbe    @@ok
  82.         mov     bl,5
  83. @@ok:
  84.         xor     bh,bh
  85.         add     bx,bx
  86.         mov     dx,cpu_msg[bx]
  87.         mov     ah,9
  88.         int     21h
  89.  
  90.         test    [have_cpuid],-1
  91.          jz     no_cpuid
  92.  
  93.         mov     bx, word ptr [feature_bits]
  94.         mov     ax, word ptr [feature_bits+2]
  95.         or      ax,bx
  96.         lea     dx,[earlyP5$]
  97.          jz     dispMsg
  98.  
  99. ;
  100. ; We have full CPUID support on this cpu, report back what we found!
  101. ;
  102.         mov     al,[stepping]
  103.         xor     ah,ah
  104.         mov     bl,10
  105.         div     bl
  106.         add     ax,'00'
  107.         mov     [step$],ax
  108.  
  109.         mov     al,[CpuModel]
  110.         xor     ah,ah
  111.         div     bl
  112.         add     ax,'00'
  113.         mov     [model$],ax
  114.  
  115.         mov     al,[cpu_type]
  116.         xor     ah,ah
  117.         div     bl
  118.         add     ax,'00'
  119.         mov     [make$],ax
  120.         
  121.         lea     dx,[cpuid_result$]
  122.         mov     ah,9
  123.         int     21h
  124. ;
  125. ; Display feature bits definitions:
  126. ;
  127.         lea     si,[feature_list-2]
  128.         mov     cx,9            ; Nr of defined feature bits
  129.         mov     di,word ptr [feature_bits]
  130.  
  131.         lea     dx,[feature_msg1$]
  132.         mov     ah,9
  133.         int     21h
  134.  
  135. @@next_feature:
  136.         add     si,2
  137.         shr     di,1
  138.          jnc    @@skip_feature
  139.         mov     dx,[si]
  140.         mov     ah,9
  141.         int     21h
  142.  
  143. @@skip_feature:
  144.         dec     cx
  145.          jnz    @@next_feature
  146.  
  147.         lea     dx,[feature_msg2$]
  148. dispMsg:
  149.         mov     ah,9
  150.         int     21h
  151.  
  152. no_cpuid:
  153.         call    getndp
  154.         mov     bl,[ndp_type]
  155.         cmp     bl,3
  156.          jbe    @@ndp_ok
  157.         mov     bl,3
  158. @@ndp_ok:
  159.         xor     bh,bh
  160.         add     bx,bx
  161.         mov     dx,ndp_msg[bx]
  162.         mov     ah,9
  163.         int     21h
  164.  
  165.         test    bx,bx
  166.          jz     exit            ; No NDP, so no NDP bug either! :-)
  167.  
  168.         call    testndp
  169.         lea     dx,[FPU_OK$]
  170.          jz     @@disp_bug
  171.         lea     dx,[FPU_Bug$]
  172. @@disp_bug:
  173.         mov     ah,9
  174.         int     21h
  175.  
  176. exit:
  177.         mov     ax,4c00h
  178.         int     21h             ; All done!
  179. start   endp
  180.  
  181. getcpu  proc    ; return 0,1,2,3,4,5 etc in BL for 808x,186,286,386...
  182.  
  183.         pushf
  184.         pop     ax
  185.         and     ah,0fh          ; Try to clear four upper flag bits!
  186.         push    ax
  187.         popf
  188.         pushf
  189.         pop     ax
  190.         xor     bx,bx           ; Assume 808x -> BX = 0
  191.         cmp     ah,0f0h
  192.          jae    getcpu_done     ; All four upper bits set -> 808x!
  193.  
  194.         or      ah,0f0h         ; Try to set the upper four bits:
  195.         push    ax
  196.         popf
  197.         pushf
  198.         pop     ax
  199.         and     ah,0f0h         ; Isolate them
  200.         mov     bx,2            ; This is a 286!
  201.          jz     getcpu_done     ; Just a 286, no FDIV problem!
  202. ;
  203. ; *************** 386+ code *******************
  204. ;
  205.         .486
  206.         mov     edx,esp
  207.         and     esp,not 3               ; DWORD-align ESP!
  208.  
  209.         pushfd
  210.         pop     eax
  211.         mov     ecx,eax
  212.         xor     ecx,1 SHL 18    ; AC flag == bit # 18!
  213.         push    ecx
  214.         popfd
  215.         pushfd
  216.         pop     ecx
  217.         push    eax
  218.         popfd
  219.         mov     esp,edx
  220.  
  221.         inc     bx              ; BX = 3
  222.         xor     ecx,eax         ; Could we toggle the AC flag?
  223.          jz     getcpu_done     ; No, so this is a 386!
  224.  
  225.         mov     ecx,eax
  226.         xor     eax,1 SHL 21    ; ID flag == bit # 21!
  227.         push    eax
  228.         popfd
  229.         pushfd
  230.         pop     eax
  231.         inc     bx              ; BX = 4
  232.         xor     eax,ecx         ; Could we toggle the ID bit?
  233.          jnz    haveCPUID       ;
  234.  
  235. getcpu_done:
  236.         mov     [cpu_type],bl
  237.         ret                     ; Return with BX = CPU ID
  238.  
  239. haveCPUID:
  240.         mov     [have_cpuid],1  ; Minimal support for CPUID
  241.  
  242. ; Use CPUID to get more info!
  243.         xor     eax,eax
  244.         db      0Fh, 0A2h       ; CPUID opcode!
  245.  
  246.         mov     [vendor_id],ebx
  247.         mov     [vendor_id+4],edx
  248.         mov     [vendor_id+8],ecx
  249.         test    eax,eax
  250.          jz     getcpu_done
  251.  
  252.         mov     eax,1
  253.         db      0Fh, 0A2h       ; CPUID opcode!
  254.         mov     [feature_bits],edx
  255.         and     ah,15           ; CPU Make [4(486), 5 (Pentium) etc]
  256.         mov     [cpu_type],ah   ; Save it! (Return value)
  257.  
  258.         mov     ah,al
  259.         shr     ah,4
  260.         and     al,15
  261.         mov     [stepping],al
  262.         mov     [CpuModel],ah
  263.         .8086
  264.  
  265.         ret
  266. getcpu  endp
  267.  
  268.         .data
  269. cw      dw      ?
  270.  
  271.         .code
  272.  
  273. getndp  proc
  274.         fninit
  275.         xor     dx,dx                   ; DL = (NO87, 8087, 287, 387+)
  276.         mov     bx,offset cw
  277.         mov     [bx],dx                 ; Make sure ControlWord is zero!
  278.         fnstcw  [bx]
  279.          jmp    $+2                     ; Wait for result
  280.          jmp    $+2                     ; Wait for result
  281.          jmp    $+2                     ; Wait for result
  282.         cmp     byte ptr [bx+1],03
  283.          jne    ndpdone                 ; NO 87 installed
  284.  
  285.         fdisi                           ; 8087 Disable interrupts
  286.         fstcw   [bx]
  287.         inc     dx                      ; At least 8087
  288.         fwait                           ;  Wait for result from FSTCW
  289.         test    byte ptr [bx],80h       ; DISI bit set?
  290.          jnz    ndpdone                 ; Yes, it's a 8087
  291.  
  292.         .286
  293.         .287
  294.         inc    dx                       ; 80287 or 80387
  295.         fld1
  296.         fldz
  297.         fdivp   st(1),st                ; 1/0 = +Inf
  298.         fld     st(0)
  299.         fchs                            ; = -Inf
  300.         fcompp
  301.         fwait                           ; Wait for result
  302.         fstsw   ax
  303.         sahf                            ; Status from float point cmp
  304.          je     ndpdone                 ; +Inf == -Inf => 287
  305.         inc     dx                      ; 387
  306.         .8086
  307.         .8087
  308. ndpdone:
  309.         mov    [ndp_type],dl
  310.         ret
  311.  
  312. getndp  endp
  313.  
  314. testndp proc
  315. ; Check for FPU bug: Return Z(ero)/NonZero for OK/Bad
  316.  
  317.         finit
  318.         fld     [one]
  319.         fld     [bugnr]
  320.         fdivp   st(1),st
  321.         fld     [bugnr]
  322.         fmulp   st(1),st
  323.         fld     [one]
  324.         fsubp   st(1),st
  325.         fstp    [diff]
  326.         fwait
  327.         mov     ax,word ptr [diff]
  328.         or      ax,word ptr [diff+2]
  329.         or      ax,word ptr [diff+4]
  330.         ret
  331. testndp endp
  332.  
  333.         end     start
  334.  
  335.