source: vendor/emx/current/src/dos/except.asm

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 30.6 KB
Line 
1;
2; EXCEPT.ASM -- Handle excetions
3;
4; Copyright (c) 1991-1995 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26 INCLUDE EMX.INC
27 INCLUDE SWAPPER.INC
28 INCLUDE DEBUG.INC
29 INCLUDE VPRINT.INC
30 INCLUDE OPRINT.INC
31 INCLUDE PMIO.INC
32 INCLUDE PMINT.INC
33 INCLUDE SIGNAL.INC
34 INCLUDE PROCESS.INC
35 INCLUDE CORE.INC
36 INCLUDE TABLES.INC
37 INCLUDE MISC.INC
38
39 PUBLIC EXC_TAB, STDOUT_DUMP
40 PUBLIC EXCEPT_FAKE, EXCEPT_RET, EXCEPT_TASK, EXCEPT_NAME
41
42
43SER_FLAG = FALSE ; Don't use serial interface
44DEBUG_PTRACE = FALSE
45
46SV_DATA SEGMENT
47
48EXCEPT2 EQU NMI
49
50EXC_TAB LABEL WORD
51 IRP X,<0,1,2,3,4,5,6,7,9,11,12,13,14,15,16,17>
52 DW X, EXCEPT&X
53 ENDM
54 DW 0FFFFH, 0FFFFH
55
56$EXCEPTION DB "Exception ",0
57$ERRCODE DB "ERRCODE=",0
58$CS DB "CS=", 0
59$EIP DB " EIP=", 0
60$SS DB "SS=", 0
61$ESP DB " ESP=", 0
62$EFLAGS DB "EFLAGS=", 0
63$CR2 DB "CR2=", 0
64
65$DS DB "DS=", 0
66$ES DB "ES=", 0
67$FS DB "FS=", 0
68$GS DB "GS=", 0
69$EAX DB "EAX=", 0
70$EBX DB "EBX=", 0
71$ECX DB "ECX=", 0
72$EDX DB "EDX=", 0
73$ESI DB "ESI=", 0
74$EDI DB "EDI=", 0
75$EBP DB "EBP=", 0
76
77$EXCEPT0 DB "divide error", 0
78$EXCEPT1 DB "debug exception", 0
79$EXCEPT2 DB "nonmaskable interrupt", 0
80$EXCEPT3 DB "breakpoint", 0
81$EXCEPT4 DB "overflow", 0
82$EXCEPT5 DB "bounds check", 0
83$EXCEPT6 DB "invalid opcode", 0
84$EXCEPT7 DB "coprocessor not available", 0
85$EXCEPT8 DB "double fault", 0
86$RESERVED DB "reserved", 0
87$EXCEPT10 DB "invalid TSS", 0
88$EXCEPT11 DB "segment not present", 0
89$EXCEPT12 DB "stack exception", 0
90$EXCEPT13 DB "general protection", 0
91$EXCEPT14 DB "page fault", 0
92$EXCEPT15 DB "reserved", 0
93$EXCEPT16 DB "coprocessor error", 0
94$EXCEPT17 DB "alignment check", 0
95
96EXCEPT_TEXTS DW $EXCEPT0, $EXCEPT1, $EXCEPT2, $EXCEPT3
97 DW $EXCEPT4, $EXCEPT5, $EXCEPT6, $EXCEPT7
98 DW $EXCEPT8, $RESERVED, $EXCEPT10, $EXCEPT11
99 DW $EXCEPT12, $EXCEPT13, $EXCEPT14, $EXCEPT15
100 DW $EXCEPT16, $EXCEPT17
101
102REG_16 EQU 10000H
103REG_NL EQU 20000H
104
105REG_TAB LABEL DWORD
106 DD OFFSET $DS, 6 OR REG_16
107 DD OFFSET $ES, 4 OR REG_16
108 DD OFFSET $FS, 2 OR REG_16
109 DD OFFSET $GS, 0 OR REG_16 OR REG_NL
110 DD OFFSET $EAX, 36
111 DD OFFSET $EBX, 24
112 DD OFFSET $ECX, 32
113 DD OFFSET $EDX, 28 OR REG_NL
114 DD OFFSET $ESI, 12
115 DD OFFSET $EDI, 8
116 DD OFFSET $EBP, 16
117 DD 0, 0
118
119;
120; Table for converting exception numbers to signal numbers
121;
122EXC_TO_SIG_TAB DB SIGILL ; 0 Unused
123 DB SIGTRAP ; 1 Debug
124 DB SIGBUS ; 2 NMI
125 DB SIGTRAP ; 3 Breakpoint
126 DB SIGFPE ; 4 Overflow
127 DB SIGFPE ; 5 BOUND
128 DB SIGILL ; 6 Invalid instruction
129 DB SIGFPE ; 7 Numeric coprocessor not available
130 DB SIGSEGV ; 8 Double fault
131 DB SIGSEGV ; 9 Coproc. operand seg. limit viol.
132 DB SIGILL ; 10 Invalid task state segment
133 DB SIGSEGV ; 11 Segment not present
134 DB SIGSEGV ; 12 Stack fault
135 DB SIGSEGV ; 13 General protection
136 DB SIGSEGV ; 14 Page fault
137 DB SIGBUS ; 15 Unused
138 DB SIGFPE ; 16 Numeric coprocessor error
139 DB SIGSEGV ; 17 Alignment check (486)
140
141;
142; Send register dump of exception to stdout (not to CON) if NOT FALSE
143;
144STDOUT_DUMP DB FALSE
145
146SV_DATA ENDS
147
148
149SV_CODE SEGMENT
150
151 ASSUME CS:SV_CODE, DS:NOTHING
152
153 .386P
154
155 ASSUME DS:NOTHING
156
157
158 IRP X,<0,1,3,4,5,6,7,9,11,12,13,14,15,16,17>
159 TALIGN 2
160EXCEPT&X:
161 IF &X LE 7 OR &X EQ 15 OR &X EQ 16 ; Assume EX 17 w/errcd
162 PUSH DWORD PTR 0 ; Mock error code
163 ENDIF
164 PUSHAD ; Save the general registers
165 MOV AL, X ; Exception number to AL
166 JMP EXCEPT ; Common code
167 ENDM
168
169;
170; Common code for all exceptions
171;
172; This code is called via an interrupt gate, therefore interrupts are
173; disabled.
174;
175
176
177 ASSUME DS:NOTHING
178 ASSUME BP:PTR ISTACKFRAME
179 TALIGN 4
180EXCEPT: PUSH DS ; Save segment registers
181 PUSH ES
182 PUSH FS
183 PUSH GS
184 IF SER_FLAG
185 PUSH AX
186 SERIAL "E"
187 POP AX
188 ENDIF
189 MOV EBP, ESP ; Setup stack frame
190 SUB ESP, FRAME_SIZE ; Local variables
191 MOV BX, G_SV_DATA_SEL
192 MOV DS, BX ; Make data segment accessible
193 ASSUME DS:SV_DATA
194 MOV EXCEPT_NO, AL ; Save exception number
195 CLD
196;
197; Check for debugging
198;
199 IF DEBUG_PTRACE
200 CMP AL, 1 ; Debug exception?
201 JE SHORT EXCEPT_4 ; Yes -> built-in debugger
202 ENDIF
203;
204; Check for page faults
205;
206 CMP AL, 14 ; Page fault?
207 JNE SHORT EXCEPT_1
208 CALL PAGE_FAULT ; Yes -> try to handle this
209;
210; Check for floating-point exceptions
211;
212EXCEPT_1: IF FLOATING_POINT
213 CMP EXCEPT_NO, 7 ; Coprocessor not available?
214 JNE SHORT EXCEPT_2 ; No -> skip
215 CALL EXCEPT_DNA ; Task switch / emulator
216 ENDIF
217;
218; Check for return from signal handler
219;
220EXCEPT_2: CMP EXCEPT_NO, 13 ; General protection violation?
221 JNE SHORT EXCEPT_3 ; No -> skip
222 MOV EAX, I_ERRCD ; Get error code
223 OR AX, AX ; Tried to load a selector?
224 JNE SHORT EXCEPT_3 ; Yes -> skip
225 MOVZX EAX, I_CS ; Get CS
226 LSL EAX, EAX ; Get code segment limit
227 JNZ SHORT EXCEPT_3 ; Avoid another exception
228 MOV ESI, I_EIP ; Put CS:EIP into ES:ESI
229 MOV ES, I_CS ; NB: All segments are readable
230 CMP ESI, EAX ; EIP beyond limit?
231 JA SHORT EXCEPT_3 ; Yes -> avoid another exception
232 CMP BYTE PTR ES:[ESI], 0C3H ; Pointing to RETN?
233 JNE SHORT EXCEPT_3 ; No -> skip
234 MOVZX EAX, I_SS ; Get SS
235 LSL EAX, EAX ; Get stack segment limit
236 JNZ SHORT EXCEPT_3 ; Avoid another exception
237 SUB EAX, size SIGFRAME - 1 ; We examine a SIGFRAME
238 JC SHORT EXCEPT_3 ; Cannot happen
239 MOV ESI, I_ESP ; Put SS:ESP into ES:ESI
240 ASSUME ESI:NEAR32 PTR SIGFRAME
241 MOV ES, I_SS ; NB: Expand=Up
242 CMP ESI, EAX ; ESP beyond limit?
243 JA SHORT EXCEPT_3 ; Yes -> avoid another exception
244 CMP ES:[ESI].SF_EIP, SIG_EIP ; Our special EIP?
245 JNE SHORT EXCEPT_3 ; No -> skip
246 CMP ES:[ESI].SF_SIGNATURE, SIG_SIGNATURE ; Signature?
247 JNE SHORT EXCEPT_3 ; No -> skip
248 CALL SIG_RETURN ; Return from signal handler
249 ASSUME ESI:NOTHING
250 JMP EXCEPT_12 ; Signal not handled
251
252;
253; This entry point is used for SIGFPE (see PMINT.ASM).
254;
255EXCEPT_FAKE: MOV EXCEPT_NO, AL
256
257;
258; Check for ptraced process
259;
260EXCEPT_3: TEST I_CS, 3 ; In supervisor?
261 JZ SHORT EXCEPT_4 ; Yes -> skip
262 MOV BX, PROCESS_PTR ; Current process
263 CMP BX, NO_PROCESS ; No process?
264 JE SHORT EXCEPT_4 ; Yes -> skip (cannot happen)
265 TEST (PROCESS PTR [BX]).P_FLAGS, PF_DEBUG
266 JZ SHORT EXCEPT_4 ; Process not in debug mode ->
267 CALL EXCEPT_PTRACE ; Return to ptracing process
268EXCEPT_4: CMP EXCEPT_NO, 1 ; Debug exception?
269 JNE SHORT EXCEPT_5 ; No -> skip
270 CALL DEBUG_EXCEPTION
271 JMP SHORT EXCEPT_10
272
273;
274; Give the debugger a chance
275;
276EXCEPT_5: CMP STEP_FLAG, FALSE ; -S option?
277 JE SHORT EXCEPT_6
278 CALL DEBUG_EXCEPTION
279;
280; Check for exceptions to be mapped to signals
281;
282EXCEPT_6: TEST I_CS, 3 ; Called from user code?
283 JZ SHORT EXCEPT_10 ; No -> skip
284 MOV BX, PROCESS_PTR ; Current process
285 CMP BX, NO_PROCESS ; No process?
286 JE SHORT EXCEPT_10 ; Yes -> skip
287 ASSUME BX:PTR PROCESS
288 MOV AL, EXCEPT_NO ; Compute signal number
289 CALL EXC_TO_SIG ; from exception number
290 MOV EDX, EAX ; EDX := signal number
291;
292; Deliver the signal if a signal handler is set. Deliver the
293; signal even if it is blocked.
294;
295 MOV SI, DX
296 SHL SI, 2
297 MOV EAX, [BX].P_SIG_HANDLERS[SI] ; Get address
298 CMP EAX, SIG_IGN ; Ignore signal
299 JE SHORT EXCEPT_10 ; Yes -> skip
300 CMP EAX, SIG_DFL ; Default processing?
301 JE SHORT EXCEPT_10 ; Yes -> skip
302 CALL EXCEPT_SIGNAL ; Deliver the signal
303 ASSUME BX:NOTHING
304;
305; Display register dump if appropriate
306;
307EXCEPT_10: CMP I_CS, L_CODE_SEL ; In user code?
308 JE SHORT EXCEPT_11 ; Yes -> don't show registers
309 CALL EX_DUMP
310EXCEPT_11: CMP I_CS, L_CODE_SEL ; In user code?
311 JNE SHORT STOP ; No -> loop forever
312;
313; Display message. Dump core unless disabled
314;
315 MOV AL, EXCEPT_NO
316 CALL EXC_TO_SIG
317EXCEPT_12: CALL SIG_MSG ; Display "Stopped by SIG..."
318 CMP EAX, SIGNALS ; Valid signal number?
319 JAE SHORT EXCEPT_13 ; No -> dump core
320 CMP SIG_CORE[EAX], FALSE ; Dump core for this signal?
321 JE SHORT NOCORE ; No -> skip
322EXCEPT_13: MOV BX, PROCESS_PTR ; Current process
323 CMP BX, NO_PROCESS ; No process?
324 JE SHORT NOCORE ; Yes -> skip
325 TEST (PROCESS PTR [BX]).P_FLAGS, PF_NO_CORE
326 JNZ SHORT NOCORE ; Core dumps disabled -> skip
327 CALL CORE_REGS_I
328 CALL CORE_DUMP
329NOCORE: MOV AX, 4CFFH
330 INT 21H
331
332STOP: JMP STOP
333
334;
335; Return from exception handler. This code is either CALLed from the
336; exception handler or JuMPed to by a procedure CALLed by the exception
337; handler.
338;
339 TALIGN 2
340EXCEPT_RET: ADD ESP, 2 + FRAME_SIZE ; Remove return address and
341 ; local data
342;
343; Deliver pending signals. This is required for delivering signals
344; on return from a signal handler.
345;
346 CALL SIG_DELIVER_PENDING
347 POP GS
348 POP FS
349 POP ES
350 POP DS
351 POPAD
352 NOP ; Avoid 386 bug
353 ADD ESP, 4 ; Skip error code
354 IRETD
355
356
357;
358; Switch back to the process that issued ptrace(P_STEP)
359;
360; In: BX PROCESS_PTR
361;
362 ASSUME DS:SV_DATA
363 ASSUME BX:PTR PROCESS
364EXCEPT_PTRACE: MOV [BX].P_STATUS, PS_STOP ; Process stopped
365 OR [BX].P_FLAGS, PF_WAIT_WAIT
366 MOV AL, EXCEPT_NO ; Get exception number
367 CALL EXC_TO_SIG ; Convert to signal number
368 MOV [BX].P_SIG_NO, AL ; and store it
369 PUSH EAX ; Save it for ptrace result
370 CALL SAVE_PROCESS ; Save outgoing process
371 MOV EAX, [BX].P_PPID ; Parent process ID
372 CALL FIND_PROCESS ; Find table entry
373 POP EAX ; Signal number
374 CMP BX, NO_PROCESS ; Not found?
375 JE SHORT EXCEPT_PTRACE_1 ; Should not happen
376 MOV PROCESS_PTR, BX ; Switch to parent process
377 MOV PROCESS_SIG, BX
378 MOV CX, [BX].P_STATUS ; Get process status
379 CALL REST_PROCESS ; Restore incoming process
380 CMP CX, PS_WAIT_PTRACE ; Has been waiting in ptrace?
381 JNZ SHORT EXCEPT_PTRACE_1 ; No -> should not happen
382 MOV I_EAX, EAX ; Return signal number
383 MOV I_ECX, 0 ; No error
384 CALL BREAK_AFTER_IRET ; For built-in debugger
385 JMP EXCEPT_RET ; Return to ptrace
386EXCEPT_PTRACE_1:RET ; Continue exception handler
387 ASSUME BX:NOTHING
388 ASSUME BP:NOTHING
389
390
391 ASSUME DS:SV_DATA
392 ASSUME BP:PTR ISTACKFRAME
393EX_DUMP PROC NEAR
394 CMP I_CS, L_CODE_SEL
395 JE SHORT EX_DUMP3
396 MOV VOUTPUT, NOT FALSE
397 MOV ETEXT, OFFSET SV_CODE:VTEXT
398 MOV EBYTE, OFFSET SV_CODE:VBYTE
399 MOV EWORD, OFFSET SV_CODE:VWORD
400 MOV EDWORD, OFFSET SV_CODE:VDWORD
401 MOV ECRLF, OFFSET SV_CODE:VCRLF
402 MOV ECHAR, OFFSET SV_CODE:VCHAR
403 MOV AX, G_VIDEO_SEL
404 MOV ES, AX
405 CALL VCLS
406 JMP SHORT EX_DUMP5
407
408EX_DUMP3: MOV VOUTPUT, FALSE
409 MOV ETEXT, OFFSET SV_CODE:OTEXT
410 MOV EBYTE, OFFSET SV_CODE:OBYTE
411 MOV EWORD, OFFSET SV_CODE:OWORD
412 MOV EDWORD, OFFSET SV_CODE:ODWORD
413 MOV ECRLF, OFFSET SV_CODE:OCRLF
414 MOV ECHAR, OFFSET SV_CODE:OCHAR
415 CMP STDOUT_DUMP, FALSE
416 JNE SHORT EX_DUMP4
417 CALL FORCE_STDOUT
418EX_DUMP4: CALL OCRLF
419EX_DUMP5: LEA EDX, $EXCEPTION
420 CALL ETEXT
421 MOV AL, EXCEPT_NO
422 CALL EBYTE
423 CMP AL, 17
424 JA SHORT EX_DUMP6
425 MOV AL, ":"
426 CALL ECHAR
427 MOV AL, " "
428 CALL ECHAR
429 MOV AL, EXCEPT_NO
430 CALL EXCEPT_NAME
431 CALL ETEXT
432EX_DUMP6: CALL ECRLF
433 MOV AL, EXCEPT_NO
434 CMP AL, 8
435 JB SHORT NO_ERRCODE
436 CMP AL, 14
437 JA SHORT NO_ERRCODE
438 LEA EDX, $ERRCODE
439 CALL ETEXT
440 MOV EAX, I_ERRCD
441 CALL EDWORD
442 CALL ECRLF
443NO_ERRCODE: LEA EDX, $CS
444 CALL ETEXT
445 MOV AX, I_CS
446 CALL EWORD
447 LEA EDX, $EIP
448 CALL ETEXT
449 MOV EAX, I_EIP
450 CALL EDWORD
451 CALL ECRLF
452;
453; Display SS:ESP
454;
455 MOV SI, I_SS
456 MOV EDI, I_ESP
457 TEST I_CS, 3 ; RPL = 0?
458 JNZ SHORT EXD_SS_ESP_1 ; No -> use values from stack
459;
460; For RPL=0 the stack has not been switched
461;
462 MOV SI, SS
463 LEA EDI, [EBP+56]
464EXD_SS_ESP_1: LEA EDX, $SS
465 CALL ETEXT
466 MOV AX, SI
467 CALL EWORD
468 LEA EDX, $ESP
469 CALL ETEXT
470 MOV EAX, EDI
471 CALL EDWORD
472 CALL ECRLF
473
474 LEA EDX, $EFLAGS
475 CALL ETEXT
476 MOV EAX, I_EFLAGS
477 CALL EDWORD
478 CALL ECRLF
479 CMP EXCEPT_NO, 14
480 JNE SHORT EX_NO_CR2
481 LEA EDX, $CR2
482 CALL ETEXT
483 MOV EAX, CR2
484 CALL EDWORD
485 CALL ECRLF
486EX_NO_CR2: LEA EDI, REG_TAB
487REG_DUMP_1: MOV EDX, [EDI+0]
488 OR EDX, EDX
489 JZ SHORT REG_DUMP_END
490 CALL ETEXT
491 MOV EAX, [EDI+4]
492 TEST EAX, REG_16
493 JNZ SHORT REG_DUMP_16
494 AND EAX, 0FFFFH
495 MOV EAX, SS:[EBP+EAX]
496 CALL EDWORD
497 JMP SHORT REG_DUMP_2
498REG_DUMP_16: AND EAX, 0FFFFH
499 MOV AX, SS:[EBP+EAX]
500 CALL EWORD
501REG_DUMP_2: TEST DWORD PTR [EDI+4], REG_NL
502 JZ SHORT REG_DUMP_3
503 CALL ECRLF
504 JMP SHORT REG_DUMP_9
505REG_DUMP_3: MOV AL, TAB
506 CALL ECHAR
507REG_DUMP_9: ADD EDI, 8
508 JMP SHORT REG_DUMP_1
509
510REG_DUMP_END: CALL ECRLF
511 LEA ESI, I_EFLAGS + 4
512 TEST I_CS, 3 ; RPL of return CS
513 JZ SHORT SAME_LEVEL_2 ; Called from supervisor
514 ADD ESI, 8 ; Skip ESP and SS
515SAME_LEVEL_2: XOR EAX, EAX
516 MOV AX, SS
517 MOV FS, AX
518 LSL ECX, EAX
519 INC ECX
520 SUB ECX, ESI
521 JBE SHORT NOSDUMP
522 SHR ECX, 1
523 CMP ECX, 128
524 JBE SHORT SDUMP1
525 MOV ECX, 128
526SDUMP1: CALL MEM_DUMP ; (FS, ESI, ECX)
527NOSDUMP: RET
528 ASSUME BP:NOTHING
529EX_DUMP ENDP
530
531
532;
533; Raise a signal from exception handler
534;
535; Note that this must be a procedure to get the stack right at EXCEPT_RET.
536;
537; In: EAX Address of the signal handler
538; EDX Signal number
539; BX Pointer to process table entry
540;
541EXCEPT_SIGNAL PROC NEAR
542 MOV ECX, NOT FALSE ; Trap
543 CALL SIG_USER_CALL ; Call user signal handler
544 JMP EXCEPT_RET ; (This enables interrupts)
545EXCEPT_SIGNAL ENDP
546
547;
548; Numeric coprocessor not available (DNA=device not available)
549;
550; Handle task switching and emulation
551;
552 IF FLOATING_POINT
553
554 ASSUME DS:SV_DATA
555 ASSUME BP:PTR ISTACKFRAME
556EXCEPT_DNA PROC NEAR
557 CMP FP_FLAG, FP_387 ; 387 coprocessor present?
558 JNE SHORT EDNA_EMU ; No -> emulate
559 CLTS ; Clear TS bit of CR0
560 MOV BX, PROCESS_FP ; Last process using FPU
561 CMP BX, PROCESS_PTR ; Same process?
562 JE SHORT EDNA_NO_REST ; Yes -> do nothing
563 CMP BX, NO_PROCESS ; Save status?
564 JE SHORT EDNA_NO_SAVE ; No -> skip
565 ASSUME BX:PTR PROCESS
566 DB 66H
567 FNSAVE [BX].P_CW ; Save FPU context, initialize
568 FWAIT
569EDNA_NO_SAVE: MOV BX, PROCESS_PTR ; Current process
570 MOV PROCESS_FP, BX ; FPU switched to new process
571 CMP BX, NO_PROCESS ; Any process?
572 JE SHORT EDNA_SV ; No -> in supervisor
573 TEST [BX].P_FLAGS, PF_387_USED ; Initialize?
574 JNZ SHORT EDNA_REST ; No -> restore
575 CALL SETUP_FP ; Initialize 387
576 OR [BX].P_FLAGS, PF_387_USED ; 387 initialized
577 JMP SHORT EDNA_NO_REST ; Don't restore
578
579EDNA_SV: CALL SETUP_FP ; Initialize 387
580 JMP SHORT EDNA_NO_REST ; Don't restore
581;
582; Note: 32-bit mode? 287?
583;
584EDNA_REST:
585 DB 66H
586 FRSTOR [BX].P_CW
587EDNA_NO_REST: JMP EXCEPT_RET ; Return to fp instruction
588
589;
590; Call coprocessor emulator.
591;
592; If there is no coprocess emulator, the untyped call and return
593; constructs of GCC 2.6.0 use the FNSAVE and FRSTOR instructions
594; even if no floating point code is used by the application.
595; Therefore, we silently ignore FNSAVE and FRSTOR.
596;
597; However, GCC 2.6.1 generates more complicated code which I don't
598; want to handle here. That doesn't matter as we have a real FPU
599; emulator now.
600;
601 TALIGN 4
602EDNA_EMU: TEST I_CS, 3 ; In supervisor?
603 JZ SHORT EDNA_EMU_RET ; Yes -> skip
604 CMP FPUEMU_STATE, FES_ON
605 JE SHORT EDNA_EMU_CALL
606 CMP FPUEMU_STATE, FES_OFF
607 JNE SHORT EDNA_EMU_NO
608 CALL FPUEMU_LOAD ; Try to load a FPU emulator
609 CMP FPUEMU_STATE, FES_LOADING
610 JNE SHORT EDNA_EMU_NO
611 JMP EXCEPT_RET ; Run the emulator
612
613; TODO: Abort if FP exception in emulator
614 TALIGN 4
615EDNA_EMU_CALL: CALL FPUEMU_CALL ; Switch to the FPU emulator
616 JMP EXCEPT_RET
617
618 TALIGN 4
619EDNA_EMU_NO: MOV ESI, I_EIP ; Put CS:EIP into ES:ESI
620 MOV ES, I_CS ; NB: All segments are readable
621 CMP BYTE PTR ES:[ESI], 0DDH ; 1st byte of FNSAVE, FRSTOR
622 JNE SHORT EDNA_EMU_RET ; Other -> default processing
623 INC ESI
624 MOV AH, ES:[ESI] ; Get MOD, XXX, R/M
625 INC ESI
626 MOV AL, AH
627 AND AL, 11000000B ; Extract MOD
628 CMP AL, 11000000B ; MOD=11?
629 JE SHORT EDNA_EMU_RET ; Yes -> not FSAVE/FRSTOR
630 MOV AL, AH
631 AND AL, 00111000B ; Extract XXX (opcode)
632 CMP AL, 00100000B ; FRSTOR?
633 JE SHORT FPEMU_1 ; Yes ->
634 CMP AL, 00110000B ; FSAVE?
635 JE SHORT FPEMU_1 ; Yes ->
636EDNA_EMU_RET: RET ; Default exception processing
637 ASSUME BX:NOTHING
638
639;
640; FSAVE and FRSTOR
641;
642FPEMU_1: MOV AL, AH
643 AND AL, 00000111B ; Extract R/M
644 CMP AL, 00000100B ; Use SIB?
645 JE SHORT FPEMU_SIB ; Yes -> look at SIB
646 MOV AL, AH
647 AND AL, 11000000B ; Extract MOD
648 JZ SHORT FPEMU_MOD00 ; MOD=00 ->
649 CMP AL, 01000000B ; MOD=01?
650 JE SHORT FPEMU_MOD01 ; Yes ->
651;
652; MOD=10: [REG+DISP32]
653;
654FPEMU_MOD10: ADD ESI, 4 ; Skip DISP32
655 JMP SHORT FPEMU_IGNORE
656
657;
658; MOD=01: [REG+DISP8]
659;
660FPEMU_MOD01: INC ESI ; Skip DISP8
661 JMP SHORT FPEMU_IGNORE
662
663;
664; MOD=00: [REG] or [DISP32]
665;
666FPEMU_MOD00: MOV AL, AH
667 AND AL, 00000111B ; Extract R/M
668 CMP AL, 00000101B ; EBP (meaning DISP32)?
669 JNE SHORT FPEMU_IGNORE ; No -> no displacement
670 ADD ESI, 4 ; Skip DISP32
671 JMP SHORT FPEMU_IGNORE
672
673;
674; R/M=100: SIB
675;
676FPEMU_SIB: MOV DL, ES:[ESI] ; Fetch SIB
677 INC ESI
678 MOV AL, AH
679 AND AL, 11000000B ; Extract MOD
680 JZ SHORT FPEMU_SIB_MOD00 ; MOD=00 ->
681 CMP AL, 01000000B ; MOD=01?
682 JE SHORT FPEMU_SIB_MOD01 ; Yes ->
683;
684; MOD=10: [REG+SCALE*INDEX+DISP32]
685;
686FPEMU_SIB_MOD10:ADD ESI, 4 ; Skip DISP32
687 JMP SHORT FPEMU_IGNORE
688
689;
690; MOD=01: [REG+SCALE*INDEX+DISP8]
691;
692FPEMU_SIB_MOD01:INC ESI ; Skip DISP8
693 JMP SHORT FPEMU_IGNORE
694
695;
696; MOD=00: [REG+SCALE*INDEX] or [DISP32+SCALE*INDEX]
697;
698FPEMU_SIB_MOD00:MOV AL, DL
699 AND AL, 00000111B ; Extract BASE
700 CMP AL, 00000100B ; EBP (meaning DISP32)?
701 JNE SHORT FPEMU_IGNORE ; No -> no displacement
702 ADD ESI, 4 ; Skip DISP32
703 JMP SHORT FPEMU_IGNORE
704
705;
706; Continue the application at EIP:=ESI
707;
708FPEMU_IGNORE: MOV I_EIP, ESI
709 JMP EXCEPT_RET
710
711
712;
713; Initialize 387 for new process
714;
715SETUP_FP PROC NEAR
716 FNINIT
717 FSTCW FP_TMP
718 FWAIT
719 OR FP_TMP, 3FH ; Use default error handlers
720 FLDCW FP_TMP
721 RET
722SETUP_FP ENDP
723
724 ASSUME BP:NOTHING
725EXCEPT_DNA ENDP
726
727 ENDIF
728
729;
730; Convert exception number to signal number
731;
732; In: AL Exception number (0..17, not checked!)
733;
734; Out: EAX Signal number
735;
736 ASSUME DS:SV_DATA
737EXC_TO_SIG PROC NEAR
738 PUSH BX
739 LEA BX, EXC_TO_SIG_TAB
740 XLAT EXC_TO_SIG_TAB
741 MOVZX EAX, AL
742 POP BX
743 RET
744EXC_TO_SIG ENDP
745
746;
747; Memory (stack) dump
748;
749; In: FS:ESI Source
750; CX Word count
751; ES:BX Destination
752;
753 ASSUME DS:NOTHING
754MEM_DUMP PROC NEAR
755 PUSH EAX
756 PUSH ESI
757 JCXZ MDUMP9
758MDUMP1: CMP VOUTPUT, FALSE
759 JE SHORT MDUMP2
760 MOV AX, 5
761 CALL VWRAP
762 CALL VGETCOL
763MDUMP2: MOV AX, FS:[ESI]
764 CALL EWORD
765 DEC CX
766 JZ SHORT MDUMP9
767 MOV AL, " "
768 CALL ECHAR
769 ADD ESI, 2
770 JMP MDUMP1
771MDUMP9: POP ESI
772 POP EAX
773 RET
774MEM_DUMP ENDP
775
776
777;
778; Task for exceptions 8 (double fault) and 10 (invalid TSS)
779;
780 ASSUME DS:SV_DATA ; Loaded from TSS
781EXCEPT_TASK: CLI ; Not required
782 IF SER_FLAG
783 SERIAL "T"
784 ENDIF
785 PUSH AX ; Exception number
786 MOV AX, G_VIDEO_SEL
787 MOV ES, AX
788 CALL VCLS
789 LEA EDX, $EXCEPTION
790 CALL VTEXT
791 POP AX ; Loaded from TSS
792 CALL VBYTE
793 PUSH AX
794 MOV AL, ":"
795 CALL VCHAR
796 MOV AL, " "
797 CALL VCHAR
798 POP AX
799 CALL EXCEPT_NAME
800 CALL VTEXT
801 CALL VCRLF
802 LEA EDX, $CS
803 CALL VTEXT
804 MOV AX, G_TSS_MEM_SEL
805 MOV FS, AX
806 MOV AX, (TSS_STRUC PTR FS:[0]).TSS_CS
807 CALL VWORD
808 LEA EDX, $EIP
809 CALL VTEXT
810 MOV EAX, (TSS_STRUC PTR FS:[0]).TSS_EIP
811 CALL VDWORD
812 CALL VCRLF
813 JMP $
814 ASSUME ESI:NOTHING
815
816;
817; Return name of exception
818;
819; In: AL Exception number
820;
821; Out: EDX Text
822;
823EXCEPT_NAME PROC NEAR
824 LEA EDX, $RESERVED
825 CMP AL, 17
826 JA SHORT ENAME1
827 PUSH BX
828 MOV BL, AL
829 XOR BH, BH
830 SHL BX, 1
831 MOV DX, EXCEPT_TEXTS[BX] ; Keep upper word of EDX
832 POP BX
833ENAME1: RET
834EXCEPT_NAME ENDP
835
836SV_CODE ENDS
837
838 END
Note: See TracBrowser for help on using the repository browser.