OSDN Git Service

updated copyleft and need to test and fix newer version of open watcom
[proj16/16.git] / src / lib / wcpu / 16_wcpu.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2022 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 /* tab size = 8 */\r
23 \r
24 #include "src/lib/wcpu/16_wcpu.h"\r
25 \r
26 //#define USECPUPROBE\r
27 \r
28 byte WCPU_detectfpu()\r
29 {\r
30         byte fputype=0;\r
31         word funk=0;\r
32         boolean errflag=0;\r
33         __asm {\r
34                 PUSHF                                           ; we gonna modify flags, so back them up\r
35 .8087           fninit                                                  ; Initialize FPU\r
36 //              mov     [WORD PTR funk], 55AAh          ; Set junk value\r
37 //              fnstsw  funk                                    ; Store status word\r
38 //              cmp     [BYTE PTR funk], 0                      ; If it's not 0, no FPU\r
39                 mov     funk, 55AAh                             ; Set junk value\r
40                 fnstsw  funk                                    ; Store status word\r
41                 cmp     funk, 0                                 ; If it's not 0, no FPU\r
42 //              jne     short   _done\r
43                 jne     short   _err\r
44                 jmp     _fpu\r
45                 _err:\r
46                 mov     errflag, 1\r
47                 _fpu:\r
48 /*      }\r
49         if(!errflag){\r
50         printf(".");\r
51         __asm {*/\r
52                 fnstcw  funk                                    ; Store control word\r
53                 mov     ax, funk                                        ; If the bits are not the way\r
54                 and     ax, 103Fh                                       ; they should be, no FPU\r
55                 cmp     ax, 3Fh\r
56 //              jne     short _done\r
57                 je      short   __err\r
58                 jmp     __fpu\r
59                 __err:\r
60                 mov     errflag, 1\r
61                 __fpu:\r
62         /*}}\r
63         if(!errflag){\r
64         printf(".");\r
65         __asm {*/\r
66 //              and     [WORD PTR funk], 0FF7Fh         ; Clear interrupt bit\r
67                 and     funk, 0FF7Fh                            ; Clear interrupt bit\r
68                 fldcw   funk                                            ; Load control word\r
69                 fdisi                                                   ; Disable interrupts\r
70                 fstcw   funk                                            ; Store control word\r
71 //              test    [BYTE PTR funk], 80h                    ; If it changed, it's an 8087\r
72                 test    funk, 80h                                       ; If it changed, it's an 8087\r
73                 mov     fputype, 1\r
74 \r
75                 _done:\r
76                 POPF                                            ; restore flags we backed up earlier\r
77         }//}\r
78         //printf("WCPU_detectfpu():\n   fputype=%u\n    funk=%u errflag=%u\n", fputype, funk, errflag);\r
79 #ifdef USECPUPROBE\r
80         if (cpu_flags & CPU_FLAG_FPU) printf(" - With FPU\n");\r
81 #endif\r
82         return fputype;\r
83 }\r
84 \r
85 byte WCPU_detectcpu()\r
86 {\r
87         byte cputype=0;\r
88         __asm {\r
89                 PUSHF                   ; we gonna modify flags, so back them up\r
90                 ; first check if its 8086/8088 or 80186/80188\r
91                 PUSHF                   ; FLAGS -> STACK\r
92                 POP     AX              ; STACK -> AX\r
93                 AND     AX, 00FFFh      ; clear 12-15 bits (they are always 1 on 8086/8088 and 80186/80188)\r
94                 PUSH    AX              ; AX -> STACK\r
95                 POPF                    ; STACK -> FLAGS\r
96                 ; this is where magic happen\r
97                 PUSHF                   ; FLAGS -> STACK\r
98                 POP     AX              ; STACK -> AX\r
99                 AND     AX, 0F000h      ; 0-11 bits aren't important to us\r
100                 CMP     AX, 0F000h      ; check if all 12-15 bits are set (simple comparision)\r
101                 JNE     _286p           ; if no, 286+ CPU\r
102                 MOV     cputype, 0      ; if yes, we are done, set cputype to 0 and end this\r
103                 JMP     _done\r
104         _286p:\r
105                 ; now check if its 286 or newer\r
106                 PUSHF                   ; FLAGS -> STACK\r
107                 POP     AX              ; STACK -> AX\r
108                 OR      AX, 07000h      ; set 12-14 bits (they are always cleared by 286 if its real mode)\r
109                 PUSH    AX              ; AX -> STACK\r
110                 POPF                    ; STACK -> FLAGS\r
111                 ; this is where magic happen\r
112                 PUSHF                   ; FLAGS -> STACK\r
113                 POP     AX              ; STACK -> AX\r
114                 TEST    AX, 07000h      ; check if at least 1 bit in 12-14 bits range is set (15th won't be set anyway)\r
115                 JNZ     _386p           ; not all bits clear, its 386+\r
116                 MOV     cputype, 1      ; all bits clear, its 286, we are done\r
117                 JMP     _done\r
118         _386p:\r
119                 MOV     cputype, 2      ; its 386 or newer, but we don't care if its newer at this point\r
120         _done:\r
121                 POPF                    ; restore flags we backed up earlier\r
122         }\r
123         return cputype;\r
124 }\r
125 \r
126 const char *WCPU_cpudetectmesg()\r
127 {\r
128         const char *cpus;\r
129         unsigned char cput;\r
130 \r
131         cput = WCPU_detectcpu();\r
132         switch(cput)\r
133         {\r
134                 case 0: cpus = "8086/8088 or 80186/80188"; break;\r
135                 case 1: cpus = "80286"; break;\r
136                 case 2: cpus = "80386 or newer"; break;\r
137                 default: cpus = "internal error"; break;\r
138         }\r
139         return cpus;\r
140 }\r
141 \r
142 const char *WCPU_fpudetectmesg()\r
143 {\r
144         char *fpus;\r
145         unsigned char fput;\r
146         word cput;\r
147 \r
148         fput = WCPU_detectfpu();\r
149         cput = WCPU_detectcpu();\r
150         switch(cput)\r
151         {\r
152                 case 0: cput=80; break;\r
153                 case 1: cput=802; break;\r
154                 case 2: cput=803; break;\r
155                 default: cput=0; break;\r
156         }\r
157         switch(fput)\r
158         {\r
159                 case 0: fpus = "none"; break;\r
160                 case 1: sprintf(fpus, "%d87", cput); break;\r
161                 default: fpus = "internal error"; break;\r
162         }\r
163         return fpus;\r
164 }\r
165 \r
166 void WCPU_cpufpumesg()\r
167 {\r
168 #ifdef USECPUPROBE\r
169         cpu_probe();\r
170 #endif\r
171         printf("detected CPU type: %s\n",       WCPU_cpudetectmesg());\r
172         printf("detected FPU type: %s\n",       WCPU_fpudetectmesg());\r
173 }\r