exceptn.as 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /* Copyright (C) 1994, 1995 Charles Sandmann ([email protected])
  2. * This file maybe freely distributed and modified as long as copyright remains.
  3. */
  4. EAX = 0
  5. EBX = 4
  6. ECX = 8
  7. EDX = 12
  8. ESI = 16
  9. EDI = 20
  10. EBP = 24
  11. ESP = 28
  12. EIP = 32
  13. EFLAGS = 36
  14. CS = 40
  15. DS = 42
  16. ES = 44
  17. FS = 46
  18. GS = 48
  19. SS = 50
  20. ERRCODE = 52
  21. EXCEPNO = 56
  22. PREVEXC = 60
  23. /* Length 64 bytes plus non-used FPU */
  24. .data
  25. .balign 8
  26. .comm exception_stack, 8000
  27. .text
  28. .balign 16,,7
  29. .macro EXCEPTION_ENTRY number
  30. pushl \number
  31. jmp exception_handler
  32. .endm
  33. .global ___djgpp_exception_table
  34. ___djgpp_exception_table:
  35. EXCEPTION_ENTRY $18
  36. EXCEPTION_ENTRY $19
  37. EXCEPTION_ENTRY $0
  38. EXCEPTION_ENTRY $1
  39. EXCEPTION_ENTRY $2
  40. EXCEPTION_ENTRY $3
  41. EXCEPTION_ENTRY $4
  42. EXCEPTION_ENTRY $5
  43. EXCEPTION_ENTRY $6
  44. EXCEPTION_ENTRY $7
  45. EXCEPTION_ENTRY $8
  46. EXCEPTION_ENTRY $9
  47. EXCEPTION_ENTRY $10
  48. EXCEPTION_ENTRY $11
  49. EXCEPTION_ENTRY $12
  50. EXCEPTION_ENTRY $13
  51. EXCEPTION_ENTRY $14
  52. EXCEPTION_ENTRY $15
  53. EXCEPTION_ENTRY $16
  54. EXCEPTION_ENTRY $17
  55. /* This code is called any time an exception occurs in the 32 bit protected
  56. ;* mode code. The exception number is pushed on the stack. This is called
  57. ;* on a locked stack with interrupts disabled. Don't try to terminate.
  58. ;*
  59. ;* [ * | SS ] * Don't modify
  60. ;* [ ESP ]
  61. ;* [ EFLAGS ]
  62. ;* [ * | CS ] * Don't modify
  63. ;* [ EIP ]
  64. ;* [ ERR CODE ]
  65. ;* [ * |RET CS*] * Don't modify
  66. ;* [ RET EIP* ] * Don't modify
  67. ;* [ EXCEPTION # ] (And later EBP)
  68. ;*/
  69. /* ;WARNING WARNING WARNING
  70. ;The mechanism for passing signals between the debugger
  71. ;and the debuggee relies on the *exact* instructions between
  72. ;EXCEPTION_ENTRY($13) above and "cmpb $0, forced" instruction
  73. ;below! These instructions are stored in forced_test[] buffer
  74. ;in src/debug/common/dbgcom.c. Do NOT change anything between
  75. ;these two instructions, or you will break signal support in
  76. ;the debuggers!! */
  77. exception_handler:
  78. pushl %ebx
  79. pushl %ds
  80. .byte 0x2e /* CS: */
  81. cmpb $0, forced
  82. je not_forced
  83. call limitFix
  84. .byte 0x2e /* CS: */
  85. movzbl forced,%ebx
  86. movl %ebx,8(%esp) /* replace EXCEPNO */
  87. cmpb $0x75, %bl
  88. jne not_forced
  89. movzwl ___djgpp_fpu_state,%ebx
  90. movl %ebx,20(%esp) /* set ERRCODE to FPU state */
  91. not_forced:
  92. movw %cs:___djgpp_our_DS, %ds
  93. movl $0x10000, forced /* its zero now, flag inuse */
  94. movl $exception_state, %ebx
  95. popl DS(%ebx)
  96. popl EBX(%ebx)
  97. popl EXCEPNO(%ebx)
  98. movl %esi, ESI(%ebx)
  99. movl %edi, EDI(%ebx)
  100. movl %ebp, EBP(%ebx)
  101. movl %eax, EAX(%ebx)
  102. movl %ecx, ECX(%ebx)
  103. movl %edx, EDX(%ebx)
  104. movw %es, ES(%ebx)
  105. movw %fs, FS(%ebx)
  106. movw %gs, GS(%ebx)
  107. movl ___djgpp_exception_state_ptr, %eax
  108. movl %eax, PREVEXC(%ebx)
  109. /* Stack clean at this point, DS:[EBX] points to exception_state, all
  110. register information saved. Now get the info on stack. */
  111. pushl %ebp
  112. movl %esp, %ebp /* load ebp with stack for easy access */
  113. movl 12(%ebp), %eax
  114. movl %eax, ERRCODE(%ebx)
  115. movl 16(%ebp), %eax
  116. movl %eax, EIP(%ebx)
  117. movl 20(%ebp), %eax
  118. movw %ax, CS(%ebx)
  119. movl 24(%ebp), %eax
  120. movl %eax, EFLAGS(%ebx)
  121. andb $0xfe, %ah /* Clear trace flag */
  122. movl %eax, 24(%ebp) /* and restore on stack */
  123. movl 28(%ebp), %eax
  124. movl %eax, ESP(%ebx)
  125. movl 32(%ebp), %eax
  126. movw %ax, SS(%ebx)
  127. movl $dpmi_exception_proc1, 16(%ebp) /* where to return */
  128. movw %cs, 20(%ebp)
  129. /* Change to our local stack on return from exception (maybe stack exception) */
  130. movw %ds, %ax
  131. cmpb $12,EXCEPNO(%ebx) /* Stack fault ? */
  132. je 1f
  133. cmpw %ax,32(%ebp)
  134. je stack_ok
  135. .byte 0x2e /* CS: */
  136. movw ___djgpp_ds_alias,%di
  137. cmpw %di,32(%ebp) /* if it's DS alias, switch to normal DS */
  138. jne 1f
  139. movw %ax,32(%ebp)
  140. jmp stack_ok
  141. 1: movl $exception_stack+8000, 28(%ebp)
  142. movw %ax, 32(%ebp)
  143. stack_ok:
  144. /* Now copy the exception structure to the new stack before returning */
  145. movw %ax, %es
  146. movl %ebx,%esi
  147. movl 28(%ebp), %edi
  148. subl $92, %edi /* 64 plus extra for longjmp */
  149. movl %edi, 28(%ebp)
  150. movl %edi, ___djgpp_exception_state_ptr
  151. movl $16, %ecx
  152. cld
  153. rep
  154. movsl
  155. movl EAX(%ebx), %eax /* restore regs */
  156. movl ESI(%ebx), %esi
  157. movl EDI(%ebx), %edi
  158. movl ECX(%ebx), %ecx
  159. movw ES(%ebx), %es
  160. popl %ebp
  161. pushl EBX(%ebx)
  162. pushl DS(%ebx)
  163. movb $0, forced+2 /* flag non-use */
  164. popl %ds
  165. popl %ebx
  166. lret
  167. /* Code to fix fake exception, EBX destroyed. Note, app_DS may == our_DS! */
  168. .balign 16,,7
  169. limitFix:
  170. pushl %eax
  171. pushl %ecx
  172. pushl %edx
  173. .byte 0x2e /* CS: */
  174. movl ___djgpp_app_DS, %ebx /* avoid size prefix */
  175. .byte 0x2e /* CS: */
  176. movl ds_limit, %edx
  177. movl %edx, %ecx
  178. shrl $16, %ecx
  179. movw $0x0008, %ax
  180. int $0x31 /* Set segment limit */
  181. popl %edx
  182. popl %ecx
  183. popl %eax
  184. ret
  185. /* This local routine preprocesses a return request to the C code. It checks
  186. to make sure the DS & SS are set OK for C code. If not, it sets them up */
  187. .balign 16,,7
  188. dpmi_exception_proc1:
  189. cld
  190. .byte 0x2e /* CS: !!! */
  191. movw ___djgpp_our_DS, %bx /* to be sure */
  192. movw %bx, %ds
  193. movw %bx, %es
  194. /* Note: SS:ESP should be set properly by exception routine */
  195. jmp ___djgpp_exception_processor
  196. /* This code is called by a user routine wishing to save an interrupt
  197. ;* state. It will return with a clean stack, our DS,ES,SS.
  198. ;* Minor bug: uses static exception_state for a short window without
  199. ;* interrupts guaranteed disabled.
  200. ;*
  201. ;* [ EFLAGS ]
  202. ;* [ * | CS ]
  203. ;* [ EIP ]
  204. ;* [ CALLING EIP ]
  205. ;*/
  206. .balign 16,,7
  207. .globl ___djgpp_save_interrupt_regs
  208. ___djgpp_save_interrupt_regs:
  209. pushl %esi
  210. pushl %ds
  211. movw %cs:___djgpp_our_DS, %ds
  212. movl $exception_state, %esi
  213. popl DS(%esi) /* Trashes ES but OK */
  214. popl ESI(%esi)
  215. movl %edi, EDI(%esi)
  216. movl %ebp, EBP(%esi)
  217. movl %eax, EAX(%esi)
  218. movl %ebx, EBX(%esi)
  219. movl %ecx, ECX(%esi)
  220. movl %edx, EDX(%esi)
  221. popl %edx /* Save calling EIP */
  222. popl EIP(%esi)
  223. popl %eax
  224. movw %ax,CS(%esi) /* Don't pop, nukes DS */
  225. popl EFLAGS(%esi)
  226. movl %esp, ESP(%esi)
  227. movw %es, ES(%esi)
  228. movw %fs, FS(%esi)
  229. movw %gs, GS(%esi)
  230. movw %ss, SS(%esi)
  231. movl ___djgpp_exception_state_ptr, %eax
  232. movl %eax, PREVEXC(%esi)
  233. cld
  234. movw %ds, %ax
  235. movw %ax, %es
  236. movw %ss, %bx
  237. cmpw %ax, %bx /* is SS = DS ? */
  238. je Lss_ok
  239. movw %ax, %ss /* set new SS:ESP */
  240. movl $exception_stack+8000, %esp
  241. Lss_ok: subl $92, %esp /* 64 plus extra for longjmp */
  242. movl %esp, %edi
  243. movl $16, %ecx
  244. movl %edi, ___djgpp_exception_state_ptr
  245. rep
  246. movsl /* Copy structure to stack */
  247. jmp *%edx /* A "return" */
  248. .balign 8 /* We will touch this; it must be locked */
  249. .global ___djgpp_hw_lock_start
  250. ___djgpp_hw_lock_start:
  251. /* src/debug/common/dbgcom.c knows that `ds_limit' is stored
  252. 4 bytes before `forced' and relies on that. Do NOT change that! */
  253. ds_limit: .long 0
  254. forced: .long 0
  255. .global ___djgpp_cbrk_count
  256. ___djgpp_cbrk_count: .long 0
  257. .global ___djgpp_timer_countdown
  258. ___djgpp_timer_countdown: .long 0
  259. .global ___djgpp_our_DS
  260. ___djgpp_our_DS: .word 0
  261. .global ___djgpp_app_DS
  262. ___djgpp_app_DS: .word 0
  263. .global ___djgpp_dos_sel
  264. ___djgpp_dos_sel: .word 0
  265. .global ___djgpp_hwint_flags
  266. ___djgpp_hwint_flags: .word 0
  267. .global ___djgpp_sigint_key
  268. ___djgpp_sigint_key: .word 0 /* scan code and kb status */
  269. .global ___djgpp_sigint_mask
  270. ___djgpp_sigint_mask: .word 0 /* kb status mask */
  271. .global ___djgpp_sigquit_key
  272. ___djgpp_sigquit_key: .word 0
  273. .global ___djgpp_sigquit_mask
  274. ___djgpp_sigquit_mask: .word 0
  275. .global ___djgpp_old_kbd
  276. ___djgpp_old_kbd: .long 0,0
  277. .global ___djgpp_old_timer
  278. ___djgpp_old_timer: .long 0,0
  279. .global ___djgpp_exception_state_ptr
  280. ___djgpp_exception_state_ptr: .long 0
  281. exception_state: .space 64
  282. .global ___djgpp_ds_alias
  283. ___djgpp_ds_alias: .word 0 /* used in dpmi/api/d0303.s (alloc rmcb) */
  284. .global ___djgpp_fpu_state
  285. ___djgpp_fpu_state: .word 0
  286. .balign 16,,7
  287. .global ___djgpp_npx_hdlr
  288. ___djgpp_npx_hdlr:
  289. fnstsw ___djgpp_fpu_state
  290. fnclex
  291. pushl %eax
  292. xorl %eax,%eax
  293. outb %al,$0x0f0
  294. movb $0x20,%al
  295. outb %al,$0x0a0
  296. outb %al,$0x020
  297. movb $0x75,%al
  298. hw_to_excp:
  299. call ___djgpp_hw_exception
  300. popl %eax
  301. sti
  302. iret
  303. .balign 16,,7
  304. .global ___djgpp_kbd_hdlr
  305. ___djgpp_kbd_hdlr:
  306. pushl %eax
  307. pushl %ebx
  308. pushl %ds
  309. .byte 0x2e /* CS: */
  310. testb $1, ___djgpp_hwint_flags /* Disable? */
  311. jne Lkbd_chain
  312. movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */
  313. /* movw $0x7021,0xb0f00 */ /* Test code - write to mono */
  314. /* Check Keyboard status bits */
  315. movb 0x417,%ah /* Get KB status byte */
  316. testb $1,%ah
  317. je 6f
  318. orb $2,%ah /* If RShift is set, set LShift as well */
  319. 6:
  320. inb $0x60,%al /* Read the scan code */
  321. 99:
  322. movb %ah,%bh /* Save KB status */
  323. andb %cs:___djgpp_sigint_mask, %ah /* Mask off irrelevant bits */
  324. cmpw %cs:___djgpp_sigint_key, %ax /* Test for SIGINT */
  325. jne 7f
  326. movb $0x79,%bh /* SIGINT */
  327. jmp 98f
  328. 7:
  329. movb %bh,%ah /* Restore KB status */
  330. andb %cs:___djgpp_sigquit_mask, %ah /* Mask off irrelevant bits */
  331. cmpw %cs:___djgpp_sigquit_key, %ax /* Test for SIGQUIT*/
  332. jne Lkbd_chain
  333. movb $0x7a,%bh /* SIGQUIT */
  334. /* Clear interrupt, (later: remove byte from controller?)
  335. movb $0x20,%al
  336. outb %al,$0x020 */
  337. 98:
  338. movb %bh,%al
  339. call ___djgpp_hw_exception
  340. Lkbd_chain:
  341. popl %ds
  342. popl %ebx
  343. popl %eax
  344. ljmp %cs:___djgpp_old_kbd
  345. .balign 16,,7
  346. .global ___djgpp_kbd_hdlr_pc98
  347. ___djgpp_kbd_hdlr_pc98:
  348. pushl %eax
  349. pushl %ebx
  350. pushl %ds
  351. .byte 0x2e /* CS: */
  352. testb $1, ___djgpp_hwint_flags /* Disable? */
  353. jne Lkbd_chain
  354. /* Check CTRL state */
  355. movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */
  356. movb 0x053a,%al /* Get KB status byte */
  357. /* Convert PC98 style status byte to PC/AT style */
  358. movb %al,%ah
  359. andb $0x09,%ah /* GRPH(=ALT), SHIFT(=R-Shift) */
  360. testb $0x02,%al
  361. je 981f
  362. orb $0x40,%ah /* CAPS(=Caps Lock) */
  363. 981: testb $0x10,%al
  364. je 982f
  365. orb $0x04,%ah /* CTRL(=Ctrl) */
  366. 982: testb $0x01,%al
  367. je 983f
  368. orb $0x02,%ah /* SHIFT(=L-Shift) */
  369. 983: testb $0x04,%al
  370. je 984f
  371. orb $0x20,%ah /* KANA(=NUM Lock) */
  372. 984: inb $0x41,%al /* Read the scan code */
  373. jmp 99b
  374. .balign 16,,7
  375. .global ___djgpp_timer_hdlr
  376. ___djgpp_timer_hdlr:
  377. .byte 0x2e /* CS: */
  378. cmpl $0,___djgpp_timer_countdown
  379. je 4f
  380. pushl %ds
  381. movw %cs:___djgpp_ds_alias, %ds
  382. decl ___djgpp_timer_countdown
  383. popl %ds
  384. jmp 3f
  385. 4:
  386. pushl %eax
  387. movb $0x78,%al
  388. call ___djgpp_hw_exception
  389. popl %eax
  390. 3:
  391. .byte 0x2e /* CS: */
  392. testb $4, ___djgpp_hwint_flags /* IRET or chain? */
  393. jne 2f
  394. ljmp %cs:___djgpp_old_timer
  395. 2:
  396. pushl %eax
  397. movb $0x20,%al /* EOI the interrupt */
  398. outb %al,$0x020
  399. popl %eax
  400. iret
  401. /* On entry ES is the DS alias selector */
  402. .balign 16,,7
  403. .global ___djgpp_cbrk_hdlr /* A RMCB handler for 0x1b */
  404. ___djgpp_cbrk_hdlr:
  405. cld
  406. lodsl /* EAX = DS:[esi] CS:IP */
  407. movl %eax, %es:0x2a(%edi) /* store in structure */
  408. lodsl /* AX = FLAGS */
  409. movw %ax, %es:0x20(%edi)
  410. addw $6, %es:0x2e(%edi) /* Adjust RM SP */
  411. movb $0x1b,%al
  412. .byte 0x2e /* CS: */
  413. testb $2, ___djgpp_hwint_flags /* Count, don't kill */
  414. jne 1f
  415. call ___djgpp_hw_exception
  416. iret
  417. 1:
  418. incl %es:___djgpp_cbrk_count
  419. iret
  420. .global ___djgpp_i24 /* Int 24 handler if needed */
  421. .global ___djgpp_iret /* Int 23 handler if needed */
  422. ___djgpp_i24:
  423. movb $3,%al
  424. ___djgpp_iret:
  425. iret
  426. /* Code to stop execution ASAP, EAX destroyed. Make DS/ES/SS invalid.
  427. Fake exception value is passed in AL and moved into the "forced" variable.
  428. This is used to convert a HW interrupt into something we can transfer
  429. control away from via longjmp or exit(), common with SIGINT, SIGFPE, or
  430. if we want EIP information on timers. */
  431. .balign 16,,7
  432. .global ___djgpp_hw_exception
  433. ___djgpp_hw_exception:
  434. .byte 0x2e /* CS: */
  435. cmpl $0, forced /* Already flagged? */
  436. jne already_forced
  437. pushl %ebx
  438. pushl %ecx
  439. pushl %edx
  440. pushl %ds
  441. movw %cs:___djgpp_our_DS, %ds
  442. movl ___djgpp_app_DS, %ebx /* avoid size prefix */
  443. lsl %ebx, %ecx
  444. movl %ecx, ds_limit /* Save current limit */
  445. movb %al, forced /* Indicate a fake exception */
  446. xorl %ecx, %ecx
  447. movw $0xfff, %dx /* 4K limit is null page ! */
  448. movw $0x0008, %ax
  449. int $0x31 /* Set segment limit */
  450. 5: popl %ds
  451. popl %edx
  452. popl %ecx
  453. popl %ebx
  454. already_forced:
  455. ret
  456. .global ___djgpp_hw_lock_end
  457. ___djgpp_hw_lock_end:
  458. ret /* LD does weird things */