dpmiexcp.pp 24 KB

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