~ubuntu-branches/ubuntu/dapper/fpc/dapper

« back to all changes in this revision

Viewing changes to rtl/go32v2/exceptn.as

  • Committer: Bazaar Package Importer
  • Author(s): Carlos Laviola
  • Date: 2001-08-29 23:15:17 UTC
  • Revision ID: james.westby@ubuntu.com-20010829231517-thxsp7ctuab584ia
Tags: upstream-1.0.4
ImportĀ upstreamĀ versionĀ 1.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1994, 1995 Charles Sandmann (sandmann@clio.rice.edu)
 
2
 * This file maybe freely distributed and modified as long as copyright remains.
 
3
 */
 
4
 
 
5
  EAX = 0
 
6
  EBX = 4
 
7
  ECX = 8
 
8
  EDX = 12
 
9
  ESI = 16
 
10
  EDI = 20
 
11
  EBP = 24
 
12
  ESP = 28
 
13
  EIP = 32
 
14
  EFLAGS = 36
 
15
  CS = 40
 
16
  DS = 42
 
17
  ES = 44
 
18
  FS = 46
 
19
  GS = 48
 
20
  SS = 50
 
21
  ERRCODE = 52
 
22
  EXCEPNO = 56
 
23
  PREVEXC = 60
 
24
/* Length 64 bytes plus non-used FPU */
 
25
        .data
 
26
        .balign 8
 
27
        .comm   exception_stack, 8000
 
28
 
 
29
        .text
 
30
        .balign 16,,7
 
31
   .macro EXCEPTION_ENTRY number
 
32
        pushl   \number
 
33
        jmp     exception_handler
 
34
   .endm
 
35
 
 
36
        .global ___djgpp_exception_table
 
37
___djgpp_exception_table:
 
38
EXCEPTION_ENTRY $18
 
39
EXCEPTION_ENTRY $19
 
40
EXCEPTION_ENTRY $0
 
41
EXCEPTION_ENTRY $1
 
42
EXCEPTION_ENTRY $2
 
43
EXCEPTION_ENTRY $3
 
44
EXCEPTION_ENTRY $4
 
45
EXCEPTION_ENTRY $5
 
46
EXCEPTION_ENTRY $6
 
47
EXCEPTION_ENTRY $7
 
48
EXCEPTION_ENTRY $8
 
49
EXCEPTION_ENTRY $9
 
50
EXCEPTION_ENTRY $10
 
51
EXCEPTION_ENTRY $11
 
52
EXCEPTION_ENTRY $12
 
53
EXCEPTION_ENTRY $13
 
54
EXCEPTION_ENTRY $14
 
55
EXCEPTION_ENTRY $15
 
56
EXCEPTION_ENTRY $16
 
57
EXCEPTION_ENTRY $17
 
58
 
 
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.
 
62
;*
 
63
;*      [   *   |   SS  ]       * Don't modify
 
64
;*      [      ESP      ]
 
65
;*      [    EFLAGS     ]
 
66
;*      [   *   |   CS  ]       * Don't modify
 
67
;*      [      EIP      ]
 
68
;*      [   ERR CODE    ]
 
69
;*      [   *   |RET CS*]       * Don't modify
 
70
;*      [   RET EIP*    ]       * Don't modify
 
71
;*      [  EXCEPTION #  ]       (And later EBP)
 
72
;*/
 
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
 
80
   ;the debuggers!!  */
 
81
exception_handler:
 
82
        pushl   %ebx
 
83
        pushl   %ds
 
84
        .byte   0x2e                            /* CS: */
 
85
        cmpb    $0, forced
 
86
        je      not_forced
 
87
        call    limitFix
 
88
        .byte   0x2e                            /* CS: */
 
89
        movzbl  forced,%ebx
 
90
        movl    %ebx,8(%esp)                    /* replace EXCEPNO */
 
91
        cmpb    $0x75, %bl
 
92
        jne     not_forced
 
93
        movzwl    ___djgpp_fpu_state,%ebx
 
94
        movl    %ebx,20(%esp)                   /* set ERRCODE to FPU state */
 
95
not_forced:
 
96
        movw    %cs:___djgpp_our_DS, %ds
 
97
        movl    $0x10000, forced                /* its zero now, flag inuse */
 
98
        movl    $exception_state, %ebx
 
99
        popl    DS(%ebx)
 
100
        popl    EBX(%ebx)
 
101
        popl    EXCEPNO(%ebx)
 
102
        movl    %esi, ESI(%ebx)
 
103
        movl    %edi, EDI(%ebx)
 
104
        movl    %ebp, EBP(%ebx)
 
105
        movl    %eax, EAX(%ebx)
 
106
        movl    %ecx, ECX(%ebx)
 
107
        movl    %edx, EDX(%ebx)
 
108
        movw    %es, ES(%ebx)
 
109
        movw    %fs, FS(%ebx)
 
110
        movw    %gs, GS(%ebx)
 
111
        movl    ___djgpp_exception_state_ptr, %eax
 
112
        movl    %eax, PREVEXC(%ebx)
 
113
 
 
114
/* Stack clean at this point, DS:[EBX] points to exception_state, all
 
115
   register information saved.  Now get the info on stack. */
 
116
 
 
117
        pushl   %ebp
 
118
        movl    %esp, %ebp      /* load ebp with stack for easy access */
 
119
        
 
120
        movl    12(%ebp), %eax
 
121
        movl    %eax, ERRCODE(%ebx)
 
122
        movl    16(%ebp), %eax
 
123
        movl    %eax, EIP(%ebx)
 
124
        movl    20(%ebp), %eax
 
125
        movw    %ax, CS(%ebx)
 
126
        movl    24(%ebp), %eax
 
127
        movl    %eax, EFLAGS(%ebx)
 
128
        andb    $0xfe, %ah                      /* Clear trace flag */
 
129
        movl    %eax, 24(%ebp)                  /* and restore on stack */
 
130
 
 
131
        movl    28(%ebp), %eax
 
132
        movl    %eax, ESP(%ebx)
 
133
        movl    32(%ebp), %eax
 
134
        movw    %ax, SS(%ebx)
 
135
 
 
136
        movl    $dpmi_exception_proc1, 16(%ebp)         /* where to return */
 
137
        movw    %cs, 20(%ebp)
 
138
 
 
139
/* Change to our local stack on return from exception (maybe stack exception) */
 
140
        movw    %ds, %ax
 
141
        cmpb    $12,EXCEPNO(%ebx)               /* Stack fault ? */
 
142
        je      1f
 
143
        cmpw    %ax,32(%ebp)
 
144
        je      stack_ok
 
145
        .byte   0x2e                            /* CS: */
 
146
        movw    ___djgpp_ds_alias,%di
 
147
        cmpw    %di,32(%ebp)    /* if it's DS alias, switch to normal DS */
 
148
        jne     1f
 
149
        movw    %ax,32(%ebp)
 
150
        jmp     stack_ok
 
151
1:      movl    $exception_stack+8000, 28(%ebp)
 
152
        movw    %ax, 32(%ebp)
 
153
stack_ok:
 
154
/* Now copy the exception structure to the new stack before returning */
 
155
        movw    %ax, %es
 
156
        movl    %ebx,%esi
 
157
        movl    28(%ebp), %edi
 
158
        subl    $92, %edi                       /* 64 plus extra for longjmp */
 
159
        movl    %edi, 28(%ebp)
 
160
        movl    %edi, ___djgpp_exception_state_ptr
 
161
        movl    $16, %ecx
 
162
        cld
 
163
        rep
 
164
        movsl
 
165
 
 
166
        movl    EAX(%ebx), %eax                         /* restore regs */
 
167
        movl    ESI(%ebx), %esi
 
168
        movl    EDI(%ebx), %edi
 
169
        movl    ECX(%ebx), %ecx
 
170
        movw    ES(%ebx), %es
 
171
        popl    %ebp
 
172
        pushl   EBX(%ebx)
 
173
        pushl   DS(%ebx)
 
174
        movb    $0, forced+2                            /* flag non-use */
 
175
        popl    %ds
 
176
        popl    %ebx
 
177
        lret
 
178
 
 
179
/* Code to fix fake exception, EBX destroyed.  Note, app_DS may == our_DS! */
 
180
        .balign 16,,7
 
181
limitFix:
 
182
        pushl   %eax
 
183
        pushl   %ecx
 
184
        pushl   %edx
 
185
        .byte   0x2e                            /* CS: */
 
186
        movl    ___djgpp_app_DS, %ebx           /* avoid size prefix */
 
187
        .byte   0x2e                            /* CS: */
 
188
        movl    ds_limit, %edx
 
189
        movl    %edx, %ecx
 
190
        shrl    $16, %ecx
 
191
        movw    $0x0008, %ax
 
192
        int     $0x31                           /* Set segment limit */
 
193
        popl    %edx
 
194
        popl    %ecx
 
195
        popl    %eax
 
196
        ret
 
197
 
 
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 */
 
200
        .balign 16,,7
 
201
dpmi_exception_proc1:
 
202
        cld
 
203
        .byte   0x2e                            /* CS: !!! */
 
204
        movw    ___djgpp_our_DS, %bx            /* to be sure */
 
205
        movw    %bx, %ds
 
206
        movw    %bx, %es
 
207
        /* Note: SS:ESP should be set properly by exception routine */
 
208
        jmp     ___djgpp_exception_processor
 
209
 
 
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.
 
214
;*
 
215
;*      [    EFLAGS     ]
 
216
;*      [   *   |   CS  ]
 
217
;*      [      EIP      ]
 
218
;*      [  CALLING EIP  ]
 
219
;*/
 
220
 
 
221
        .balign 16,,7
 
222
        .globl  ___djgpp_save_interrupt_regs
 
223
___djgpp_save_interrupt_regs:
 
224
        pushl   %esi
 
225
        pushl   %ds
 
226
        movw    %cs:___djgpp_our_DS, %ds
 
227
        movl    $exception_state, %esi
 
228
        popl    DS(%esi)                /* Trashes ES but OK */
 
229
        popl    ESI(%esi)
 
230
        movl    %edi, EDI(%esi)
 
231
        movl    %ebp, EBP(%esi)
 
232
        movl    %eax, EAX(%esi)
 
233
        movl    %ebx, EBX(%esi)
 
234
        movl    %ecx, ECX(%esi)
 
235
        movl    %edx, EDX(%esi)
 
236
        popl    %edx                    /* Save calling EIP */
 
237
        popl    EIP(%esi)
 
238
        popl    %eax
 
239
        movw    %ax,CS(%esi)            /* Don't pop, nukes DS */
 
240
        popl    EFLAGS(%esi)
 
241
        movl    %esp, ESP(%esi)
 
242
        movw    %es, ES(%esi)
 
243
        movw    %fs, FS(%esi)
 
244
        movw    %gs, GS(%esi)
 
245
        movw    %ss, SS(%esi)
 
246
        movl    ___djgpp_exception_state_ptr, %eax
 
247
        movl    %eax, PREVEXC(%esi)
 
248
        cld
 
249
        movw    %ds, %ax
 
250
        movw    %ax, %es
 
251
        movw    %ss, %bx
 
252
        cmpw    %ax, %bx                        /* is SS = DS ? */
 
253
        je      Lss_ok
 
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 */
 
257
        movl    %esp, %edi
 
258
        movl    $16, %ecx
 
259
        movl    %edi, ___djgpp_exception_state_ptr
 
260
        rep
 
261
        movsl                                   /* Copy structure to stack */
 
262
        jmp     *%edx                           /* A "return" */
 
263
 
 
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! */
 
269
ds_limit:                       .long   0
 
270
forced:                         .long   0
 
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) */
 
300
 
 
301
        .global ___djgpp_fpu_state
 
302
___djgpp_fpu_state:             .word   0
 
303
        .balign 16,,7
 
304
        .global ___djgpp_npx_hdlr
 
305
___djgpp_npx_hdlr:
 
306
        fnstsw  ___djgpp_fpu_state
 
307
        fnclex
 
308
        pushl   %eax
 
309
        xorl    %eax,%eax
 
310
        outb    %al,$0x0f0
 
311
        movb    $0x20,%al
 
312
        outb    %al,$0x0a0
 
313
        outb    %al,$0x020
 
314
        movb    $0x75,%al
 
315
hw_to_excp:
 
316
        call    ___djgpp_hw_exception
 
317
        popl    %eax
 
318
        sti
 
319
        iret
 
320
 
 
321
        .balign 16,,7
 
322
        .global ___djgpp_kbd_hdlr
 
323
___djgpp_kbd_hdlr:
 
324
        pushl   %eax
 
325
        pushl   %ebx
 
326
        pushl   %ds
 
327
        .byte   0x2e                            /* CS: */
 
328
        testb   $1, ___djgpp_hwint_flags        /* Disable? */
 
329
        jne     Lkbd_chain
 
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 */
 
334
        testb   $1,%ah
 
335
        je      6f
 
336
        orb     $2,%ah  /* If RShift is set, set LShift as well */
 
337
6:
 
338
        inb     $0x60,%al                       /* Read the scan code */
 
339
99:
 
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 */
 
343
        jne     7f
 
344
        movb    $0x79,%bh                       /* SIGINT */
 
345
        jmp     98f
 
346
7:
 
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*/
 
350
        jne     Lkbd_chain
 
351
        movb    $0x7a,%bh                       /* SIGQUIT */
 
352
/* Clear interrupt, (later: remove byte from controller?)
 
353
        movb    $0x20,%al
 
354
        outb    %al,$0x020      */
 
355
98:
 
356
        movb    %bh,%al
 
357
        call    ___djgpp_hw_exception
 
358
Lkbd_chain:
 
359
        popl    %ds
 
360
        popl    %ebx
 
361
        popl    %eax
 
362
        ljmp    %cs:___djgpp_old_kbd
 
363
 
 
364
        .balign 16,,7
 
365
        .global ___djgpp_kbd_hdlr_pc98
 
366
___djgpp_kbd_hdlr_pc98:
 
367
        pushl   %eax
 
368
        pushl   %ebx
 
369
        pushl   %ds
 
370
        .byte   0x2e                            /* CS: */
 
371
        testb   $1, ___djgpp_hwint_flags        /* Disable? */
 
372
        jne     Lkbd_chain
 
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 */
 
377
        movb    %al,%ah
 
378
        andb    $0x09,%ah       /* GRPH(=ALT), SHIFT(=R-Shift) */
 
379
        testb   $0x02,%al
 
380
        je      981f
 
381
        orb     $0x40,%ah       /* CAPS(=Caps Lock) */
 
382
981:    testb   $0x10,%al
 
383
        je      982f
 
384
        orb     $0x04,%ah       /* CTRL(=Ctrl) */
 
385
982:    testb   $0x01,%al
 
386
        je      983f
 
387
        orb     $0x02,%ah       /* SHIFT(=L-Shift) */
 
388
983:    testb   $0x04,%al
 
389
        je      984f
 
390
        orb     $0x20,%ah       /* KANA(=NUM Lock) */
 
391
984:    inb     $0x41,%al                       /* Read the scan code */
 
392
        jmp     99b
 
393
 
 
394
        .balign 16,,7
 
395
        .global ___djgpp_timer_hdlr
 
396
___djgpp_timer_hdlr:
 
397
        .byte   0x2e                            /* CS: */
 
398
        cmpl    $0,___djgpp_timer_countdown
 
399
        je      4f
 
400
        pushl   %ds
 
401
        movw    %cs:___djgpp_ds_alias, %ds
 
402
        decl    ___djgpp_timer_countdown
 
403
        popl    %ds
 
404
        jmp     3f
 
405
4:
 
406
        pushl   %eax
 
407
        movb    $0x78,%al
 
408
        call    ___djgpp_hw_exception
 
409
        popl    %eax
 
410
3:
 
411
        .byte   0x2e                            /* CS: */
 
412
        testb   $4, ___djgpp_hwint_flags        /* IRET or chain? */
 
413
        jne     2f
 
414
        ljmp    %cs:___djgpp_old_timer
 
415
2:
 
416
        pushl   %eax
 
417
        movb    $0x20,%al                       /* EOI the interrupt */
 
418
        outb    %al,$0x020
 
419
        popl    %eax
 
420
        iret
 
421
 
 
422
        /* On entry ES is the DS alias selector */
 
423
        .balign 16,,7
 
424
        .global ___djgpp_cbrk_hdlr              /* A RMCB handler for 0x1b */
 
425
___djgpp_cbrk_hdlr:
 
426
        cld
 
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 */
 
432
        movb    $0x1b,%al
 
433
 
 
434
        .byte   0x2e                            /* CS: */
 
435
        testb   $2, ___djgpp_hwint_flags        /* Count, don't kill */
 
436
        jne     1f
 
437
 
 
438
        call    ___djgpp_hw_exception
 
439
        iret
 
440
1:
 
441
        incl    %es:___djgpp_cbrk_count
 
442
        iret
 
443
 
 
444
        .global ___djgpp_i24                    /* Int 24 handler if needed */
 
445
        .global ___djgpp_iret                   /* Int 23 handler if needed */
 
446
___djgpp_i24:
 
447
        movb    $3,%al
 
448
___djgpp_iret:
 
449
        iret
 
450
 
 
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. */
 
456
 
 
457
        .balign 16,,7
 
458
        .global ___djgpp_hw_exception
 
459
___djgpp_hw_exception:
 
460
        .byte   0x2e                            /* CS: */
 
461
        cmpl    $0, forced                      /* Already flagged? */
 
462
        jne     already_forced
 
463
        pushl   %ebx
 
464
        pushl   %ecx
 
465
        pushl   %edx
 
466
        pushl   %ds
 
467
        movw    %cs:___djgpp_our_DS, %ds
 
468
        movl    ___djgpp_app_DS, %ebx           /* avoid size prefix */
 
469
        lsl     %ebx, %ecx
 
470
        movl    %ecx, ds_limit                  /* Save current limit */
 
471
        movb    %al, forced                     /* Indicate a fake exception */
 
472
        xorl    %ecx, %ecx
 
473
        movw    $0xfff, %dx                     /* 4K limit is null page ! */
 
474
        movw    $0x0008, %ax
 
475
        int     $0x31                           /* Set segment limit */
 
476
5:      popl    %ds
 
477
        popl    %edx
 
478
        popl    %ecx
 
479
        popl    %ebx
 
480
already_forced:
 
481
        ret
 
482
 
 
483
        .global ___djgpp_hw_lock_end
 
484
___djgpp_hw_lock_end:
 
485
        ret                                     /* LD does weird things */