dpmiexcp.pp 23 KB

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