exceptn.as 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /* Copyright (C) 1994, 1995 Charles Sandmann ([email protected])
  2. * This file maybe freely distributed and modified as long as copyright remains.
  3. */
  4. /* Simply rewritten to be compiled directly by GNU as by Pierre Muller
  5. for use in FPC the free pascal compiler */
  6. EAX = 0
  7. EBX = 4
  8. ECX = 8
  9. EDX = 12
  10. ESI = 16
  11. EDI = 20
  12. EBP = 24
  13. ESP = 28
  14. EIP = 32
  15. EFLAGS = 36
  16. CS = 40
  17. DS = 42
  18. ES = 44
  19. FS = 46
  20. GS = 48
  21. SS = 50
  22. ERRCODE = 52
  23. EXCEPNO = 56
  24. PREVEXC = 60
  25. /* Length 64 bytes plus non-used FPU */
  26. .data
  27. .align 4
  28. .lcomm exception_stack, 8000
  29. .text
  30. .align 4
  31. .macro EXCEPTION_ENTRY number
  32. pushl \number
  33. jmp exception_handler
  34. .endm
  35. .global ___djgpp_exception_table
  36. ___djgpp_exception_table:
  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. exception_handler:
  70. pushl %ebx
  71. pushl %ds
  72. .byte 0x2e /* CS: */
  73. cmpb $0, forced
  74. je not_forced
  75. call limitFix
  76. .byte 0x2e /* CS: */
  77. movzbl forced,%ebx
  78. movl %ebx,8(%esp) /* replace EXCEPNO */
  79. not_forced:
  80. movw %cs:___djgpp_our_DS, %ds
  81. movl $0x10000, forced /* its zero now, flag inuse */
  82. movl $exception_state, %ebx
  83. popl DS(%ebx)
  84. popl EBX(%ebx)
  85. popl EXCEPNO(%ebx)
  86. movl %esi, ESI(%ebx)
  87. movl %edi, EDI(%ebx)
  88. movl %ebp, EBP(%ebx)
  89. movl %eax, EAX(%ebx)
  90. movl %ecx, ECX(%ebx)
  91. movl %edx, EDX(%ebx)
  92. movw %es, ES(%ebx)
  93. movw %fs, FS(%ebx)
  94. movw %gs, GS(%ebx)
  95. movl ___djgpp_exception_state_ptr, %eax
  96. movl %eax, PREVEXC(%ebx)
  97. /* Stack clean at this point, DS:[EBX] points to exception_state, all
  98. register information saved. Now get the info on stack. */
  99. pushl %ebp
  100. movl %esp, %ebp /* load ebp with stack for easy access */
  101. movl 12(%ebp), %eax
  102. movl %eax, ERRCODE(%ebx)
  103. movl 16(%ebp), %eax
  104. movl %eax, EIP(%ebx)
  105. movl 20(%ebp), %eax
  106. movw %ax, CS(%ebx)
  107. movl 24(%ebp), %eax
  108. movl %eax, EFLAGS(%ebx)
  109. andb $0xfe, %ah /* Clear trace flag */
  110. movl %eax, 24(%ebp) /* and restore on stack */
  111. movl 28(%ebp), %eax
  112. movl %eax, ESP(%ebx)
  113. movl 32(%ebp), %eax
  114. movw %ax, SS(%ebx)
  115. movl $dpmi_exception_proc1, 16(%ebp) /* where to return */
  116. movw %cs, 20(%ebp)
  117. /* Change to our local stack on return from exception (maybe stack exception) */
  118. movw %ds, %ax
  119. cmpb $12,EXCEPNO(%ebx) /* Stack fault ? */
  120. je 1f
  121. cmpw %ax,32(%ebp)
  122. je stack_ok
  123. 1: movl $exception_stack+8000, 28(%ebp)
  124. movw %ax, 32(%ebp)
  125. stack_ok:
  126. /* Now copy the exception structure to the new stack before returning */
  127. movw %ax, %es
  128. movl %ebx,%esi
  129. movl 28(%ebp), %edi
  130. subl $92, %edi /* 64 plus extra for longjmp */
  131. movl %edi, 28(%ebp)
  132. movl %edi, ___djgpp_exception_state_ptr
  133. movl $16, %ecx
  134. cld
  135. rep
  136. movsl
  137. movl EAX(%ebx), %eax /* restore regs */
  138. movl ESI(%ebx), %esi
  139. movl EDI(%ebx), %edi
  140. movl ECX(%ebx), %ecx
  141. movw ES(%ebx), %es
  142. popl %ebp
  143. pushl EBX(%ebx)
  144. pushl DS(%ebx)
  145. movb $0, forced+2 /* flag non-use */
  146. popl %ds
  147. popl %ebx
  148. lret
  149. /* Code to fix fake exception, EBX destroyed. Note, app_DS may == our_DS! */
  150. .align 4
  151. limitFix:
  152. pushl %eax
  153. pushl %ecx
  154. pushl %edx
  155. .byte 0x2e /* CS: */
  156. movl ___djgpp_app_DS, %ebx /* avoid size prefix */
  157. .byte 0x2e /* CS: */
  158. movl ds_limit, %edx
  159. movl %edx, %ecx
  160. shrl $16, %ecx
  161. movw $0x0008, %ax
  162. int $0x31 /* Set segment limit */
  163. popl %edx
  164. popl %ecx
  165. popl %eax
  166. ret
  167. /* This local routine preprocesses a return request to the C code. It checks
  168. to make sure the DS & SS are set OK for C code. If not, it sets them up */
  169. .align 4
  170. dpmi_exception_proc1:
  171. cld
  172. .byte 0x2e /* CS: !!! */
  173. movw ___djgpp_our_DS, %bx /* to be sure */
  174. movw %bx, %ds
  175. movw %bx, %es
  176. /* Note: SS:ESP should be set properly by exception routine */
  177. jmp ___djgpp_exception_processor
  178. /* This code is called by a user routine wishing to save an interrupt
  179. ;* state. It will return with a clean stack, our DS,ES,SS.
  180. ;* Minor bug: uses static exception_state for a short window without
  181. ;* interrupts guaranteed disabled.
  182. ;*
  183. ;* [ EFLAGS ]
  184. ;* [ * | CS ]
  185. ;* [ EIP ]
  186. ;* [ CALLING EIP ]
  187. ;*/
  188. .align 4
  189. .globl ___djgpp_save_interrupt_regs
  190. ___djgpp_save_interrupt_regs:
  191. pushl %esi
  192. pushl %ds
  193. movw %cs:___djgpp_our_DS, %ds
  194. movl $exception_state, %esi
  195. popl DS(%esi) /* Trashes ES but OK */
  196. popl ESI(%esi)
  197. movl %edi, EDI(%esi)
  198. movl %ebp, EBP(%esi)
  199. movl %eax, EAX(%esi)
  200. movl %ebx, EBX(%esi)
  201. movl %ecx, ECX(%esi)
  202. movl %edx, EDX(%esi)
  203. popl %edx /* Save calling EIP */
  204. popl EIP(%esi)
  205. popl %eax
  206. movw %ax,CS(%esi) /* Don't pop, nukes DS */
  207. popl EFLAGS(%esi)
  208. movl %esp, ESP(%esi)
  209. movw %es, ES(%esi)
  210. movw %fs, FS(%esi)
  211. movw %gs, GS(%esi)
  212. movw %ss, SS(%esi)
  213. movl ___djgpp_exception_state_ptr, %eax
  214. movl %eax, PREVEXC(%esi)
  215. cld
  216. movw %ds, %ax
  217. movw %ax, %es
  218. movw %ss, %bx
  219. cmpw %ax, %bx /* is SS = DS ? */
  220. je Lss_ok
  221. movw %ax, %ss /* set new SS:ESP */
  222. movl $exception_stack+8000, %esp
  223. Lss_ok: subl $92, %esp /* 64 plus extra for longjmp */
  224. movl %esp, %edi
  225. movl $16, %ecx
  226. movl %edi, ___djgpp_exception_state_ptr
  227. rep
  228. movsl /* Copy structure to stack */
  229. jmp *%edx /* A "return" */
  230. .align 4 /* We will touch this; it must be locked */
  231. .global ___djgpp_hw_lock_start
  232. ___djgpp_hw_lock_start:
  233. ds_limit: .long 0
  234. forced: .long 0
  235. .global ___djgpp_cbrk_count
  236. ___djgpp_cbrk_count: .long 0
  237. .global ___djgpp_timer_countdown
  238. ___djgpp_timer_countdown: .long 0
  239. .global ___djgpp_our_DS
  240. ___djgpp_our_DS: .word 0
  241. .global ___djgpp_app_DS
  242. ___djgpp_app_DS: .word 0
  243. .global ___djgpp_dos_sel
  244. ___djgpp_dos_sel: .word 0
  245. .global ___djgpp_hwint_flags
  246. ___djgpp_hwint_flags: .word 0
  247. .global ___djgpp_old_kbd
  248. ___djgpp_old_kbd: .long 0,0
  249. .global ___djgpp_old_timer
  250. ___djgpp_old_timer: .long 0,0
  251. .global ___djgpp_exception_state_ptr
  252. ___djgpp_exception_state_ptr: .long 0
  253. exception_state: .space 64
  254. .global ___djgpp_ds_alias
  255. ___djgpp_ds_alias: .word 0 /* used in dpmi/api/d0303.s (alloc rmcb) */
  256. .align 4
  257. .global ___djgpp_npx_hdlr
  258. ___djgpp_npx_hdlr:
  259. pushl %eax
  260. xorl %eax,%eax
  261. outb %al,$0x0f0
  262. movb $0x20,%al
  263. outb %al,$0x0a0
  264. outb %al,$0x020
  265. movb $0x75,%al
  266. hw_to_excp:
  267. call ___djgpp_hw_exception
  268. popl %eax
  269. sti
  270. iret
  271. .align 4
  272. .global ___djgpp_kbd_hdlr
  273. ___djgpp_kbd_hdlr:
  274. pushl %eax
  275. pushl %ds
  276. .byte 0x2e /* CS: */
  277. testb $1, ___djgpp_hwint_flags /* Disable? */
  278. jne Lkbd_chain
  279. /* Check CTRL state */
  280. movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */
  281. /* movw $0x7021,0xb0f00 */ /* Test code - write to mono */
  282. testb $4,0x417 /* Test KB flags: CTRL down? */
  283. je Lkbd_chain
  284. testb $8,0x417 /* Test KB flags: ALT down? */
  285. jne Lkbd_chain /* Don't capture ALT-CTRL-C */
  286. /* Check port for scan code */
  287. inb $0x60,%al
  288. cmpb $0x2e,%al
  289. jne Lkbd_chain
  290. /* Clear interrupt, (later: remove byte from controller?)
  291. movb $0x20,%al
  292. outb %al,$0x020 */
  293. 98:
  294. movb $0x79,%al
  295. call ___djgpp_hw_exception
  296. Lkbd_chain:
  297. popl %ds
  298. popl %eax
  299. ljmp %cs:___djgpp_old_kbd
  300. .align 4
  301. .global ___djgpp_kbd_hdlr_pc98
  302. ___djgpp_kbd_hdlr_pc98:
  303. pushl %eax
  304. pushl %ds
  305. .byte 0x2e /* CS: */
  306. testb $1, ___djgpp_hwint_flags /* Disable? */
  307. jne Lkbd_chain
  308. /* Check CTRL state */
  309. movw %cs:___djgpp_dos_sel, %ds /* Conventional mem selector */
  310. testb $0x10,0x053a /* Test KB flags: CTRL down? */
  311. jz Lkbd_chain
  312. /* Check for scan code */
  313. testb $0x08,0x052f /* test KB "C" down for PC98 */
  314. jz Lkbd_chain
  315. jmp 98b
  316. .align 4
  317. .global ___djgpp_timer_hdlr
  318. ___djgpp_timer_hdlr:
  319. .byte 0x2e /* CS: */
  320. cmpl $0,___djgpp_timer_countdown
  321. je 4f
  322. pushl %ds
  323. movw %cs:___djgpp_ds_alias, %ds
  324. decl ___djgpp_timer_countdown
  325. popl %ds
  326. jmp 3f
  327. 4:
  328. pushl %eax
  329. movb $0x78,%al
  330. call ___djgpp_hw_exception
  331. popl %eax
  332. 3:
  333. .byte 0x2e /* CS: */
  334. testb $4, ___djgpp_hwint_flags /* IRET or chain? */
  335. jne 2f
  336. ljmp %cs:___djgpp_old_timer
  337. 2:
  338. pushl %eax
  339. movb $0x20,%al /* EOI the interrupt */
  340. outb %al,$0x020
  341. popl %eax
  342. iret
  343. /* On entry ES is the DS alias selector */
  344. .align 4
  345. .global ___djgpp_cbrk_hdlr /* A RMCB handler for 0x1b */
  346. ___djgpp_cbrk_hdlr:
  347. cld
  348. lodsl /* EAX = DS:[esi] CS:IP */
  349. movl %eax, %es:0x2a(%edi) /* store in structure */
  350. lodsl /* AX = FLAGS */
  351. movw %ax, %es:0x20(%edi)
  352. addw $6, %es:0x2e(%edi) /* Adjust RM SP */
  353. movb $0x1b,%al
  354. .byte 0x2e /* CS: */
  355. testb $2, ___djgpp_hwint_flags /* Count, don't kill */
  356. jne 1f
  357. call ___djgpp_hw_exception
  358. iret
  359. 1:
  360. incl %es:___djgpp_cbrk_count
  361. iret
  362. .global ___djgpp_i24 /* Int 24 handler if needed */
  363. .global ___djgpp_iret /* Int 23 handler if needed */
  364. ___djgpp_i24:
  365. movb $3,%al
  366. ___djgpp_iret:
  367. iret
  368. /* Code to stop execution ASAP, EAX destroyed. Make DS/ES/SS invalid.
  369. Fake exception value is passed in AL and moved into the "forced" variable.
  370. This is used to convert a HW interrupt into something we can transfer
  371. control away from via longjmp or exit(), common with SIGINT, SIGFPE, or
  372. if we want EIP information on timers. */
  373. .align 4
  374. .global ___djgpp_hw_exception
  375. ___djgpp_hw_exception:
  376. .byte 0x2e /* CS: */
  377. cmpl $0, forced /* Already flagged? */
  378. jne already_forced
  379. pushl %ebx
  380. pushl %ecx
  381. pushl %edx
  382. pushl %ds
  383. movw %cs:___djgpp_our_DS, %ds
  384. movl ___djgpp_app_DS, %ebx /* avoid size prefix */
  385. lsl %ebx, %ecx
  386. movl %ecx, ds_limit /* Save current limit */
  387. movb %al, forced /* Indicate a fake exception */
  388. xorl %ecx, %ecx
  389. movw $0xfff, %dx /* 4K limit is null page ! */
  390. movw $0x0008, %ax
  391. int $0x31 /* Set segment limit */
  392. 5: popl %ds
  393. popl %edx
  394. popl %ecx
  395. popl %ebx
  396. already_forced:
  397. ret
  398. .global ___djgpp_hw_lock_end
  399. ___djgpp_hw_lock_end:
  400. ret /* LD does weird things */