1
/* Copyright (C) 1994, 1995 Charles Sandmann (sandmann@clio.rice.edu)
2
* This file maybe freely distributed and modified as long as copyright remains.
24
/* Length 64 bytes plus non-used FPU */
27
.comm exception_stack, 8000
31
.macro EXCEPTION_ENTRY number
36
.global ___djgpp_exception_table
37
___djgpp_exception_table:
59
/* This code is called any time an exception occurs in the 32 bit protected
60
;* mode code. The exception number is pushed on the stack. This is called
61
;* on a locked stack with interrupts disabled. Don't try to terminate.
63
;* [ * | SS ] * Don't modify
66
;* [ * | CS ] * Don't modify
69
;* [ * |RET CS*] * Don't modify
70
;* [ RET EIP* ] * Don't modify
71
;* [ EXCEPTION # ] (And later EBP)
73
/* ;WARNING WARNING WARNING
74
;The mechanism for passing signals between the debugger
75
;and the debuggee relies on the *exact* instructions between
76
;EXCEPTION_ENTRY($13) above and "cmpb $0, forced" instruction
77
;below! These instructions are stored in forced_test[] buffer
78
;in src/debug/common/dbgcom.c. Do NOT change anything between
79
;these two instructions, or you will break signal support in
90
movl %ebx,8(%esp) /* replace EXCEPNO */
93
movzwl ___djgpp_fpu_state,%ebx
94
movl %ebx,20(%esp) /* set ERRCODE to FPU state */
96
movw %cs:___djgpp_our_DS, %ds
97
movl $0x10000, forced /* its zero now, flag inuse */
98
movl $exception_state, %ebx
111
movl ___djgpp_exception_state_ptr, %eax
112
movl %eax, PREVEXC(%ebx)
114
/* Stack clean at this point, DS:[EBX] points to exception_state, all
115
register information saved. Now get the info on stack. */
118
movl %esp, %ebp /* load ebp with stack for easy access */
121
movl %eax, ERRCODE(%ebx)
127
movl %eax, EFLAGS(%ebx)
128
andb $0xfe, %ah /* Clear trace flag */
129
movl %eax, 24(%ebp) /* and restore on stack */
136
movl $dpmi_exception_proc1, 16(%ebp) /* where to return */
139
/* Change to our local stack on return from exception (maybe stack exception) */
141
cmpb $12,EXCEPNO(%ebx) /* Stack fault ? */
146
movw ___djgpp_ds_alias,%di
147
cmpw %di,32(%ebp) /* if it's DS alias, switch to normal DS */
151
1: movl $exception_stack+8000, 28(%ebp)
154
/* Now copy the exception structure to the new stack before returning */
158
subl $92, %edi /* 64 plus extra for longjmp */
160
movl %edi, ___djgpp_exception_state_ptr
166
movl EAX(%ebx), %eax /* restore regs */
174
movb $0, forced+2 /* flag non-use */
179
/* Code to fix fake exception, EBX destroyed. Note, app_DS may == our_DS! */
186
movl ___djgpp_app_DS, %ebx /* avoid size prefix */
192
int $0x31 /* Set segment limit */
198
/* This local routine preprocesses a return request to the C code. It checks
199
to make sure the DS & SS are set OK for C code. If not, it sets them up */
201
dpmi_exception_proc1:
203
.byte 0x2e /* CS: !!! */
204
movw ___djgpp_our_DS, %bx /* to be sure */
207
/* Note: SS:ESP should be set properly by exception routine */
208
jmp ___djgpp_exception_processor
210
/* This code is called by a user routine wishing to save an interrupt
211
;* state. It will return with a clean stack, our DS,ES,SS.
212
;* Minor bug: uses static exception_state for a short window without
213
;* interrupts guaranteed disabled.
222
.globl ___djgpp_save_interrupt_regs
223
___djgpp_save_interrupt_regs:
226
movw %cs:___djgpp_our_DS, %ds
227
movl $exception_state, %esi
228
popl DS(%esi) /* Trashes ES but OK */
236
popl %edx /* Save calling EIP */
239
movw %ax,CS(%esi) /* Don't pop, nukes DS */
246
movl ___djgpp_exception_state_ptr, %eax
247
movl %eax, PREVEXC(%esi)
252
cmpw %ax, %bx /* is SS = DS ? */
254
movw %ax, %ss /* set new SS:ESP */
255
movl $exception_stack+8000, %esp
256
Lss_ok: subl $92, %esp /* 64 plus extra for longjmp */
259
movl %edi, ___djgpp_exception_state_ptr
261
movsl /* Copy structure to stack */
262
jmp *%edx /* A "return" */
264
.balign 8 /* We will touch this; it must be locked */
265
.global ___djgpp_hw_lock_start
266
___djgpp_hw_lock_start:
267
/* src/debug/common/dbgcom.c knows that `ds_limit' is stored
268
4 bytes before `forced' and relies on that. Do NOT change that! */
271
.global ___djgpp_cbrk_count
272
___djgpp_cbrk_count: .long 0
273
.global ___djgpp_timer_countdown
274
___djgpp_timer_countdown: .long 0
275
.global ___djgpp_our_DS
276
___djgpp_our_DS: .word 0
277
.global ___djgpp_app_DS
278
___djgpp_app_DS: .word 0
279
.global ___djgpp_dos_sel
280
___djgpp_dos_sel: .word 0
281
.global ___djgpp_hwint_flags
282
___djgpp_hwint_flags: .word 0
283
.global ___djgpp_sigint_key
284
___djgpp_sigint_key: .word 0 /* scan code and kb status */
285
.global ___djgpp_sigint_mask
286
___djgpp_sigint_mask: .word 0 /* kb status mask */
287
.global ___djgpp_sigquit_key
288
___djgpp_sigquit_key: .word 0
289
.global ___djgpp_sigquit_mask
290
___djgpp_sigquit_mask: .word 0
291
.global ___djgpp_old_kbd
292
___djgpp_old_kbd: .long 0,0
293
.global ___djgpp_old_timer
294
___djgpp_old_timer: .long 0,0
295
.global ___djgpp_exception_state_ptr
296
___djgpp_exception_state_ptr: .long 0
297
exception_state: .space 64
298
.global ___djgpp_ds_alias
299
___djgpp_ds_alias: .word 0 /* used in dpmi/api/d0303.s (alloc rmcb) */
301
.global ___djgpp_fpu_state
302
___djgpp_fpu_state: .word 0
304
.global ___djgpp_npx_hdlr
306
fnstsw ___djgpp_fpu_state
316
call ___djgpp_hw_exception
322
.global ___djgpp_kbd_hdlr
328
testb $1, ___djgpp_hwint_flags /* Disable? */
330
movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */
331
/* movw $0x7021,0xb0f00 */ /* Test code - write to mono */
332
/* Check Keyboard status bits */
333
movb 0x417,%ah /* Get KB status byte */
336
orb $2,%ah /* If RShift is set, set LShift as well */
338
inb $0x60,%al /* Read the scan code */
340
movb %ah,%bh /* Save KB status */
341
andb %cs:___djgpp_sigint_mask, %ah /* Mask off irrelevant bits */
342
cmpw %cs:___djgpp_sigint_key, %ax /* Test for SIGINT */
344
movb $0x79,%bh /* SIGINT */
347
movb %bh,%ah /* Restore KB status */
348
andb %cs:___djgpp_sigquit_mask, %ah /* Mask off irrelevant bits */
349
cmpw %cs:___djgpp_sigquit_key, %ax /* Test for SIGQUIT*/
351
movb $0x7a,%bh /* SIGQUIT */
352
/* Clear interrupt, (later: remove byte from controller?)
357
call ___djgpp_hw_exception
362
ljmp %cs:___djgpp_old_kbd
365
.global ___djgpp_kbd_hdlr_pc98
366
___djgpp_kbd_hdlr_pc98:
371
testb $1, ___djgpp_hwint_flags /* Disable? */
373
/* Check CTRL state */
374
movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */
375
movb 0x053a,%al /* Get KB status byte */
376
/* Convert PC98 style status byte to PC/AT style */
378
andb $0x09,%ah /* GRPH(=ALT), SHIFT(=R-Shift) */
381
orb $0x40,%ah /* CAPS(=Caps Lock) */
384
orb $0x04,%ah /* CTRL(=Ctrl) */
387
orb $0x02,%ah /* SHIFT(=L-Shift) */
390
orb $0x20,%ah /* KANA(=NUM Lock) */
391
984: inb $0x41,%al /* Read the scan code */
395
.global ___djgpp_timer_hdlr
398
cmpl $0,___djgpp_timer_countdown
401
movw %cs:___djgpp_ds_alias, %ds
402
decl ___djgpp_timer_countdown
408
call ___djgpp_hw_exception
412
testb $4, ___djgpp_hwint_flags /* IRET or chain? */
414
ljmp %cs:___djgpp_old_timer
417
movb $0x20,%al /* EOI the interrupt */
422
/* On entry ES is the DS alias selector */
424
.global ___djgpp_cbrk_hdlr /* A RMCB handler for 0x1b */
427
lodsl /* EAX = DS:[esi] CS:IP */
428
movl %eax, %es:0x2a(%edi) /* store in structure */
429
lodsl /* AX = FLAGS */
430
movw %ax, %es:0x20(%edi)
431
addw $6, %es:0x2e(%edi) /* Adjust RM SP */
435
testb $2, ___djgpp_hwint_flags /* Count, don't kill */
438
call ___djgpp_hw_exception
441
incl %es:___djgpp_cbrk_count
444
.global ___djgpp_i24 /* Int 24 handler if needed */
445
.global ___djgpp_iret /* Int 23 handler if needed */
451
/* Code to stop execution ASAP, EAX destroyed. Make DS/ES/SS invalid.
452
Fake exception value is passed in AL and moved into the "forced" variable.
453
This is used to convert a HW interrupt into something we can transfer
454
control away from via longjmp or exit(), common with SIGINT, SIGFPE, or
455
if we want EIP information on timers. */
458
.global ___djgpp_hw_exception
459
___djgpp_hw_exception:
461
cmpl $0, forced /* Already flagged? */
467
movw %cs:___djgpp_our_DS, %ds
468
movl ___djgpp_app_DS, %ebx /* avoid size prefix */
470
movl %ecx, ds_limit /* Save current limit */
471
movb %al, forced /* Indicate a fake exception */
473
movw $0xfff, %dx /* 4K limit is null page ! */
475
int $0x31 /* Set segment limit */
483
.global ___djgpp_hw_lock_end
484
___djgpp_hw_lock_end:
485
ret /* LD does weird things */