forked from skiselev/8088_bios
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcpu.inc
371 lines (331 loc) · 9.19 KB
/
cpu.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
;=========================================================================
; cpu.inc - Detect and print CPU type and FPU presence
;-------------------------------------------------------------------------
;
; Compiles with NASM 2.13.02, might work with other versions
;
; Copyright (C) 2010 - 2023 Sergey Kiselev.
; Provided for hobbyist use on the Xi 8088 and Micro 8088 boards.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;=========================================================================
flags_tf equ 0100h ; TF flag - enables single-step
;=========================================================================
; detect_cpu - detect and print CPU type
; Note:
; - Designed to detect 8088, 80C88, and V20 CPU. Likely will return
; incorrect results if used on other CPU types.
;-------------------------------------------------------------------------
detect_cpu:
push ax
push si
mov al,e_cpu_detect
out post_reg,al
mov si,msg_cpu
call print
; test for NEC V20
mov ax,0101h
aad 10h ; NEC V20 ignores the argument
cmp al,0Bh ; and always does AL = AL * 0Ah + AH
je .nec_v20
; not NEC V20, test for various 8088 versions
.i8088: ; 8088 - NMOS version of 8088
cli ; disable interrupts
push ds
xor ax,ax
mov ds,ax ; interrupt table segment
mov ax,.int_01 ; new int 01h offset
xchg ax,word [4] ; switch with original int 1 offset
push ax ; save to stack
mov ax,cs ; new int 01h segment
xchg ax,word [6] ; switch with original int 1 segment
push ax ; save to stack
pushf ; push flags to stack (save)
pushf ; push flags to stack (modify)
pop ax ; and move them to AX
or ax,flags_tf ; set TF
push ax
xor ax,ax ; AX = 0
popf ; load modified value to FLAGS register
; enable single-step
nop
push ds ; Harris 80C88 disables interrupts
; after PUSH SREG instructions
.push_sreg: ; and will not single-step to here
pop ds ; 1981 and newer 8088 disable interrupts
; after modifying segment registers
.pop_sreg: ; and will not single-step to here
nop
popf ; restore original FLAGS, disable
; single-step
pop si ; get original int 01h segment
mov word [6],si ; save it to interrupt table
pop si ; get original int 01h offset
mov word [4],si ; save it to interrupt table
pop ds
sti ; enable interrupts
cmp ax,0001h ; if AX = 0001h - we have INTEL (C) 1978
jz .i8088_78
cmp ax,0002h
jz .i8088_81
.harris: ; Harris / Intersil 80C88
mov si,msg_cpu_harris
call print
jmp .cpu_freq
.i8088_78:
mov si,msg_cpu_8088_78
call print
jmp .cpu_freq
.i8088_81:
mov si,msg_cpu_8088_81
call print
jmp .cpu_freq
.nec_v20:
mov si,msg_cpu_nec_v20
call print
.cpu_freq:
%ifdef TURBO_MODE
; print CPU clock frequency
mov si,msg_at
call print
push ax
call get_config_a ; read BIOS configuration byte A
call print_cpu_clk
pop ax
%endif ; TURBO_MODE
mov si,msg_crlf
call print
cmp ax,0001h ; if AX = 0001h - we have INTEL (C) 1978
jnz .exit
mov si,msg_cpu_bug
call print
.exit:
pop si
pop ax
ret
; stack frame after "push bp"
; BP - word [BP]
; IP - word [BP+2]
; CS - word [BP+4]
; FLAGS - word [BP+6]
.int_01:
push bp
mov bp,sp
cmp word [bp+2],.pop_sreg ; if IP = .pop_sreg we have '78 CPU
jne .1
mov al,01h ; (C) INTEL '79
jmp .int_01_exit
.1:
cmp word [bp+2],.push_sreg ; if IP = .push_sreg it is not Harris
jne .int_01_exit
mov al,02h ; not Harris / Intersil 80C88
.int_01_exit:
pop bp
iret
;=========================================================================
; detect_fpu - detect and print FPU (mathematics coprocessor) presence
;-------------------------------------------------------------------------
test_word equ 03FEh ; right at the end of interrupt table
detect_fpu:
push ax
push cx
push si
mov al,e_fpu_detect
out post_reg,al
mov si,msg_fpu
call print
fninit ; initialize coprocessor
mov cx,3
.wait:
loop .wait ; wait for coprocessor to initialize
; (can't use fwait, since it could
; be no coprocessor at all)
mov cx,word [test_word] ; save test_word to CX
mov word [test_word],0000h ; clear space for control word
fnstcw word [test_word] ; store control word
cmp word [test_word],03FFh ; 8087 sets control word to 03FFh
jne .no_fpu ; after finit
.fpu:
mov si,msg_fpu_present
call print
or word [equipment_list],equip_fpu ; update equipment word
jmp .exit
.no_fpu:
mov si,msg_absent
call print
.exit:
mov word [test_word],cx ; restore initial value of test_word
pop si
pop cx
pop ax
ret
%ifdef MACHINE_FE2010A
;=========================================================================
; detect_chipset - detect and print chipset type
; Input:
; none
; Output:
; none
; Note: This subroutine also disables DRAM refresh on both FE2010A and PT8010AF
;-------------------------------------------------------------------------
detect_chipset:
push ax
push si
mov si,msg_chipset
call print
mov si,msg_fe2010a
mov al,54h ; channel 1, LSB only, mode 2, binary
out pit_ctl_reg,al ; used for DRAM refresh on IBM PC/XT/AT
mov al,12h ; or for delays (using port_b, bit 4)
out pit_ch1_reg,al ; pulse every 15ms
mov al,40h ; this disables refresh on FE2010A
out pit_ctl_reg,al ; but not on PT8010AF
in al,pit_ch1_reg
cmp al,12h ; should be 12h on FE2010A
je .print_chipset
mov si,msg_pt8010af
.print_chipset:
call print
mov al,54h ; channel 1, LSB only, mode 2, binary
out pit_ctl_reg,al ; this disables memory refresh
pop ax
pop si
ret
%endif ; MACHINE_FE2010A
%ifdef TURBO_MODE
;=========================================================================
; print_cpu_clk - Print CPU clock frequency
; Input:
; AL - NVRAM CPU clock frequency configuration (bits 1:0)
; 0 - 4.77 MHz / Normal
; 1 - 7.16 MHz / Turbo
; 2 - 9.55 MHz (FE2010A)
; Output:
; none
;-------------------------------------------------------------------------
print_cpu_clk:
push ax
push si
and al,nvram_trbo_mask ; get turbo bits
%ifdef MACHINE_FE2010A
mov si,msg_clk_7_16mhz
cmp al,1
je .print
mov si,msg_clk_9_55mhz
cmp al,2
je .print
%endif ; MACHINE_FE2010A
%ifdef MACHINE_XI8088
mov si,msg_clk_turbo
cmp al,1
je .print
%endif ; MACHINE_XI8088
mov si,msg_clk_4_77mhz
.print:
call print
pop si
pop ax
ret
;=========================================================================
; set_cpu_clk - Set CPU clock frequency
; Input:
; AL - NVRAM CPU clock frequency configuration
; 0 - 4.77 MHz / Normal
; 1 - 7.16 MHz / Turbo
; 2 - 9.55 MHz (FE2010A)
; Output:
; none
;-------------------------------------------------------------------------
set_cpu_clk:
%ifdef MACHINE_FE2010A
cmp al, 1
je set_cpu_clk_7_16mhz
cmp al, 2
je set_cpu_clk_9_55mhz
jmp set_cpu_clk_4_77mhz
%endif ; MACHINE_FE2010A
%ifdef MACHINE_XI8088
cmp al,1
je set_cpu_clk_turbo
jmp set_cpu_clk_4_77mhz
%endif ; MACHINE_XI8088
ret
;=========================================================================
; set_cpu_clk_4_77mhz - Set CPU clock at 4.77 MHz
; set_cpu_clk_7_16mhz - Set CPU clock at 7.16 MHz
; set_cpu_clk_9_55mhz - Set CPU clock at 9.55 MHz
; set_cpu_clk_turbo - Set CPU clock at turbo frequency (system dependent)
; Input:
; none
; Output:
; none
;-------------------------------------------------------------------------
%ifdef MACHINE_FE2010A
set_cpu_clk_4_77mhz:
push ax
mov al,byte [equipment_list] ; get lower byte of the equipment list
and al,equip_fpu ; isolate FPU installed bit
or al,fe_par_disable ; disable memory parity checking
out fe_config_reg,al ; clear bits 7-5 - 4.77 MHz CPU clock
pop ax
ret
set_cpu_clk_7_16mhz:
push ax
call get_config_a
mov ah,al
mov al,byte [equipment_list] ; get lower byte of the equipment list
and al,equip_fpu ; isolate FPU installed bit
or al,fe_par_disable ; disable memory parity checking
or al,fe_clk_7_norm ; set bit 6 - 7.15 MHz CPU clock
test ah,nvram_fast_ws ; nvram_fast_ws = 1 - Normal wait states
jnz .set_config
or al,fe_clk_7_fast
.set_config:
out fe_config_reg,al
pop ax
ret
set_cpu_clk_9_55mhz:
push ax
call get_config_a
mov ah,al
mov al,byte [equipment_list] ; get lower byte of the equipment list
and al,equip_fpu ; isolate FPU installed bit
or al,fe_par_disable ; disable memory parity checking
or al,fe_clk_9_norm ; set bit 7 - 9.54 MHz CPU clock
test ah,nvram_fast_ws
jnz .set_config ; nvram_fast_ws = 1 - Normal wait states
or al,fe_clk_9_fast
.set_config:
out fe_config_reg,al
pop ax
ret
%endif ; MACHINE_FE2010A
%ifdef MACHINE_XI8088
set_cpu_clk_4_77mhz:
push ax
in al,ppi_pb_reg
and al,0FBh ; clear bit 2 (turbo enable bit)
out ppi_pb_reg,al
pop ax
ret
set_cpu_clk_turbo:
push ax
in al,ppi_pb_reg
or al,04h ; set bit 2 (turbo enable bit)
out ppi_pb_reg,al
pop ax
ret
%endif ; MACHINE_XI8088
%endif ; TURBO_MODE