dpmiexcp.pp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Pierre Muller
  4. DPMI Exception routines for Go32V2
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$ifndef IN_SYSTEM}
  12. {$GOTO ON}
  13. {$define IN_DPMIEXCP_UNIT}
  14. {$ifndef NO_EXCEPTIONS_IN_SYSTEM}
  15. {$define EXCEPTIONS_IN_SYSTEM}
  16. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  17. Unit DpmiExcp;
  18. { If linking to C code we must avoid loading of the dpmiexcp.o
  19. in libc.a from the equivalent C code
  20. => all global functions from dpmiexcp.c must be aliased PM
  21. Problem this is only valid for DJGPP v2.01 }
  22. interface
  23. {$ifdef NO_EXCEPTIONS_IN_SYSTEM}
  24. uses
  25. go32;
  26. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  27. {$endif ndef IN_SYSTEM}
  28. { No stack checking ! }
  29. {$S-}
  30. { Decide if we want to create the C functions or not }
  31. {$ifdef EXCEPTIONS_IN_SYSTEM}
  32. { If exceptions are in system the C functions must be
  33. inserted in the system unit }
  34. {$ifdef IN_DPMIEXCP_UNIT}
  35. {$undef CREATE_C_FUNCTIONS}
  36. {$else not IN_DPMIEXCP_UNIT}
  37. {$define CREATE_C_FUNCTIONS}
  38. {$endif ndef IN_DPMIEXCP_UNIT}
  39. {$else not EXCEPTIONS_IN_SYSTEM}
  40. {$define CREATE_C_FUNCTIONS}
  41. {$endif not EXCEPTIONS_IN_SYSTEM}
  42. { Error Messages }
  43. function do_faulting_finish_message(fake : boolean) : integer;cdecl;
  44. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  45. {$ifndef CREATE_C_FUNCTIONS}
  46. external;
  47. {$endif CREATE_C_FUNCTIONS}
  48. { SetJmp/LongJmp }
  49. type
  50. { must also contain exception_state !! }
  51. pdpmi_jmp_buf = ^dpmi_jmp_buf;
  52. dpmi_jmp_buf = packed record
  53. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  54. cs,ds,es,fs,gs,ss : word;
  55. sigmask : longint; { for POSIX signals only }
  56. signum : longint; { for expansion ie 386 exception number }
  57. exception_ptr : pdpmi_jmp_buf; { pointer to previous exception if exists }
  58. end;
  59. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  60. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  61. {$ifndef CREATE_C_FUNCTIONS}
  62. external name 'FPC_setjmp';
  63. {$endif CREATE_C_FUNCTIONS}
  64. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  65. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  66. {$ifndef CREATE_C_FUNCTIONS}
  67. external name 'FPC_longjmp';
  68. {$endif CREATE_C_FUNCTIONS}
  69. { Signals }
  70. const
  71. SIGABRT = 288;
  72. SIGFPE = 289;
  73. SIGILL = 290;
  74. SIGSEGV = 291;
  75. SIGTERM = 292;
  76. SIGALRM = 293;
  77. SIGHUP = 294;
  78. SIGINT = 295;
  79. SIGKILL = 296;
  80. SIGPIPE = 297;
  81. SIGQUIT = 298;
  82. SIGUSR1 = 299;
  83. SIGUSR2 = 300;
  84. SIGNOFP = 301;
  85. SIGTRAP = 302;
  86. SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
  87. SIGPROF = 304;
  88. SIGMAX = 320;
  89. SIG_BLOCK = 1;
  90. SIG_SETMASK = 2;
  91. SIG_UNBLOCK = 3;
  92. function SIG_DFL( x: longint) : longint;
  93. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  94. {$ifndef CREATE_C_FUNCTIONS}
  95. external name '___djgpp_SIG_DFL';
  96. {$endif CREATE_C_FUNCTIONS}
  97. function SIG_ERR( x: longint) : longint;
  98. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  99. {$ifndef CREATE_C_FUNCTIONS}
  100. external name '___djgpp_SIG_ERR';
  101. {$endif CREATE_C_FUNCTIONS}
  102. function SIG_IGN( x: longint) : longint;
  103. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  104. {$ifndef CREATE_C_FUNCTIONS}
  105. external name '___djgpp_SIG_IGN';
  106. {$endif CREATE_C_FUNCTIONS}
  107. type
  108. SignalHandler = function (v : longint) : longint;
  109. PSignalHandler = ^SignalHandler; { to be compatible with linux.pp }
  110. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  111. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  112. function _raise(sig : longint) : longint;
  113. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  114. { Exceptions }
  115. type
  116. pexception_state = ^texception_state;
  117. texception_state = record
  118. __eax, __ebx, __ecx, __edx, __esi : longint;
  119. __edi, __ebp, __esp, __eip, __eflags : longint;
  120. __cs, __ds, __es, __fs, __gs, __ss : word;
  121. __sigmask : longint; { for POSIX signals only }
  122. __signum : longint; { for expansion }
  123. __exception_ptr : pexception_state; { pointer to previous exception }
  124. __fpu_state : array [0..108-1] of byte; { for future use }
  125. end;
  126. procedure djgpp_exception_toggle;
  127. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  128. {$ifndef CREATE_C_FUNCTIONS}
  129. external name '___djgpp_exception_toggle';
  130. {$endif CREATE_C_FUNCTIONS}
  131. procedure djgpp_exception_setup;
  132. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  133. {$ifndef CREATE_C_FUNCTIONS}
  134. external name '___djgpp_exception_setup';
  135. {$endif CREATE_C_FUNCTIONS}
  136. function djgpp_exception_state : pexception_state;
  137. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  138. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  139. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  140. { Other }
  141. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  142. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  143. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  144. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  145. {$ifndef CREATE_C_FUNCTIONS}
  146. external;
  147. {$endif CREATE_C_FUNCTIONS}
  148. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  149. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  150. {$ifndef CREATE_C_FUNCTIONS}
  151. external;
  152. {$endif CREATE_C_FUNCTIONS}
  153. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  154. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  155. {$ifndef CREATE_C_FUNCTIONS}
  156. external;
  157. {$endif CREATE_C_FUNCTIONS}
  158. {$ifndef IN_SYSTEM}
  159. implementation
  160. {$endif IN_SYSTEM}
  161. {$asmmode ATT}
  162. {$ifdef CREATE_C_FUNCTIONS}
  163. {$L exceptn.o}
  164. var
  165. v2prt0_ds_alias : word;external name '___v2prt0_ds_alias';
  166. djgpp_ds_alias : word;external name '___djgpp_ds_alias';
  167. djgpp_old_kbd : tseginfo;external name '___djgpp_old_kbd';
  168. djgpp_hw_lock_start : longint;external name '___djgpp_hw_lock_start';
  169. djgpp_hw_lock_end : longint;external name '___djgpp_hw_lock_end';
  170. djgpp_dos_sel : word;external name '___djgpp_dos_sel';
  171. djgpp_exception_table : array[0..0] of pointer;external name '___djgpp_exception_table';
  172. dosmemselector : word;external name '_core_selector';
  173. procedure djgpp_i24;external name '___djgpp_i24';
  174. procedure djgpp_iret;external name '___djgpp_iret';
  175. procedure djgpp_npx_hdlr;external name '___djgpp_npx_hdlr';
  176. procedure djgpp_kbd_hdlr;external name '___djgpp_kbd_hdlr';
  177. procedure djgpp_kbd_hdlr_pc98;external name '___djgpp_kbd_hdlr_pc98';
  178. procedure djgpp_cbrk_hdlr;external name '___djgpp_cbrk_hdlr';
  179. var
  180. exceptions_on : boolean;
  181. { old_int00 : tseginfo;cvar;external;
  182. old_int75 : tseginfo;cvar;external; }
  183. const
  184. cbrk_vect : byte = $1b;
  185. exception_level : longint = 0;
  186. {$endif CREATE_C_FUNCTIONS}
  187. var
  188. endtext : longint;external name '_etext';
  189. starttext : longint;external name 'start';
  190. djgpp_exception_state_ptr : pexception_state;external name '___djgpp_exception_state_ptr';
  191. djgpp_hwint_flags : longint;external name '___djgpp_hwint_flags';
  192. {$ifndef IN_DPMIEXCP_UNIT}
  193. {****************************************************************************
  194. DPMI functions copied from go32 unit
  195. ****************************************************************************}
  196. const
  197. int31error : word = 0;
  198. procedure test_int31(flag : longint); stdcall; { stack-args! }
  199. begin
  200. asm
  201. pushl %ebx
  202. movw $0,INT31ERROR
  203. movl flag,%ebx
  204. testb $1,%bl
  205. jz .Lti31_1
  206. movw %ax,INT31ERROR
  207. xorl %eax,%eax
  208. jmp .Lti31_2
  209. .Lti31_1:
  210. movl $1,%eax
  211. .Lti31_2:
  212. popl %ebx
  213. end;
  214. end;
  215. function set_pm_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  216. begin
  217. asm
  218. movl intaddr,%eax
  219. movl (%eax),%edx
  220. movw 4(%eax),%cx
  221. movl $0x212,%eax
  222. movb e,%bl
  223. int $0x31
  224. pushf
  225. call test_int31
  226. movb %al,__RESULT
  227. end;
  228. end;
  229. function set_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  230. begin
  231. asm
  232. movl intaddr,%eax
  233. movl (%eax),%edx
  234. movw 4(%eax),%cx
  235. movl $0x203,%eax
  236. movb e,%bl
  237. int $0x31
  238. pushf
  239. call test_int31
  240. movb %al,__RESULT
  241. end;
  242. end;
  243. function get_pm_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  244. begin
  245. asm
  246. movl $0x210,%eax
  247. movb e,%bl
  248. int $0x31
  249. pushf
  250. call test_int31
  251. movb %al,__RESULT
  252. movl intaddr,%eax
  253. movl %edx,(%eax)
  254. movw %cx,4(%eax)
  255. end;
  256. end;
  257. function get_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  258. begin
  259. asm
  260. pushl %ebx
  261. movl $0x202,%eax
  262. movb e,%bl
  263. int $0x31
  264. pushf
  265. call test_int31
  266. movb %al,__RESULT
  267. movl intaddr,%eax
  268. movl %edx,(%eax)
  269. movw %cx,4(%eax)
  270. popl %ebx
  271. end;
  272. end;
  273. function get_segment_base_address(d : word) : longint;
  274. begin
  275. asm
  276. pushl %ebx
  277. movw d,%bx
  278. movl $6,%eax
  279. int $0x31
  280. xorl %eax,%eax
  281. movw %dx,%ax
  282. shll $16,%ecx
  283. orl %ecx,%eax
  284. movl %eax,__RESULT
  285. popl %ebx
  286. end;
  287. end;
  288. function get_segment_limit(d : word) : longint;
  289. begin
  290. asm
  291. movzwl d,%eax
  292. lsl %eax,%eax
  293. jz .L_ok2
  294. xorl %eax,%eax
  295. .L_ok2:
  296. movl %eax,__RESULT
  297. end;
  298. end;
  299. function set_rm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  300. begin
  301. asm
  302. pushl %ebx
  303. movl intaddr,%eax
  304. movw (%eax),%dx
  305. movw 4(%eax),%cx
  306. movl $0x201,%eax
  307. movb vector,%bl
  308. int $0x31
  309. pushf
  310. call test_int31
  311. movb %al,__RESULT
  312. popl %ebx
  313. end;
  314. end;
  315. function get_rm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  316. begin
  317. asm
  318. pushl %ebx
  319. movb vector,%bl
  320. movl $0x200,%eax
  321. int $0x31
  322. pushf
  323. call test_int31
  324. movb %al,__RESULT
  325. movl intaddr,%eax
  326. movzwl %dx,%edx
  327. movl %edx,(%eax)
  328. movw %cx,4(%eax)
  329. popl %ebx
  330. end;
  331. end;
  332. function free_rm_callback(var intaddr : tseginfo) : boolean;
  333. begin
  334. asm
  335. movl intaddr,%eax
  336. movw (%eax),%dx
  337. movw 4(%eax),%cx
  338. movl $0x304,%eax
  339. int $0x31
  340. pushf
  341. call test_int31
  342. movb %al,__RESULT
  343. end;
  344. end;
  345. function get_rm_callback(pm_func : pointer;const reg : trealregs;var rmcb : tseginfo) : boolean;
  346. begin
  347. asm
  348. pushl %esi
  349. pushl %edi
  350. movl pm_func,%esi
  351. movl reg,%edi
  352. pushw %es
  353. movw v2prt0_ds_alias,%ax
  354. movw %ax,%es
  355. pushw %ds
  356. movw %cs,%ax
  357. movw %ax,%ds
  358. movl $0x303,%eax
  359. int $0x31
  360. popw %ds
  361. popw %es
  362. pushf
  363. call test_int31
  364. movb %al,__RESULT
  365. movl rmcb,%eax
  366. movzwl %dx,%edx
  367. movl %edx,(%eax)
  368. movw %cx,4(%eax)
  369. popl %edi
  370. popl %esi
  371. end;
  372. end;
  373. function lock_linear_region(linearaddr, size : longint) : boolean;
  374. begin
  375. asm
  376. pushl %ebx
  377. pushl %esi
  378. pushl %edi
  379. movl $0x600,%eax
  380. movl linearaddr,%ecx
  381. movl %ecx,%ebx
  382. shrl $16,%ebx
  383. movl size,%esi
  384. movl %esi,%edi
  385. shrl $16,%esi
  386. int $0x31
  387. pushf
  388. call test_int31
  389. movb %al,__RESULT
  390. popl %edi
  391. popl %esi
  392. popl %ebx
  393. end;
  394. end;
  395. function lock_code(functionaddr : pointer;size : longint) : boolean;
  396. var
  397. linearaddr : longint;
  398. begin
  399. linearaddr:=longint(functionaddr)+get_segment_base_address(get_cs);
  400. lock_code:=lock_linear_region(linearaddr,size);
  401. end;
  402. {$endif ndef IN_DPMIEXCP_UNIT}
  403. {****************************************************************************
  404. Helpers
  405. ****************************************************************************}
  406. procedure err(const x : string);
  407. begin
  408. write(stderr, x);
  409. end;
  410. procedure errln(const x : string);
  411. begin
  412. writeln(stderr, x);
  413. end;
  414. procedure itox(v,len : longint);
  415. var
  416. st : string;
  417. begin
  418. st:=hexstr(v,len);
  419. err(st);
  420. end;
  421. {****************************************************************************
  422. SetJmp/LongJmp
  423. ****************************************************************************}
  424. {$ifdef CREATE_C_FUNCTIONS}
  425. function c_setjmp(var rec : dpmi_jmp_buf) : longint;[public, alias : '_setjmp'];
  426. begin
  427. { here we need to be subtle :
  428. - we need to return with the arg still on the stack
  429. - but we also need to jmp to FPC_setjmp and not to call it
  430. because otherwise the return address is wrong !!
  431. For this we shift the return address down and
  432. duplicate the rec on stack }
  433. asm
  434. movl %ebp,%esp
  435. popl %ebp
  436. subl $8,%esp
  437. movl %eax,(%esp)
  438. movl 8(%esp),%eax
  439. movl %eax,4(%esp)
  440. movl 12(%esp),%eax
  441. movl %eax,8(%esp)
  442. popl %eax
  443. jmp dpmi_setjmp
  444. end;
  445. end;
  446. {$endif CREATE_C_FUNCTIONS}
  447. {$ifdef CREATE_C_FUNCTIONS}
  448. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  449. [public, alias : 'FPC_setjmp'];
  450. begin
  451. asm
  452. pushl %edi
  453. movl rec,%edi
  454. movl %eax,(%edi)
  455. movl %ebx,4(%edi)
  456. movl %ecx,8(%edi)
  457. movl %edx,12(%edi)
  458. movl %esi,16(%edi)
  459. { load edi }
  460. movl -4(%ebp),%eax
  461. { ... and store it }
  462. movl %eax,20(%edi)
  463. { ebp ... }
  464. movl (%ebp),%eax
  465. movl %eax,24(%edi)
  466. { esp ... }
  467. movl %esp,%eax
  468. addl $12,%eax
  469. movl %eax,28(%edi)
  470. { the return address }
  471. movl 4(%ebp),%eax
  472. movl %eax,32(%edi)
  473. { flags ... }
  474. pushfl
  475. popl 36(%edi)
  476. { !!!!! the segment registers, not yet needed }
  477. { you need them if the exception comes from
  478. an interrupt or a seg_move }
  479. movw %cs,40(%edi)
  480. movw %ds,42(%edi)
  481. movw %es,44(%edi)
  482. movw %fs,46(%edi)
  483. movw %gs,48(%edi)
  484. movw %ss,50(%edi)
  485. movl djgpp_exception_state_ptr, %eax
  486. movl %eax, 60(%edi)
  487. { restore EDI }
  488. pop %edi
  489. { we come from the initial call }
  490. xorl %eax,%eax
  491. movl %eax,__RESULT
  492. { leave USING RET inside CDECL functions is risky as
  493. some registers are pushed at entry
  494. ret $4 not anymore since cdecl !! }
  495. end;
  496. end;
  497. {$endif CREATE_C_FUNCTIONS}
  498. {$ifdef CREATE_C_FUNCTIONS}
  499. procedure c_longjmp(var rec : dpmi_jmp_buf;return_value : longint);[public, alias : '_longjmp'];
  500. begin
  501. dpmi_longjmp(rec,return_value);
  502. { never gets here !! so pascal stack convention is no problem }
  503. end;
  504. {$endif CREATE_C_FUNCTIONS}
  505. {$ifdef CREATE_C_FUNCTIONS}
  506. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  507. [public, alias : 'FPC_longjmp'];
  508. begin
  509. if (exception_level>0) then
  510. dec(exception_level);
  511. asm
  512. { restore compiler shit }
  513. popl %ebp
  514. { copy from longjmp.S }
  515. movl 4(%esp),%edi { get dpmi_jmp_buf }
  516. movl 8(%esp),%eax { store retval in j->eax }
  517. movl %eax,0(%edi)
  518. movw 46(%edi),%fs
  519. movw 48(%edi),%gs
  520. movl 4(%edi),%ebx
  521. movl 8(%edi),%ecx
  522. movl 12(%edi),%edx
  523. movl 24(%edi),%ebp
  524. { Now for some uglyness. The dpmi_jmp_buf structure may be ABOVE the
  525. point on the new SS:ESP we are moving to. We don't allow overlap,
  526. but do force that it always be valid. We will use ES:ESI for
  527. our new stack before swapping to it. }
  528. movw 50(%edi),%es
  529. movl 28(%edi),%esi
  530. subl $28,%esi { We need 7 working longwords on stack }
  531. movl 60(%edi),%eax
  532. movl %eax,%es:(%esi) { Exception pointer }
  533. movzwl 42(%edi),%eax
  534. movl %eax,%es:4(%esi) { DS }
  535. movl 20(%edi),%eax
  536. movl %eax,%es:8(%esi) { EDI }
  537. movl 16(%edi),%eax
  538. movl %eax,%es:12(%esi) { ESI }
  539. movl 32(%edi),%eax
  540. movl %eax,%es:16(%esi) { EIP - start of IRET frame }
  541. movl 40(%edi),%eax
  542. movl %eax,%es:20(%esi) { CS }
  543. movl 36(%edi),%eax
  544. movl %eax,%es:24(%esi) { EFLAGS }
  545. movl 0(%edi),%eax
  546. movw 44(%edi),%es
  547. movw 50(%edi),%ss
  548. movl %esi,%esp
  549. popl djgpp_exception_state_ptr
  550. popl %ds
  551. popl %edi
  552. popl %esi
  553. iret { actually jump to new cs:eip loading flags }
  554. end;
  555. end;
  556. {$endif CREATE_C_FUNCTIONS}
  557. {****************************************************************************
  558. Signals
  559. ****************************************************************************}
  560. var
  561. signal_list : Array[0..SIGMAX] of SignalHandler;cvar;
  562. {$ifndef CREATE_C_FUNCTIONS}external;{$endif}
  563. {$ifdef CREATE_C_FUNCTIONS}
  564. function SIG_ERR(x:longint):longint;[public,alias : '___djgpp_SIG_ERR'];
  565. begin
  566. SIG_ERR:=-1;
  567. end;
  568. function SIG_IGN(x:longint):longint;[public,alias : '___djgpp_SIG_IGN'];
  569. begin
  570. SIG_IGN:=-1;
  571. end;
  572. function SIG_DFL(x:longint):longint;[public,alias : '___djgpp_SIG_DFL'];
  573. begin
  574. SIG_DFL:=0;
  575. end;
  576. {$endif CREATE_C_FUNCTIONS}
  577. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  578. var
  579. temp : SignalHandler;
  580. begin
  581. if ((sig < 0) or (sig > SIGMAX) or (sig = SIGKILL)) then
  582. begin
  583. signal:=@SIG_ERR;
  584. runerror(201);
  585. end;
  586. temp := signal_list[sig];
  587. signal_list[sig] := func;
  588. signal:=temp;
  589. end;
  590. {$ifdef CREATE_C_FUNCTIONS}
  591. { C counter part }
  592. function c_signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;[public,alias : '_signal'];
  593. var
  594. temp : SignalHandler;
  595. begin
  596. temp:=signal(sig,func);
  597. c_signal:=temp;
  598. end;
  599. {$endif CREATE_C_FUNCTIONS}
  600. const
  601. signames : array [0..14] of string[4] = (
  602. 'ABRT','FPE ','ILL ','SEGV','TERM','ALRM','HUP ',
  603. 'INT ','KILL','PIPE','QUIT','USR1','USR2','NOFP','TRAP');
  604. procedure print_signal_name(sig : longint);
  605. begin
  606. if ((sig >= SIGABRT) and (sig <= SIGTRAP)) then
  607. begin
  608. err('Exiting due to signal SIG');
  609. err(signames[sig-sigabrt]);
  610. end
  611. else
  612. begin
  613. err('Exiting due to signal $');
  614. itox(sig, 4);
  615. end;
  616. errln('');
  617. end;
  618. function _raise(sig : longint) : longint;
  619. var
  620. temp : SignalHandler;
  621. begin
  622. if(sig < 0) or (sig > SIGMAX) then
  623. exit(-1);
  624. temp:=signal_list[sig];
  625. if (temp = SignalHandler(@SIG_IGN)) then
  626. exit(0);
  627. if (temp = SignalHandler(@SIG_DFL)) then
  628. begin
  629. print_signal_name(sig);
  630. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  631. exit(-1);
  632. end;
  633. { this is incompatible with dxegen-dxeload stuff PM }
  634. if ((cardinal(temp) < cardinal(@starttext)) or
  635. (cardinal(temp) > cardinal(@endtext))) then
  636. begin
  637. errln('Bad signal handler, ');
  638. print_signal_name(sig);
  639. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  640. exit(-1);
  641. end;
  642. { WARNING !!! temp can be a pascal or a C
  643. function... thus %esp can be modified here !!!
  644. This might be dangerous for some optimizations ?? PM }
  645. temp(sig);
  646. exit(0);
  647. end;
  648. {$ifdef CREATE_C_FUNCTIONS}
  649. function c_raise(sig : longint) : longint;cdecl;[public,alias : '_raise'];
  650. begin
  651. c_raise:=_raise(sig);
  652. end;
  653. {$endif CREATE_C_FUNCTIONS}
  654. {****************************************************************************
  655. Exceptions
  656. ****************************************************************************}
  657. var
  658. ___djgpp_selector_limit: cardinal; external name '___djgpp_selector_limit';
  659. {$ifdef CREATE_C_FUNCTIONS}
  660. {$ifdef IN_DPMIEXCP_UNIT}
  661. procedure __exit(c:longint);cdecl;external;
  662. {$endif}
  663. function except_to_sig(excep : longint) : longint;
  664. begin
  665. case excep of
  666. 5,8,9,11,12,13,14,
  667. 18, 19 : exit(SIGSEGV);
  668. 0,4,16 : exit(SIGFPE);
  669. 1,3 : exit(SIGTRAP);
  670. 7 : exit(SIGNOFP);
  671. else
  672. begin
  673. case excep of
  674. $75 : exit(SIGFPE);
  675. $78 : exit(SIGTIMR);
  676. $1b,
  677. $79 : exit(SIGINT);
  678. $7a : exit(SIGQUIT);
  679. else
  680. exit(SIGILL);
  681. end;
  682. end;
  683. end;
  684. end;
  685. procedure show_call_frame(djgpp_exception_state : pexception_state);
  686. begin
  687. errln('Call frame traceback EIPs:');
  688. errln(BackTraceStrFunc(Pointer(djgpp_exception_state^.__eip)));
  689. dump_stack(stderr,Pointer(djgpp_exception_state^.__ebp));
  690. end;
  691. const
  692. EXCEPTIONCOUNT = 20;
  693. exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (
  694. 'Division by Zero',
  695. 'Debug',
  696. 'NMI',
  697. 'Breakpoint',
  698. 'Overflow',
  699. 'Bounds Check',
  700. 'Invalid Opcode',
  701. 'Coprocessor not available',
  702. 'Double Fault',
  703. 'Coprocessor overrun',
  704. 'Invalid TSS',
  705. 'Segment Not Present',
  706. 'Stack Fault',
  707. 'General Protection Fault',
  708. 'Page fault',
  709. ' ',
  710. 'Coprocessor Error',
  711. 'Alignment Check',
  712. 'Machine check',
  713. 'SIMD FP Error');
  714. has_error : array [0..EXCEPTIONCOUNT-1] of byte =
  715. (0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,0,0);
  716. cbrk_hooked : boolean = false;
  717. old_video_mode : byte = 3;
  718. procedure dump_selector(const name : string; sel : word);
  719. var
  720. base,limit : longint;
  721. begin
  722. err(name);
  723. err(': sel=');
  724. itox(sel, 4);
  725. if (sel<>0) then
  726. begin
  727. base:=get_segment_base_address(sel);
  728. err(' base='); itox(base, 8);
  729. limit:=get_segment_limit(sel);
  730. err(' limit='); itox(limit, 8);
  731. end;
  732. errln('');
  733. end;
  734. function farpeekb(sel : word;offset : longint) : byte;
  735. var
  736. b : byte;
  737. begin
  738. {$ifdef IN_DPMIEXCP_UNIT}
  739. seg_move(sel,offset,get_ds,longint(@b),1);
  740. {$else not IN_DPMIEXCP_UNIT}
  741. sysseg_move(sel,offset,get_ds,longint(@b),1);
  742. {$endif IN_DPMIEXCP_UNIT}
  743. farpeekb:=b;
  744. end;
  745. const message_level : byte = 0;
  746. function do_faulting_finish_message(fake : boolean) : integer;cdecl;
  747. public;
  748. var
  749. en : pchar;
  750. signum,i : longint;
  751. old_vid : byte;
  752. label
  753. simple_exit;
  754. function _my_cs: word; assembler;
  755. asm
  756. movw %cs,%ax
  757. end;
  758. begin
  759. inc(message_level);
  760. if message_level>2 then
  761. goto simple_exit;
  762. do_faulting_finish_message:=0;
  763. signum:=djgpp_exception_state_ptr^.__signum;
  764. { check video mode for original here and reset (not if PC98) }
  765. if ((go32_info_block.linear_address_of_primary_screen <> $a0000) and
  766. (farpeekb(dosmemselector, $449) <> old_video_mode)) then
  767. begin
  768. old_vid:=old_video_mode;
  769. asm
  770. pusha
  771. movzbl old_vid,%eax
  772. int $0x10
  773. popa
  774. nop
  775. end;
  776. end;
  777. if (signum >= EXCEPTIONCOUNT) then
  778. begin
  779. case signum of
  780. $75 : en:='Floating Point exception';
  781. $1b : en:='Control-Break Pressed';
  782. $79 : en:='Control-C Pressed';
  783. $7a : en:='QUIT key Pressed'
  784. else
  785. en:=nil;
  786. end;
  787. end
  788. else
  789. en:=exception_names[signum];
  790. if (en = nil) then
  791. begin
  792. if fake then
  793. err('Raised ')
  794. else
  795. err('Exception ');
  796. itox(signum, 2);
  797. err(' at eip=');
  798. (* For fake exceptions like SIGABRT report where `raise' was called. *)
  799. if fake and (djgpp_exception_state_ptr^.__cs = _my_cs)
  800. and (djgpp_exception_state_ptr^.__ebp >= djgpp_exception_state_ptr^.__esp)
  801. and (djgpp_exception_state_ptr^.__ebp >= endtext)
  802. and (djgpp_exception_state_ptr^.__ebp < ___djgpp_selector_limit) then
  803. itox(djgpp_exception_state_ptr^.__ebp + 1, 8)
  804. else
  805. itox(djgpp_exception_state_ptr^.__eip, 8);
  806. end
  807. else
  808. begin
  809. write(stderr, 'FPC ',en);
  810. err(' at eip=');
  811. itox(djgpp_exception_state_ptr^.__eip, 8);
  812. end;
  813. { Control-C should stop the program also !}
  814. {if (signum = $79) then
  815. begin
  816. errln('');
  817. exit(-1);
  818. end;}
  819. if ((signum < EXCEPTIONCOUNT) and (has_error[signum]=1)) then
  820. begin
  821. errorcode := djgpp_exception_state_ptr^.__sigmask and $ffff;
  822. if(errorcode<>0) then
  823. begin
  824. err(', error=');
  825. itox(errorcode, 4);
  826. end;
  827. end;
  828. errln('');
  829. err('eax=');
  830. itox(djgpp_exception_state_ptr^.__eax, 8);
  831. err(' ebx='); itox(djgpp_exception_state_ptr^.__ebx, 8);
  832. err(' ecx='); itox(djgpp_exception_state_ptr^.__ecx, 8);
  833. err(' edx='); itox(djgpp_exception_state_ptr^.__edx, 8);
  834. err(' esi='); itox(djgpp_exception_state_ptr^.__esi, 8);
  835. err(' edi='); itox(djgpp_exception_state_ptr^.__edi, 8);
  836. errln('');
  837. err('ebp='); itox(djgpp_exception_state_ptr^.__ebp, 8);
  838. err(' esp='); itox(djgpp_exception_state_ptr^.__esp, 8);
  839. err(' program=');
  840. errln(paramstr(0));
  841. dump_selector('cs', djgpp_exception_state_ptr^.__cs);
  842. dump_selector('ds', djgpp_exception_state_ptr^.__ds);
  843. dump_selector('es', djgpp_exception_state_ptr^.__es);
  844. dump_selector('fs', djgpp_exception_state_ptr^.__fs);
  845. dump_selector('gs', djgpp_exception_state_ptr^.__gs);
  846. dump_selector('ss', djgpp_exception_state_ptr^.__ss);
  847. errln('');
  848. if (djgpp_exception_state_ptr^.__cs = get_cs) then
  849. show_call_frame(djgpp_exception_state_ptr)
  850. {$ifdef DPMIEXCP_DEBUG}
  851. else
  852. errln('Exception occured in another context');
  853. {$endif def DPMIEXCP_DEBUG}
  854. ;
  855. if assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  856. if (djgpp_exception_state_ptr^.__exception_ptr^.__cs = get_cs) then
  857. begin
  858. Errln('First exception level stack');
  859. show_call_frame(djgpp_exception_state_ptr^.__exception_ptr);
  860. end
  861. {$ifdef DPMIEXCP_DEBUG}
  862. else
  863. begin
  864. errln('First exception occured in another context');
  865. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  866. do_faulting_finish_message(false);
  867. end;
  868. {$endif def DPMIEXCP_DEBUG}
  869. ;
  870. { must not return !! }
  871. simple_exit:
  872. if exceptions_on then
  873. djgpp_exception_toggle;
  874. __exit(-1);
  875. end;
  876. {$endif CREATE_C_FUNCTIONS}
  877. function djgpp_exception_state:pexception_state;assembler;
  878. asm
  879. movl djgpp_exception_state_ptr,%eax
  880. end;
  881. {$ifdef CREATE_C_FUNCTIONS}
  882. var
  883. _os_trueversion : word;external name '__os_trueversion';
  884. procedure djgpp_exception_processor;[public,alias : '___djgpp_exception_processor'];
  885. var
  886. sig : longint;
  887. begin
  888. if not assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  889. exception_level:=1
  890. else
  891. inc(exception_level);
  892. sig:=djgpp_exception_state_ptr^.__signum;
  893. if (exception_level=1) or (sig=$78) then
  894. begin
  895. sig := except_to_sig(sig);
  896. if signal_list[djgpp_exception_state_ptr^.__signum]
  897. <>SignalHandler(@SIG_DFL) then
  898. _raise(djgpp_exception_state_ptr^.__signum)
  899. else
  900. _raise(sig);
  901. if (djgpp_exception_state_ptr^.__signum >= EXCEPTIONCOUNT) then
  902. { Not exception so continue OK }
  903. dpmi_longjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^, djgpp_exception_state_ptr^.__eax);
  904. { User handler did not exit or longjmp, we must exit }
  905. err('FPC cannot continue from exception, exiting due to signal ');
  906. itox(sig, 4);
  907. errln('');
  908. end
  909. else
  910. begin
  911. if exception_level>2 then
  912. begin
  913. if exception_level=3 then
  914. errln('FPC triple exception, exiting !!! ');
  915. if (exceptions_on) then
  916. djgpp_exception_toggle;
  917. __exit(1);
  918. end;
  919. err('FPC double exception, exiting due to signal ');
  920. itox(sig, 4);
  921. errln('');
  922. end;
  923. do_faulting_finish_message(djgpp_exception_state<>nil);
  924. end;
  925. type
  926. trealseginfo = tseginfo;
  927. pseginfo = ^tseginfo;
  928. var
  929. except_ori : array [0..EXCEPTIONCOUNT-1] of tseginfo;
  930. {$ifdef DPMIEXCP_DEBUG}
  931. export name '_ori_exceptions';
  932. {$endif def DPMIEXCP_DEBUG}
  933. kbd_ori : tseginfo;
  934. int0_ori,
  935. npx_ori : tseginfo;
  936. cbrk_ori,
  937. cbrk_rmcb : trealseginfo;
  938. cbrk_regs : trealregs;
  939. v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  940. procedure djgpp_exception_toggle;
  941. [public,alias : '___djgpp_exception_toggle'];
  942. var
  943. _except : tseginfo;
  944. i : longint;
  945. begin
  946. {$ifdef DPMIEXCP_DEBUG}
  947. if exceptions_on then
  948. errln('Disabling FPC exceptions')
  949. else
  950. errln('Enabling FPC exceptions');
  951. {$endif DPMIEXCP_DEBUG}
  952. { toggle here to avoid infinite recursion }
  953. { if a subfunction calls runerror !! }
  954. exceptions_on:=not exceptions_on;
  955. v2prt0_exceptions_on:=exceptions_on;
  956. { Exceptions 18 and 19 settings generates a bug in
  957. the DJGPP debug code PM }
  958. for i:=0 to 17{EXCEPTIONCOUNT-1} do
  959. begin
  960. {$ifdef DPMIEXCP_DEBUG}
  961. errln('new exception '+hexstr(i,2)+' '+hexstr(except_ori[i].segment,4)+':'+hexstr(longint(except_ori[i].offset),8));
  962. {$endif DPMIEXCP_DEBUG}
  963. { Windows 2000 seems to not set carryflag on func 0x210 :( PM }
  964. if (_os_trueversion <> $532) and get_pm_exception_handler(i,_except) then
  965. begin
  966. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  967. begin
  968. {$ifdef DPMIEXCP_DEBUG}
  969. errln('Using DPMI 1.0 functions');
  970. {$endif DPMIEXCP_DEBUG}
  971. if not set_pm_exception_handler(i,except_ori[i]) then
  972. errln('error setting exception nø'+hexstr(i,2));
  973. end;
  974. except_ori[i]:=_except;
  975. end
  976. else
  977. begin
  978. if get_exception_handler(i,_except) then
  979. begin
  980. {$ifdef DPMIEXCP_DEBUG}
  981. errln('Using DPMI 0.9 functions');
  982. {$endif DPMIEXCP_DEBUG}
  983. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  984. begin
  985. if not set_exception_handler(i,except_ori[i]) then
  986. errln('error setting exception nø'+hexstr(i,2));
  987. end;
  988. except_ori[i]:=_except;
  989. end;
  990. end;
  991. {$ifdef DPMIEXCP_DEBUG}
  992. errln('prev exception '+hexstr(i,2)+' '+hexstr(_except.segment,4)+':'+hexstr(longint(_except.offset),8));
  993. {$endif DPMIEXCP_DEBUG}
  994. end;
  995. get_pm_interrupt($75,_except);
  996. set_pm_interrupt($75,npx_ori);
  997. npx_ori:=_except;
  998. get_pm_interrupt($0,_except);
  999. set_pm_interrupt($0,int0_ori);
  1000. int0_ori:=_except;
  1001. get_pm_interrupt(9,_except);
  1002. set_pm_interrupt(9,kbd_ori);
  1003. kbd_ori:=_except;
  1004. if (cbrk_hooked) then
  1005. begin
  1006. set_rm_interrupt(cbrk_vect,cbrk_ori);
  1007. free_rm_callback(cbrk_rmcb);
  1008. cbrk_hooked := false;
  1009. {$ifdef DPMIEXCP_DEBUG}
  1010. errln('back to ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  1011. {$endif DPMIEXCP_DEBUG}
  1012. end
  1013. else
  1014. begin
  1015. get_rm_interrupt(cbrk_vect, cbrk_ori);
  1016. {$ifdef DPMIEXCP_DEBUG}
  1017. errln('ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  1018. {$endif DPMIEXCP_DEBUG}
  1019. get_rm_callback(@djgpp_cbrk_hdlr, cbrk_regs, cbrk_rmcb);
  1020. set_rm_interrupt(cbrk_vect, cbrk_rmcb);
  1021. {$ifdef DPMIEXCP_DEBUG}
  1022. errln('now rm cbrk '+hexstr(cbrk_rmcb.segment,4)+':'+hexstr(longint(cbrk_rmcb.offset),4));
  1023. {$endif DPMIEXCP_DEBUG}
  1024. cbrk_hooked := true;
  1025. end;
  1026. end;
  1027. {$endif CREATE_C_FUNCTIONS}
  1028. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  1029. var
  1030. res : longint;
  1031. begin
  1032. asm
  1033. pushl %ebx
  1034. movl flag,%ebx
  1035. movl $0xe01,%eax
  1036. int $0x31
  1037. jc .L_coproc_error
  1038. xorl %eax,%eax
  1039. .L_coproc_error:
  1040. movl %eax,res
  1041. popl %ebx
  1042. end;
  1043. dpmi_set_coprocessor_emulation:=res;
  1044. end;
  1045. {$ifdef CREATE_C_FUNCTIONS}
  1046. var
  1047. _swap_in : pointer;external name '_swap_in';
  1048. _swap_out : pointer;external name '_swap_out';
  1049. _exception_exit : pointer;external name '_exception_exit';
  1050. const
  1051. STUBINFO_END = $54;
  1052. procedure __maybe_fix_w2k_ntvdm_bug;[public,alias : '___maybe_fix_w2k_ntvdm_bug'];
  1053. var
  1054. psp_sel : word;
  1055. begin
  1056. if _os_trueversion = $532 then
  1057. begin
  1058. { avoid NTVDM bug on NT,2000 or XP }
  1059. { see dpmiexcp.c source of DJGPP PM }
  1060. if stub_info^.size < STUBINFO_END then
  1061. begin
  1062. asm
  1063. movb $0x51,%ah
  1064. int $0x21
  1065. movb $0x50,%ah
  1066. int $0x21
  1067. end;
  1068. end
  1069. else
  1070. begin
  1071. psp_sel:=stub_info^.psp_selector;
  1072. asm
  1073. pushl %ebx
  1074. movw psp_sel,%bx
  1075. movb $0x50,%ah
  1076. int $0x21
  1077. popl %ebx
  1078. end;
  1079. end;
  1080. end;
  1081. end;
  1082. procedure dpmiexcp_exit{(status : longint)};[public,alias : 'excep_exit'];
  1083. { We need to restore hardware interrupt handlers even if somebody calls
  1084. `_exit' directly, or else we crash the machine in nested programs.
  1085. We only toggle the handlers if the original keyboard handler is intact
  1086. (otherwise, they might have already toggled them). }
  1087. begin
  1088. {
  1089. void __maybe_fix_w2k_ntvdm_bug(void)
  1090. if (_osmajor == 5 && _get_dos_version(1) == 0x532) /* Windows NT, 2000 or XP? */
  1091. {
  1092. if(_stubinfo->size < STUBINFO_END) /* V2load'ed image, stubinfo PSP bad */
  1093. /* Protected mode call to SetPSP - uses BX from GetPSP (0x51) */
  1094. asm volatile("movb $0x51, %%ah \n\
  1095. int $0x21 \n\
  1096. movb $0x50, %%ah \n\
  1097. int $0x21 "
  1098. : : : "ax", "bx" ); /* output, input, regs */
  1099. else
  1100. /* Protected mode call to SetPSP - may destroy RM PSP if not extended */
  1101. asm volatile("movw %0, %%bx \n\
  1102. movb $0x50, %%ah \n\
  1103. int $0x21 "
  1104. : /* output */
  1105. : "g" (_stubinfo->psp_selector) /* input */
  1106. : "ax", "bx" ); /* regs */
  1107. }
  1108. }
  1109. if (exceptions_on) then
  1110. djgpp_exception_toggle;
  1111. _exception_exit:=nil;
  1112. _swap_in:=nil;
  1113. _swap_out:=nil;
  1114. __maybe_fix_w2k_ntvdm_bug;
  1115. { restore the FPU state }
  1116. dpmi_set_coprocessor_emulation(1);
  1117. end;
  1118. { _exit in dpmiexcp.c
  1119. is already present in v2prt0.as PM}
  1120. { used by dos.pp for swap vectors }
  1121. procedure dpmi_swap_in;[public,alias : 'swap_in'];
  1122. begin
  1123. if not (exceptions_on) then
  1124. djgpp_exception_toggle;
  1125. end;
  1126. procedure dpmi_swap_out;[public,alias : 'swap_out'];
  1127. begin
  1128. if (exceptions_on) then
  1129. djgpp_exception_toggle;
  1130. end;
  1131. var
  1132. ___djgpp_app_DS : word;external name '___djgpp_app_DS';
  1133. ___djgpp_our_DS : word;external name '___djgpp_our_DS';
  1134. __djgpp_sigint_mask : word;external name '___djgpp_sigint_mask';
  1135. __djgpp_sigint_key : word;external name '___djgpp_sigint_key';
  1136. __djgpp_sigquit_mask : word;external name '___djgpp_sigquit_mask';
  1137. __djgpp_sigquit_key : word;external name '___djgpp_sigquit_key';
  1138. { to avoid loading of C lib version of dpmiexcp
  1139. I need to have all exported assembler labels
  1140. of dpmiexcp.c in this unit.
  1141. DJGPP v2.03 add to new functions:
  1142. __djgpp_set_sigint_key
  1143. __djgpp_set_sigquit_key
  1144. that I implement here simply translating C code PM }
  1145. Const
  1146. LSHIFT = 1;
  1147. RSHIFT = 2;
  1148. CTRL = 4;
  1149. ALT = 8;
  1150. DEFAULT_SIGINT = $042e; { Ctrl-C: scan code 2Eh, kb status 04h }
  1151. DEFAULT_SIGQUIT = $042b; { Ctrl-\: scan code 2Bh, kb status 04h }
  1152. DEFAULT_SIGINT_98 = $042b; { Ctrl-C: scan code 2Bh, kb status 04h }
  1153. DEFAULT_SIGQUIT_98 = $040d; { Ctrl-\: scan code 0Dh, kb status 04h }
  1154. { Make it so the key NEW_KEY will generate the signal SIG.
  1155. NEW_KEY must include the keyboard status byte in bits 8-15 and the
  1156. scan code in bits 0-7. }
  1157. function set_signal_key(sig,new_key : longint) : longint;
  1158. type
  1159. pword = ^word;
  1160. var
  1161. old_key : longint;
  1162. mask,key : pword;
  1163. kb_status : word;
  1164. begin
  1165. if (sig = SIGINT) then
  1166. begin
  1167. mask := @__djgpp_sigint_mask;
  1168. key := @__djgpp_sigint_key;
  1169. end
  1170. else if (sig = SIGQUIT) then
  1171. begin
  1172. mask := @__djgpp_sigquit_mask;
  1173. key := @__djgpp_sigquit_key;
  1174. end
  1175. else
  1176. exit(-1);
  1177. old_key := key^;
  1178. key^ := new_key and $ffff;
  1179. kb_status := key^ shr 8;
  1180. mask^ := $f; { Alt, Ctrl and Shift bits only }
  1181. { Mask off the RShift bit unless they explicitly asked for it.
  1182. Our keyboard handler pretends that LShift is pressed when they
  1183. press RShift. }
  1184. if ((kb_status and RSHIFT) = 0) then
  1185. mask^ :=mask^ and not RSHIFT;
  1186. { Mask off the LShift bit if any of the Ctrl or Alt are set
  1187. since Shift doesn't matter when Ctrl and/or Alt are pressed. }
  1188. if (kb_status and (CTRL or ALT))<>0 then
  1189. mask^:= mask^ and not LSHIFT;
  1190. exit(old_key);
  1191. end;
  1192. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  1193. begin
  1194. __djgpp_set_sigint_key:=set_signal_key(SIGINT, new_key);
  1195. end;
  1196. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  1197. begin
  1198. __djgpp_set_sigquit_key:=set_signal_key(SIGQUIT, new_key);
  1199. end;
  1200. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  1201. var
  1202. fake_exception : texception_state;
  1203. begin
  1204. if (sig >= SIGABRT) and (sig <= SIGTRAP) then
  1205. begin
  1206. if djgpp_exception_state_ptr=nil then
  1207. begin
  1208. { This is a software signal, like SIGABRT or SIGKILL.
  1209. Fill the exception structure, so we get the traceback. }
  1210. djgpp_exception_state_ptr:=@fake_exception;
  1211. if (dpmi_setjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^)<>0) then
  1212. begin
  1213. errln('Bad longjmp to __djgpp_exception_state--aborting');
  1214. do_faulting_finish_message(true); { does not return }
  1215. end
  1216. else
  1217. { Fake the exception number. 7Ah is the last one hardwired
  1218. inside exceptn.S, for SIGQUIT. }
  1219. djgpp_exception_state_ptr^.__signum:=$7a + 1 + sig - SIGABRT;
  1220. end;
  1221. end;
  1222. print_signal_name(sig);
  1223. if assigned(djgpp_exception_state_ptr) then
  1224. { This exits, does not return. }
  1225. do_faulting_finish_message(djgpp_exception_state_ptr=@fake_exception);
  1226. __exit(-1);
  1227. __djgpp__traceback_exit:=0;
  1228. end;
  1229. procedure djgpp_int0;
  1230. begin
  1231. HandleError(200);
  1232. end;
  1233. procedure djgpp_exception_setup;
  1234. [public,alias : '___djgpp_exception_setup'];
  1235. var
  1236. temp_kbd,
  1237. temp_npx : pointer;
  1238. _except,
  1239. old_kbd : tseginfo;
  1240. locksize : longint;
  1241. i : longint;
  1242. begin
  1243. if assigned(_exception_exit) then
  1244. exit;
  1245. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1246. begin
  1247. __djgpp_set_sigint_key(DEFAULT_SIGINT);
  1248. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT);
  1249. end
  1250. else
  1251. begin { for PC98 }
  1252. __djgpp_set_sigint_key(DEFAULT_SIGINT_98);
  1253. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT_98);
  1254. end;
  1255. _exception_exit:=@dpmiexcp_exit;
  1256. _swap_in:=@dpmi_swap_in;
  1257. _swap_out:=@dpmi_swap_out;
  1258. { reset signals }
  1259. for i := 0 to SIGMAX do
  1260. signal_list[i] := SignalHandler(@SIG_DFL);
  1261. { app_DS only used when converting HW interrupts to exceptions }
  1262. asm
  1263. movw %ds,___djgpp_app_DS
  1264. movw %ds,___djgpp_our_DS
  1265. end;
  1266. djgpp_dos_sel:=dosmemselector;
  1267. { lock addresses which may see HW interrupts }
  1268. lock_code(@djgpp_hw_lock_start,@djgpp_hw_lock_end-@djgpp_hw_lock_start);
  1269. _except.segment:=get_cs;
  1270. { the first 18 exceptions start at offset +8 since exception
  1271. #18 and #19 had to be put in front of the table. }
  1272. _except.offset:=@djgpp_exception_table + 8;
  1273. for i:=0 to 17 do
  1274. begin
  1275. except_ori[i] := _except; { New value to set }
  1276. inc(_except.offset,4); { This is the size of push n, jmp }
  1277. end;
  1278. except_ori[18].segment := _except.segment;
  1279. except_ori[19].segment := _except.segment;
  1280. except_ori[18].offset := @djgpp_exception_table;
  1281. except_ori[19].offset := @djgpp_exception_table + 4;
  1282. kbd_ori.segment:=_except.segment;
  1283. npx_ori.segment:=_except.segment;
  1284. npx_ori.offset:=@djgpp_npx_hdlr;
  1285. int0_ori.segment:=_except.segment;
  1286. int0_ori.offset:=@djgpp_int0;
  1287. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1288. kbd_ori.offset:=@djgpp_kbd_hdlr
  1289. else
  1290. begin
  1291. kbd_ori.offset:=@djgpp_kbd_hdlr_pc98;
  1292. cbrk_vect := $06;
  1293. _except.offset:=@djgpp_iret;
  1294. set_pm_interrupt($23,_except);
  1295. end;
  1296. _except.offset:=@djgpp_i24;
  1297. set_pm_interrupt($24, _except);
  1298. get_pm_interrupt(9,djgpp_old_kbd);
  1299. djgpp_exception_toggle; { Set new values & save old values }
  1300. { get original video mode and save }
  1301. old_video_mode := farpeekb(dosmemselector, $449);
  1302. end;
  1303. {$endif CREATE_C_FUNCTIONS}
  1304. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  1305. begin
  1306. djgpp_set_ctrl_c:=(djgpp_hwint_flags and 1)=0;
  1307. if enable then
  1308. djgpp_hwint_flags:=djgpp_hwint_flags and (not 1)
  1309. else
  1310. djgpp_hwint_flags:=djgpp_hwint_flags or 1;
  1311. end;
  1312. {$ifdef CREATE_C_FUNCTIONS}
  1313. function c_djgpp_set_ctrl_c(enable : longint) : boolean;cdecl;[public,alias : '___djgpp_set_ctrl_c'];
  1314. begin
  1315. c_djgpp_set_ctrl_c:=djgpp_set_ctrl_c(boolean(enable));
  1316. end;
  1317. {$endif def CREATE_C_FUNCTIONS}
  1318. {$ifdef IN_DPMIEXCP_UNIT}
  1319. procedure ResetDefaultHandlers;
  1320. begin
  1321. Signal(SIGSEGV,@SIG_DFL);
  1322. Signal(SIGFPE,@SIG_DFL);
  1323. Signal(SIGNOFP,@SIG_DFL);
  1324. Signal(SIGTRAP,@SIG_DFL);
  1325. Signal(SIGTIMR,@SIG_DFL);
  1326. Signal(SIGINT,@SIG_DFL);
  1327. Signal(SIGQUIT,@SIG_DFL);
  1328. Signal(SIGILL,@SIG_DFL);
  1329. end;
  1330. {$endif IN_DPMIEXCP_UNIT}
  1331. procedure InitDPMIExcp;
  1332. begin
  1333. {$ifdef CREATE_C_FUNCTIONS}
  1334. djgpp_ds_alias:=v2prt0_ds_alias;
  1335. djgpp_exception_setup;
  1336. {$endif CREATE_C_FUNCTIONS}
  1337. end;
  1338. {$ifndef IN_SYSTEM}
  1339. begin
  1340. {$ifdef CREATE_C_FUNCTIONS}
  1341. InitDPMIExcp;
  1342. {$else not CREATE_C_FUNCTIONS}
  1343. ResetDefaultHandlers;
  1344. {$endif CREATE_C_FUNCTIONS}
  1345. end.
  1346. {$else IN_SYSTEM}
  1347. const
  1348. FPU_ControlWord : word = $1332;
  1349. function HandleException(sig : longint) : longint;
  1350. var
  1351. truesig : longint;
  1352. ErrorOfSig : longint;
  1353. FpuStatus,FPUControl : word;
  1354. eip,ebp : longint;
  1355. begin
  1356. if assigned(djgpp_exception_state_ptr) then
  1357. truesig:=djgpp_exception_state_ptr^.__signum
  1358. else
  1359. truesig:=sig;
  1360. ErrorOfSig:=0;
  1361. case truesig of
  1362. {exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (}
  1363. 0 : ErrorOfSig:=200; {'Division by Zero'}
  1364. 5 : ErrorOfSig:=201; {'Bounds Check'}
  1365. 12 : ErrorOfSig:=202; {'Stack Fault'}
  1366. 7, {'Coprocessor not available'}
  1367. 9, {'Coprocessor overrun'}
  1368. SIGNOFP : ErrorOfSig:=207;
  1369. 16,SIGFPE,$75 : begin
  1370. { This needs special handling }
  1371. { to discriminate between 205,206 and 207 }
  1372. if truesig=$75 then
  1373. fpustatus:=djgpp_exception_state_ptr^.__sigmask and $ffff
  1374. else
  1375. asm
  1376. fnstsw %ax
  1377. fnclex
  1378. movw %ax,fpustatus
  1379. end;
  1380. if (FpuStatus and FPU_Invalid)<>0 then
  1381. ErrorOfSig:=216
  1382. else if (FpuStatus and FPU_Denormal)<>0 then
  1383. ErrorOfSig:=216
  1384. else if (FpuStatus and FPU_DivisionByZero)<>0 then
  1385. ErrorOfSig:=200
  1386. else if (FpuStatus and FPU_Overflow)<>0 then
  1387. ErrorOfSig:=205
  1388. else if (FpuStatus and FPU_Underflow)<>0 then
  1389. ErrorOfSig:=206
  1390. else
  1391. ErrorOfSig:=207; {'Coprocessor Error'}
  1392. { if exceptions then Reset FPU and reload control word }
  1393. if (FPUStatus and FPU_ExceptionMask)<>0 then
  1394. asm
  1395. fninit
  1396. fldcw FPU_ControlWord
  1397. end;
  1398. end;
  1399. 4 : ErrorOfSig:=215; {'Overflow'}
  1400. 1, {'Debug'}
  1401. 2, {'NMI'}
  1402. 3, {'Breakpoint'}
  1403. 6, {'Invalid Opcode'}
  1404. 8, {'Double Fault'}
  1405. 10, {'Invalid TSS'}
  1406. 11, {'Segment Not Present'}
  1407. 13, {'General Protection Fault'}
  1408. 14, {'Page fault'}
  1409. 15, {' ',}
  1410. 17, {'Alignment Check',}
  1411. 18, {'Machine Check',}
  1412. 19, {'SSE FP error'}
  1413. SIGSEGV,SIGTRAP,SIGTIMR,SIGINT,SIGQUIT
  1414. : ErrorOfSig:=216;
  1415. end;
  1416. if assigned(djgpp_exception_state_ptr) then
  1417. Begin
  1418. if exception_level>0 then
  1419. dec(exception_level);
  1420. eip:=djgpp_exception_state_ptr^.__eip;
  1421. ebp:=djgpp_exception_state_ptr^.__ebp;
  1422. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  1423. HandleErrorAddrFrame(ErrorOfSig,pointer(eip),pointer(ebp));
  1424. End
  1425. else
  1426. { probably higher level is required }
  1427. HandleErrorFrame(ErrorOfSig,get_caller_frame(get_frame));
  1428. HandleException:=0;
  1429. end;
  1430. procedure InstallDefaultHandlers;
  1431. begin
  1432. Signal(SIGSEGV,@HandleException);
  1433. Signal(SIGFPE,@HandleException);
  1434. Signal(SIGNOFP,@HandleException);
  1435. Signal(SIGTRAP,@HandleException);
  1436. Signal(SIGTIMR,@HandleException);
  1437. Signal(SIGINT,@HandleException);
  1438. Signal(SIGQUIT,@HandleException);
  1439. Signal(SIGILL,@HandleException);
  1440. end;
  1441. {$endif IN_SYSTEM}