dpmiexcp.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1997-98 by Pierre Muller
  5. DPMI Exception routines for Go32V2
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. Unit DPMIExcp;
  13. { If linking to C code we must avoid loading of the dpmiexcp.o
  14. in libc.a from the equivalent C code
  15. => all global functions from dpmiexcp.c must be aliased PM
  16. Problem this is only valid for DJGPP v2.01 }
  17. interface
  18. uses
  19. go32;
  20. { No stack checking ! }
  21. {$S-}
  22. { Error Messages }
  23. function do_faulting_finish_message : integer;
  24. { SetJmp/LongJmp }
  25. type
  26. { must also contain exception_state !! }
  27. pdpmi_jmp_buf = ^dpmi_jmp_buf;
  28. dpmi_jmp_buf = packed record
  29. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  30. cs,ds,es,fs,gs,ss : word;
  31. sigmask : longint; { for POSIX signals only }
  32. signum : longint; { for expansion ie 386 exception number }
  33. exception_ptr : pdpmi_jmp_buf; { pointer to previous exception if exists }
  34. end;
  35. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  36. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  37. { Signals }
  38. const
  39. SIGABRT = 288;
  40. SIGFPE = 289;
  41. SIGILL = 290;
  42. SIGSEGV = 291;
  43. SIGTERM = 292;
  44. SIGALRM = 293;
  45. SIGHUP = 294;
  46. SIGINT = 295;
  47. SIGKILL = 296;
  48. SIGPIPE = 297;
  49. SIGQUIT = 298;
  50. SIGUSR1 = 299;
  51. SIGUSR2 = 300;
  52. SIGNOFP = 301;
  53. SIGTRAP = 302;
  54. SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
  55. SIGPROF = 304;
  56. SIGMAX = 320;
  57. SIG_BLOCK = 1;
  58. SIG_SETMASK = 2;
  59. SIG_UNBLOCK = 3;
  60. function SIG_DFL( x: longint) : longint;
  61. function SIG_ERR( x: longint) : longint;
  62. function SIG_IGN( x: longint) : longint;
  63. type
  64. SignalHandler = function (v : longint) : longint;
  65. PSignalHandler = SignalHandler; { to be compatible with linux.pp }
  66. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  67. function _raise(sig : longint) : longint;
  68. { Exceptions }
  69. type
  70. pexception_state = ^texception_state;
  71. texception_state = record
  72. __eax, __ebx, __ecx, __edx, __esi : longint;
  73. __edi, __ebp, __esp, __eip, __eflags : longint;
  74. __cs, __ds, __es, __fs, __gs, __ss : word;
  75. __sigmask : longint; { for POSIX signals only }
  76. __signum : longint; { for expansion }
  77. __exception_ptr : pexception_state; { pointer to previous exception }
  78. __fpu_state : array [0..108-1] of byte; { for future use }
  79. end;
  80. procedure djgpp_exception_toggle;
  81. procedure djgpp_exception_setup;
  82. function djgpp_exception_state : pexception_state;
  83. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  84. { Other }
  85. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  86. implementation
  87. {$ASMMODE DIRECT}
  88. {$L exceptn.o}
  89. var
  90. v2prt0_ds_alias : pointer;external name '___v2prt0_ds_alias';
  91. djgpp_ds_alias : pointer;external name '___djgpp_ds_alias';
  92. endtext : longint;external name '_etext';
  93. starttext : longint;external name 'start';
  94. djgpp_old_kbd : tseginfo;external name '___djgpp_old_kbd';
  95. djgpp_hw_lock_start : longint;external name '___djgpp_hw_lock_start';
  96. djgpp_hw_lock_end : longint;external name '___djgpp_hw_lock_end';
  97. djgpp_hwint_flags : longint;external name '___djgpp_hwint_flags';
  98. djgpp_dos_sel : word;external name '___djgpp_dos_sel';
  99. djgpp_exception_table : array[0..0] of pointer;external name '___djgpp_exception_table';
  100. procedure djgpp_i24;external name ' ___djgpp_i24';
  101. procedure djgpp_iret;external name ' ___djgpp_iret';
  102. procedure djgpp_npx_hdlr;external name '___djgpp_npx_hdlr';
  103. procedure djgpp_kbd_hdlr;external name '___djgpp_kbd_hdlr';
  104. procedure djgpp_kbd_hdlr_pc98;external name '___djgpp_kbd_hdlr_pc98';
  105. procedure djgpp_cbrk_hdlr;external name '___djgpp_cbrk_hdlr';
  106. var
  107. exceptions_on : boolean;
  108. old_int00 : tseginfo;cvar;external;
  109. old_int75 : tseginfo;cvar;external;
  110. const
  111. cbrk_vect : byte = $1b;
  112. exception_level : longint = 0;
  113. {****************************************************************************
  114. Helpers
  115. ****************************************************************************}
  116. procedure err(const x : string);
  117. begin
  118. write(stderr, x);
  119. end;
  120. procedure errln(const x : string);
  121. begin
  122. writeln(stderr, x);
  123. end;
  124. procedure itox(v,len : longint);
  125. var
  126. st : string;
  127. begin
  128. st:=hexstr(v,len);
  129. err(st);
  130. end;
  131. {****************************************************************************
  132. SetJmp/LongJmp
  133. ****************************************************************************}
  134. { function c_setjmp(var rec : dpmi_jmp_buf) : longint;cdecl;[public, alias : '_setjmp'];
  135. begin
  136. c_setjmp:=dpmi_setjmp(rec);
  137. end; }
  138. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  139. begin
  140. asm
  141. pushl %edi
  142. movl rec,%edi
  143. movl %eax,(%edi)
  144. movl %ebx,4(%edi)
  145. movl %ecx,8(%edi)
  146. movl %edx,12(%edi)
  147. movl %esi,16(%edi)
  148. { load edi }
  149. movl -4(%ebp),%eax
  150. { ... and store it }
  151. movl %eax,20(%edi)
  152. { ebp ... }
  153. movl (%ebp),%eax
  154. movl %eax,24(%edi)
  155. { esp ... }
  156. movl %esp,%eax
  157. addl $12,%eax
  158. movl %eax,28(%edi)
  159. { the return address }
  160. movl 4(%ebp),%eax
  161. movl %eax,32(%edi)
  162. { flags ... }
  163. pushfl
  164. popl 36(%edi)
  165. { !!!!! the segment registers, not yet needed }
  166. { you need them if the exception comes from
  167. an interrupt or a seg_move }
  168. movw %cs,40(%edi)
  169. movw %ds,42(%edi)
  170. movw %es,44(%edi)
  171. movw %fs,46(%edi)
  172. movw %gs,48(%edi)
  173. movw %ss,50(%edi)
  174. movl ___djgpp_exception_state_ptr, %eax
  175. movl %eax, 60(%edi)
  176. { restore EDI }
  177. pop %edi
  178. { we come from the initial call }
  179. xorl %eax,%eax
  180. movl %eax,__RESULT
  181. { leave USING RET inside CDECL functions is risky as
  182. some registers are pushed at entry
  183. ret $4 not anymore since cdecl !! }
  184. end;
  185. end;
  186. {procedure c_longjmp(var rec : dpmi_jmp_buf;return_value : longint);cdecl;[public, alias : '_longjmp'];
  187. begin
  188. dpmi_longjmp(rec,return_value);
  189. end; }
  190. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  191. begin
  192. if (@rec=pdpmi_jmp_buf(djgpp_exception_state)) and (exception_level>0) then
  193. dec(exception_level);
  194. asm
  195. { restore compiler shit }
  196. popl %ebp
  197. { copy from longjmp.S }
  198. movl 4(%esp),%edi { get dpmi_jmp_buf }
  199. movl 8(%esp),%eax { store retval in j->eax }
  200. movl %eax,0(%edi)
  201. movw 46(%edi),%fs
  202. movw 48(%edi),%gs
  203. movl 4(%edi),%ebx
  204. movl 8(%edi),%ecx
  205. movl 12(%edi),%edx
  206. movl 24(%edi),%ebp
  207. { Now for some uglyness. The dpmi_jmp_buf structure may be ABOVE the
  208. point on the new SS:ESP we are moving to. We don't allow overlap,
  209. but do force that it always be valid. We will use ES:ESI for
  210. our new stack before swapping to it. }
  211. movw 50(%edi),%es
  212. movl 28(%edi),%esi
  213. subl $28,%esi { We need 7 working longwords on stack }
  214. movl 60(%edi),%eax
  215. es
  216. movl %eax,(%esi) { Exception pointer }
  217. movzwl 42(%edi),%eax
  218. es
  219. movl %eax,4(%esi) { DS }
  220. movl 20(%edi),%eax
  221. es
  222. movl %eax,8(%esi) { EDI }
  223. movl 16(%edi),%eax
  224. es
  225. movl %eax,12(%esi) { ESI }
  226. movl 32(%edi),%eax
  227. es
  228. movl %eax,16(%esi) { EIP - start of IRET frame }
  229. movl 40(%edi),%eax
  230. es
  231. movl %eax,20(%esi) { CS }
  232. movl 36(%edi),%eax
  233. es
  234. movl %eax,24(%esi) { EFLAGS }
  235. movl 0(%edi),%eax
  236. movw 44(%edi),%es
  237. movw 50(%edi),%ss
  238. movl %esi,%esp
  239. popl ___djgpp_exception_state_ptr
  240. popl %ds
  241. popl %edi
  242. popl %esi
  243. iret { actually jump to new cs:eip loading flags }
  244. end;
  245. end;
  246. {****************************************************************************
  247. Signals
  248. ****************************************************************************}
  249. var
  250. signal_list : Array[0..SIGMAX] of SignalHandler;
  251. function SIG_ERR(x:longint):longint;
  252. begin
  253. SIG_ERR:=-1;
  254. end;
  255. function SIG_IGN(x:longint):longint;
  256. begin
  257. SIG_IGN:=-1;
  258. end;
  259. function SIG_DFL(x:longint):longint;
  260. begin
  261. SIG_DFL:=0;
  262. end;
  263. function signal(sig : longint;func : SignalHandler) : SignalHandler;
  264. var
  265. temp : SignalHandler;
  266. begin
  267. if ((sig <= 0) or (sig > SIGMAX) or (sig = SIGKILL)) then
  268. begin
  269. signal:=@SIG_ERR;
  270. runerror(201);
  271. end;
  272. temp := signal_list[sig - 1];
  273. signal_list[sig - 1] := func;
  274. signal:=temp;
  275. end;
  276. { C counter part }
  277. function c_signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;[public,alias : '_signal'];
  278. var
  279. temp : SignalHandler;
  280. begin
  281. temp:=signal(sig,func);
  282. c_signal:=temp;
  283. end;
  284. const
  285. signames : array [0..14] of string[4] = (
  286. 'ABRT','FPE ','ILL ','SEGV','TERM','ALRM','HUP ',
  287. 'INT ','KILL','PIPE','QUIT','USR1','USR2','NOFP','TRAP');
  288. function _raise(sig : longint) : longint;
  289. var
  290. temp : SignalHandler;
  291. label
  292. traceback_exit;
  293. begin
  294. if(sig <= 0) or (sig > SIGMAX) then
  295. exit(-1);
  296. temp:=signal_list[sig - 1];
  297. if (temp = SignalHandler(@SIG_IGN)) then
  298. exit(0);
  299. if (temp = SignalHandler(@SIG_DFL)) then
  300. begin
  301. traceback_exit:
  302. if ((sig >= SIGABRT) and (sig <= SIGTRAP)) then
  303. begin
  304. err('Exiting due to signal SIG');
  305. err(signames[sig-sigabrt]);
  306. end
  307. else
  308. begin
  309. err('Exiting due to signal $');
  310. itox(sig, 4);
  311. end;
  312. errln('');
  313. do_faulting_finish_message(); { Exits, does not return }
  314. exit(-1);
  315. end;
  316. { this is incompatible with dxegen-dxeload stuff PM }
  317. if ((cardinal(temp) < cardinal(@starttext)) or
  318. (cardinal(temp) > cardinal(@endtext))) then
  319. begin
  320. errln('Bad signal handler, ');
  321. goto traceback_exit;
  322. end;
  323. temp(sig);
  324. exit(0);
  325. end;
  326. function c_raise(sig : longint) : longint;cdecl;[public,alias : '_raise'];
  327. begin
  328. c_raise:=_raise(sig);
  329. end;
  330. {****************************************************************************
  331. Exceptions
  332. ****************************************************************************}
  333. function except_to_sig(excep : longint) : longint;
  334. begin
  335. case excep of
  336. 5,8,9,11,12,13,14 : exit(SIGSEGV);
  337. 0,4,16 : exit(SIGFPE);
  338. 1,3 : exit(SIGTRAP);
  339. 7 : exit(SIGNOFP);
  340. else
  341. begin
  342. case excep of
  343. $75 : exit(SIGFPE);
  344. $78 : exit(SIGTIMR);
  345. $1b,
  346. $79 : exit(SIGINT);
  347. else
  348. exit(SIGILL);
  349. end;
  350. end;
  351. end;
  352. end;
  353. procedure show_call_frame(djgpp_exception_state : pexception_state);
  354. begin
  355. errln('Call frame traceback EIPs:');
  356. errln(' 0x'+hexstr(djgpp_exception_state^.__eip, 8));
  357. dump_stack(djgpp_exception_state^.__ebp);
  358. end;
  359. const
  360. EXCEPTIONCOUNT = 18;
  361. exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (
  362. 'Division by Zero',
  363. 'Debug',
  364. 'NMI',
  365. 'Breakpoint',
  366. 'Overflow',
  367. 'Bounds Check',
  368. 'Invalid Opcode',
  369. 'Coprocessor not available',
  370. 'Double Fault',
  371. 'Coprocessor overrun',
  372. 'Invalid TSS',
  373. 'Segment Not Present',
  374. 'Stack Fault',
  375. 'General Protection Fault',
  376. 'Page fault',
  377. ' ',
  378. 'Coprocessor Error',
  379. 'Alignment Check');
  380. has_error : array [0..EXCEPTIONCOUNT-1] of byte =
  381. (0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1);
  382. cbrk_hooked : boolean = false;
  383. old_video_mode : byte = 3;
  384. procedure dump_selector(const name : string; sel : word);
  385. var
  386. base,limit : longint;
  387. begin
  388. err(name);
  389. err(': sel=');
  390. itox(sel, 4);
  391. if (sel<>0) then
  392. begin
  393. base:=get_segment_base_address(sel);
  394. err(' base='); itox(base, 8);
  395. limit:=get_segment_limit(sel);
  396. err(' limit='); itox(limit, 8);
  397. end;
  398. errln('');
  399. end;
  400. function farpeekb(sel : word;offset : longint) : byte;
  401. var
  402. b : byte;
  403. begin
  404. seg_move(sel,offset,get_ds,longint(@b),1);
  405. farpeekb:=b;
  406. end;
  407. function do_faulting_finish_message : integer;
  408. var
  409. en : pchar;
  410. signum,i : longint;
  411. old_vid : byte;
  412. begin
  413. do_faulting_finish_message:=0;
  414. signum:=djgpp_exception_state^.__signum;
  415. { check video mode for original here and reset (not if PC98) */ }
  416. if ((go32_info_block.linear_address_of_primary_screen <> $a0000) and
  417. (farpeekb(dosmemselector, $449) <> old_video_mode)) then
  418. begin
  419. old_vid:=old_video_mode;
  420. asm
  421. pusha
  422. movzbl old_vid,%eax
  423. int $0x10
  424. popa
  425. nop
  426. end;
  427. end;
  428. if (signum >= EXCEPTIONCOUNT) then
  429. begin
  430. case signum of
  431. $75 : en:='Floating Point exception';
  432. $1b : en:='Control-Break Pressed';
  433. $79 : en:='Control-C Pressed';
  434. else
  435. en:=nil;
  436. end;
  437. end
  438. else
  439. en:=exception_names[signum];
  440. if (en = nil) then
  441. begin
  442. err('Exception ');
  443. itox(signum, 2);
  444. err(' at eip=');
  445. itox(djgpp_exception_state^.__eip, 8);
  446. end
  447. else
  448. begin
  449. write(stderr, 'FPC ',en);
  450. err(' at eip=');
  451. itox(djgpp_exception_state^.__eip, 8);
  452. end;
  453. { Control-C should stop the program also !}
  454. {if (signum = $79) then
  455. begin
  456. errln('');
  457. exit(-1);
  458. end;}
  459. if ((signum < EXCEPTIONCOUNT) and (has_error[signum]=1)) then
  460. begin
  461. errorcode := djgpp_exception_state^.__sigmask and $ffff;
  462. if(errorcode<>0) then
  463. begin
  464. err(', error=');
  465. itox(errorcode, 4);
  466. end;
  467. end;
  468. errln('');
  469. err('eax=');
  470. itox(djgpp_exception_state^.__eax, 8);
  471. err(' ebx='); itox(djgpp_exception_state^.__ebx, 8);
  472. err(' ecx='); itox(djgpp_exception_state^.__ecx, 8);
  473. err(' edx='); itox(djgpp_exception_state^.__edx, 8);
  474. err(' esi='); itox(djgpp_exception_state^.__esi, 8);
  475. err(' edi='); itox(djgpp_exception_state^.__edi, 8);
  476. errln('');
  477. err('ebp='); itox(djgpp_exception_state^.__ebp, 8);
  478. err(' esp='); itox(djgpp_exception_state^.__esp, 8);
  479. err(' program=');
  480. errln(paramstr(0));
  481. dump_selector('cs', djgpp_exception_state^.__cs);
  482. dump_selector('ds', djgpp_exception_state^.__ds);
  483. dump_selector('es', djgpp_exception_state^.__es);
  484. dump_selector('fs', djgpp_exception_state^.__fs);
  485. dump_selector('gs', djgpp_exception_state^.__gs);
  486. dump_selector('ss', djgpp_exception_state^.__ss);
  487. errln('');
  488. if (djgpp_exception_state^.__cs = get_cs) then
  489. show_call_frame(djgpp_exception_state)
  490. {$ifdef SYSTEMDEBUG}
  491. else
  492. errln('Exception occured in another context');
  493. {$endif def SYSTEMDEBUG}
  494. ;
  495. if assigned(djgpp_exception_state^.__exception_ptr) then
  496. if (djgpp_exception_state^.__exception_ptr^.__cs = get_cs) then
  497. begin
  498. Errln('First exception level stack');
  499. show_call_frame(djgpp_exception_state^.__exception_ptr);
  500. end
  501. {$ifdef SYSTEMDEBUG}
  502. else
  503. errln('First exception occured in another context');
  504. {$endif def SYSTEMDEBUG}
  505. ;
  506. { must not return !! }
  507. if exceptions_on then
  508. djgpp_exception_toggle;
  509. asm
  510. pushw $1
  511. call ___exit
  512. end;
  513. end;
  514. function djgpp_exception_state:pexception_state;assembler;
  515. asm
  516. movl ___djgpp_exception_state_ptr,%eax
  517. end;
  518. procedure djgpp_exception_processor;[public,alias : '___djgpp_exception_processor'];
  519. var
  520. sig : longint;
  521. begin
  522. if not assigned(djgpp_exception_state^.__exception_ptr) then
  523. exception_level:=1
  524. else
  525. inc(exception_level);
  526. sig:=djgpp_exception_state^.__signum;
  527. if (exception_level=1) or (sig=$78) then
  528. begin
  529. sig := except_to_sig(sig);
  530. _raise(sig);
  531. if (djgpp_exception_state^.__signum >= EXCEPTIONCOUNT) then
  532. { Not exception so continue OK }
  533. dpmi_longjmp(pdpmi_jmp_buf(djgpp_exception_state)^, djgpp_exception_state^.__eax);
  534. { User handler did not exit or longjmp, we must exit }
  535. err('FPC cannot continue from exception, exiting due to signal ');
  536. itox(sig, 4);
  537. errln('');
  538. end
  539. else
  540. begin
  541. if exception_level>2 then
  542. begin
  543. errln('FPC triple exception, exiting !!! ');
  544. if (exceptions_on) then
  545. djgpp_exception_toggle;
  546. asm
  547. pushw $1
  548. call ___exit
  549. end;
  550. end;
  551. err('FPC double exception, exiting due to signal ');
  552. itox(sig, 4);
  553. errln('');
  554. end;
  555. do_faulting_finish_message;
  556. end;
  557. type
  558. trealseginfo = tseginfo;
  559. pseginfo = ^tseginfo;
  560. var
  561. except_ori : array [0..EXCEPTIONCOUNT-1] of tseginfo;
  562. {$ifdef SYSTEMDEBUG}
  563. export name '_ori_exceptions';
  564. {$endif def SYSTEMDEBUG}
  565. kbd_ori : tseginfo;
  566. npx_ori : tseginfo;
  567. cbrk_ori,
  568. cbrk_rmcb : trealseginfo;
  569. cbrk_regs : registers;
  570. procedure djgpp_exception_toggle;[alias : '___djgpp_exception_toggle'];
  571. var
  572. _except : tseginfo;
  573. i : longint;
  574. local_ex : boolean;
  575. begin
  576. {$ifdef SYSTEMDEBUG}
  577. if exceptions_on then
  578. errln('Disabling FPC exceptions')
  579. else
  580. errln('Enabling FPC exceptions');
  581. {$endif SYSTEMDEBUG}
  582. { toggle here to avoid infinite recursion }
  583. { if a subfunction calls runerror !! }
  584. exceptions_on:=not exceptions_on;
  585. local_ex:=exceptions_on;
  586. asm
  587. movzbl local_ex,%eax
  588. movl %eax,_v2prt0_exceptions_on
  589. end;
  590. for i:=0 to EXCEPTIONCOUNT-1 do
  591. begin
  592. if get_pm_exception_handler(i,_except) then
  593. begin
  594. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  595. begin
  596. if not set_pm_exception_handler(i,except_ori[i]) then
  597. errln('error setting exception nø'+hexstr(i,2));
  598. end;
  599. except_ori[i]:=_except;
  600. end
  601. else
  602. begin
  603. if get_exception_handler(i,_except) then
  604. begin
  605. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  606. begin
  607. if not set_exception_handler(i,except_ori[i]) then
  608. errln('error setting exception nø'+hexstr(i,2));
  609. end;
  610. except_ori[i]:=_except;
  611. end;
  612. end;
  613. end;
  614. get_pm_interrupt($75,_except);
  615. set_pm_interrupt($75,npx_ori);
  616. npx_ori:=_except;
  617. get_pm_interrupt(9,_except);
  618. set_pm_interrupt(9,kbd_ori);
  619. kbd_ori:=_except;
  620. if (cbrk_hooked) then
  621. begin
  622. set_rm_interrupt(cbrk_vect,cbrk_ori);
  623. free_rm_callback(cbrk_rmcb);
  624. cbrk_hooked := false;
  625. {$ifdef SYSTEMDEBUG}
  626. errln('back to ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  627. {$endif SYSTEMDEBUG}
  628. end
  629. else
  630. begin
  631. get_rm_interrupt(cbrk_vect, cbrk_ori);
  632. {$ifdef SYSTEMDEBUG}
  633. errln('ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  634. {$endif SYSTEMDEBUG}
  635. get_rm_callback(@djgpp_cbrk_hdlr, cbrk_regs, cbrk_rmcb);
  636. set_rm_interrupt(cbrk_vect, cbrk_rmcb);
  637. {$ifdef SYSTEMDEBUG}
  638. errln('now rm cbrk '+hexstr(cbrk_rmcb.segment,4)+':'+hexstr(longint(cbrk_rmcb.offset),4));
  639. {$endif SYSTEMDEBUG}
  640. cbrk_hooked := true;
  641. end;
  642. end;
  643. function dpmi_set_coprocessor_emulation(flag : longint) : longint;
  644. var
  645. res : longint;
  646. begin
  647. asm
  648. movl flag,%ebx
  649. movl $0xe01,%eax
  650. int $0x31
  651. jc .L_coproc_error
  652. xorl %eax,%eax
  653. .L_coproc_error:
  654. movl %eax,res
  655. end;
  656. dpmi_set_coprocessor_emulation:=res;
  657. end;
  658. procedure dpmiexcp_exit{(status : longint)};[public,alias : 'excep_exit'];
  659. { We need to restore hardware interrupt handlers even if somebody calls
  660. `_exit' directly, or else we crash the machine in nested programs.
  661. We only toggle the handlers if the original keyboard handler is intact
  662. (otherwise, they might have already toggled them). }
  663. begin
  664. if (exceptions_on) then
  665. djgpp_exception_toggle;
  666. asm
  667. xorl %eax,%eax
  668. movl %eax,_exception_exit
  669. movl %eax,_swap_in
  670. movl %eax,_swap_out
  671. end;
  672. { restore the FPU state }
  673. dpmi_set_coprocessor_emulation(1);
  674. end;
  675. { _exit in dpmiexcp.c
  676. is already present in v2prt0.as PM}
  677. { used by dos.pp for swap vectors }
  678. procedure dpmi_swap_in;[public,alias : 'swap_in'];
  679. begin
  680. if not (exceptions_on) then
  681. djgpp_exception_toggle;
  682. end;
  683. procedure dpmi_swap_out;[public,alias : 'swap_out'];
  684. begin
  685. if (exceptions_on) then
  686. djgpp_exception_toggle;
  687. end;
  688. procedure djgpp_exception_setup;[alias : '___djgpp_exception_setup'];
  689. var
  690. temp_kbd,
  691. temp_npx : pointer;
  692. _except,
  693. old_kbd : tseginfo;
  694. locksize : longint;
  695. i : longint;
  696. begin
  697. asm
  698. movl _exception_exit,%eax
  699. xorl %eax,%eax
  700. jne .L_already
  701. leal excep_exit,%eax
  702. movl %eax,_exception_exit
  703. leal swap_in,%eax
  704. movl %eax,_swap_in
  705. leal swap_out,%eax
  706. movl %eax,_swap_out
  707. end;
  708. { reset signals }
  709. for i := 0 to SIGMAX-1 do
  710. signal_list[i] := SignalHandler(@SIG_DFL);
  711. { app_DS only used when converting HW interrupts to exceptions }
  712. asm
  713. movw %ds,___djgpp_app_DS
  714. movw %ds,___djgpp_our_DS
  715. end;
  716. djgpp_dos_sel:=dosmemselector;
  717. { lock addresses which may see HW interrupts }
  718. lock_code(@djgpp_hw_lock_start,@djgpp_hw_lock_end-@djgpp_hw_lock_start);
  719. _except.segment:=get_cs;
  720. _except.offset:=@djgpp_exception_table;
  721. for i:=0 to ExceptionCount-1 do
  722. begin
  723. except_ori[i] := _except; { New value to set }
  724. inc(_except.offset,4); { This is the size of push n, jmp }
  725. end;
  726. kbd_ori.segment:=_except.segment;
  727. npx_ori.segment:=_except.segment;
  728. npx_ori.offset:=@djgpp_npx_hdlr;
  729. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  730. kbd_ori.offset:=@djgpp_kbd_hdlr
  731. else
  732. begin
  733. kbd_ori.offset:=@djgpp_kbd_hdlr_pc98;
  734. cbrk_vect := $06;
  735. _except.offset:=@djgpp_iret;
  736. set_pm_interrupt($23,_except);
  737. end;
  738. _except.offset:=@djgpp_i24;
  739. set_pm_interrupt($24, _except);
  740. get_pm_interrupt(9,djgpp_old_kbd);
  741. djgpp_exception_toggle; { Set new values & save old values }
  742. { get original video mode and save }
  743. old_video_mode := farpeekb(dosmemselector, $449);
  744. asm
  745. .L_already:
  746. end;
  747. end;
  748. function djgpp_set_ctrl_c(enable : boolean) : boolean;
  749. begin
  750. djgpp_set_ctrl_c:=(djgpp_hwint_flags and 1)=0;
  751. if enable then
  752. djgpp_hwint_flags:=djgpp_hwint_flags and (not 1)
  753. else
  754. djgpp_hwint_flags:=djgpp_hwint_flags or 1;
  755. end;
  756. function c_djgpp_set_ctrl_c(enable : longint) : boolean;cdecl;[public,alias : '___djgpp_set_ctrl_c'];
  757. begin
  758. c_djgpp_set_ctrl_c:=djgpp_set_ctrl_c(boolean(enable));
  759. end;
  760. procedure InitDPMIExcp;
  761. begin
  762. djgpp_ds_alias:=v2prt0_ds_alias;
  763. djgpp_exception_setup;
  764. end;
  765. begin
  766. InitDPMIExcp;
  767. end.
  768. {
  769. $Log$
  770. Revision 1.2 1998-12-21 14:23:12 pierre
  771. dpmiexcp.pp
  772. Revision 1.1 1998/12/21 13:07:02 peter
  773. * use -FE
  774. Revision 1.11 1998/11/17 09:42:50 pierre
  775. * position check of signal handler was wrong
  776. Revision 1.10 1998/10/13 21:42:42 peter
  777. * cleanup and use of external var
  778. * fixed ctrl-break crashes
  779. Revision 1.9 1998/08/20 08:08:36 pierre
  780. * dpmiexcp did not compile with older versions
  781. due to the proc to procvar bug
  782. * makefile separator problem fixed
  783. Revision 1.8 1998/08/19 10:56:33 pierre
  784. + added some special code for C interface
  785. to avoid loading of crt1.o or dpmiexcp.o from the libc.a
  786. Revision 1.7 1998/08/15 17:01:13 peter
  787. * smartlinking the units works now
  788. * setjmp/longjmp -> dmpi_setjmp/dpmi_longjmp to solve systemunit
  789. conflict
  790. Revision 1.6 1998/08/04 13:31:32 pierre
  791. * changed all FPK into FPC
  792. Revision 1.5 1998/07/08 12:02:19 carl
  793. * make it compiler under fpc v0995
  794. Revision 1.4 1998/06/26 08:19:08 pierre
  795. + all debug in ifdef SYSTEMDEBUG
  796. + added local arrays :
  797. opennames names of opened files
  798. fileopen boolean array to know if still open
  799. usefull with gdb if you get problems about too
  800. many open files !!
  801. Revision 1.3 1998/05/31 14:18:23 peter
  802. * force att or direct assembling
  803. * cleanup of some files
  804. Revision 1.2 1998/04/21 14:46:33 pierre
  805. + debug info better output
  806. no normal code changed
  807. }