dpmiexcp.pp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647
  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;cdecl;
  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;cdecl;
  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;cdecl;
  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;cdecl;
  109. PSignalHandler = ^SignalHandler; { to be compatible with linux.pp }
  110. function signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;
  111. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  112. function _raise(sig : longint) : longint;cdecl;
  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;cdecl;
  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;cdecl;
  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;cdecl;
  139. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  140. { Other }
  141. function dpmi_set_coprocessor_emulation(flag : longint) : longint;cdecl;
  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;cdecl;[public, alias : '_setjmp'];
  426. begin
  427. {$ifndef REGCALL}
  428. { here we need to be subtle :
  429. - we need to return with the arg still on the stack
  430. - but we also need to jmp to FPC_setjmp and not to call it
  431. because otherwise the return address is wrong !!
  432. For this we shift the return address down and
  433. duplicate the rec on stack }
  434. asm
  435. movl %ebp,%esp
  436. popl %ebp
  437. subl $8,%esp
  438. movl %eax,(%esp)
  439. movl 8(%esp),%eax
  440. movl %eax,4(%esp)
  441. movl 12(%esp),%eax
  442. movl %eax,8(%esp)
  443. popl %eax
  444. jmp dpmi_setjmp
  445. end;
  446. {$ELSE REGCALL}
  447. { this is easier with regcall convention
  448. because dpmi_setjmp expects rec arg in $eax }
  449. asm
  450. movl rec,%eax
  451. movl %ebp,%esp
  452. popl %ebp
  453. pushl %eax
  454. { stack is now:
  455. (%esp): saved eax
  456. 4(%esp): return addr
  457. 8(%esp): rec addr
  458. we need just
  459. (%esp): return addr }
  460. movl 4(%esp),%eax
  461. movl %eax,8(%esp)
  462. popl %eax
  463. addl $4,%esp
  464. jmp dpmi_setjmp
  465. end;
  466. {$ENDIF REGCALL}
  467. end;
  468. {$endif CREATE_C_FUNCTIONS}
  469. {$ifdef CREATE_C_FUNCTIONS}
  470. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  471. [public, alias : 'FPC_setjmp'];
  472. begin
  473. asm
  474. pushl %edi
  475. movl rec,%edi
  476. movl %eax,(%edi)
  477. movl %ebx,4(%edi)
  478. movl %ecx,8(%edi)
  479. movl %edx,12(%edi)
  480. movl %esi,16(%edi)
  481. {$ifndef REGCALL}
  482. { load edi }
  483. movl -4(%ebp),%eax
  484. {$ELSE REGCALL}
  485. { load edi }
  486. movl (%esp),%eax
  487. {$ENDIF REGCALL}
  488. { ... and store it }
  489. movl %eax,20(%edi)
  490. { ebp ... }
  491. movl (%ebp),%eax
  492. movl %eax,24(%edi)
  493. {$ifndef REGCALL}
  494. { esp ... }
  495. movl %esp,%eax
  496. addl $12,%eax
  497. {$ELSE REGCALL}
  498. { for esp, use ebp ... }
  499. movl %ebp,%eax
  500. addl $8,%eax
  501. {$ENDIF REGCALL}
  502. movl %eax,28(%edi)
  503. { the return address }
  504. movl 4(%ebp),%eax
  505. movl %eax,32(%edi)
  506. { flags ... }
  507. pushfl
  508. popl 36(%edi)
  509. { !!!!! the segment registers, not yet needed }
  510. { you need them if the exception comes from
  511. an interrupt or a seg_move }
  512. movw %cs,40(%edi)
  513. movw %ds,42(%edi)
  514. movw %es,44(%edi)
  515. movw %fs,46(%edi)
  516. movw %gs,48(%edi)
  517. movw %ss,50(%edi)
  518. movl djgpp_exception_state_ptr, %eax
  519. movl %eax, 60(%edi)
  520. { restore EDI }
  521. pop %edi
  522. { we come from the initial call }
  523. xorl %eax,%eax
  524. movl %eax,__RESULT
  525. { leave USING RET inside CDECL functions is risky as
  526. some registers are pushed at entry
  527. ret $4 not anymore since cdecl !! }
  528. end;
  529. end;
  530. {$endif CREATE_C_FUNCTIONS}
  531. {$ifdef CREATE_C_FUNCTIONS}
  532. procedure c_longjmp(var rec : dpmi_jmp_buf;return_value : longint);cdecl;[public, alias : '_longjmp'];
  533. begin
  534. dpmi_longjmp(rec,return_value);
  535. { never gets here !! so pascal stack convention is no problem }
  536. end;
  537. {$endif CREATE_C_FUNCTIONS}
  538. {$ifdef CREATE_C_FUNCTIONS}
  539. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  540. [public, alias : 'FPC_longjmp'];
  541. begin
  542. if (exception_level>0) then
  543. dec(exception_level);
  544. asm
  545. { copy from longjmp.S }
  546. { Adapted to avoid being sensitive to
  547. argument being on stack or in registers 2006-12-21 PM }
  548. movl rec,%edi { get dpmi_jmp_buf }
  549. movl return_value,%eax { store retval in j->eax }
  550. { restore compiler shit }
  551. popl %ebp
  552. movl %eax,0(%edi)
  553. movw 46(%edi),%fs
  554. movw 48(%edi),%gs
  555. movl 4(%edi),%ebx
  556. movl 8(%edi),%ecx
  557. movl 12(%edi),%edx
  558. movl 24(%edi),%ebp
  559. { Now for some uglyness. The dpmi_jmp_buf structure may be ABOVE the
  560. point on the new SS:ESP we are moving to. We don't allow overlap,
  561. but do force that it always be valid. We will use ES:ESI for
  562. our new stack before swapping to it. }
  563. movw 50(%edi),%es
  564. movl 28(%edi),%esi
  565. subl $28,%esi { We need 7 working longwords on stack }
  566. movl 60(%edi),%eax
  567. movl %eax,%es:(%esi) { Exception pointer }
  568. movzwl 42(%edi),%eax
  569. movl %eax,%es:4(%esi) { DS }
  570. movl 20(%edi),%eax
  571. movl %eax,%es:8(%esi) { EDI }
  572. movl 16(%edi),%eax
  573. movl %eax,%es:12(%esi) { ESI }
  574. movl 32(%edi),%eax
  575. movl %eax,%es:16(%esi) { EIP - start of IRET frame }
  576. movl 40(%edi),%eax
  577. movl %eax,%es:20(%esi) { CS }
  578. movl 36(%edi),%eax
  579. movl %eax,%es:24(%esi) { EFLAGS }
  580. movl 0(%edi),%eax
  581. movw 44(%edi),%es
  582. movw 50(%edi),%ss
  583. movl %esi,%esp
  584. popl djgpp_exception_state_ptr
  585. popl %ds
  586. popl %edi
  587. popl %esi
  588. iret { actually jump to new cs:eip loading flags }
  589. end;
  590. end;
  591. {$endif CREATE_C_FUNCTIONS}
  592. {****************************************************************************
  593. Signals
  594. ****************************************************************************}
  595. var
  596. signal_list : Array[0..SIGMAX] of SignalHandler;cvar;
  597. {$ifndef CREATE_C_FUNCTIONS}external;{$else}public;{$endif}
  598. {$ifdef CREATE_C_FUNCTIONS}
  599. function SIG_ERR(x:longint):longint;cdecl;[public,alias : '___djgpp_SIG_ERR'];
  600. begin
  601. SIG_ERR:=-1;
  602. end;
  603. function SIG_IGN(x:longint):longint;cdecl;[public,alias : '___djgpp_SIG_IGN'];
  604. begin
  605. SIG_IGN:=-1;
  606. end;
  607. function SIG_DFL(x:longint):longint;cdecl;[public,alias : '___djgpp_SIG_DFL'];
  608. begin
  609. SIG_DFL:=0;
  610. end;
  611. {$endif CREATE_C_FUNCTIONS}
  612. function signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;
  613. var
  614. temp : SignalHandler;
  615. begin
  616. if ((sig < 0) or (sig > SIGMAX) or (sig = SIGKILL)) then
  617. begin
  618. signal:=@SIG_ERR;
  619. runerror(201);
  620. end;
  621. temp := signal_list[sig];
  622. signal_list[sig] := func;
  623. signal:=temp;
  624. end;
  625. {$ifdef CREATE_C_FUNCTIONS}
  626. { C counter part }
  627. function c_signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;[public,alias : '_signal'];
  628. var
  629. temp : SignalHandler;
  630. begin
  631. temp:=signal(sig,func);
  632. c_signal:=temp;
  633. end;
  634. {$endif CREATE_C_FUNCTIONS}
  635. const
  636. signames : array [0..14] of string[4] = (
  637. 'ABRT','FPE ','ILL ','SEGV','TERM','ALRM','HUP ',
  638. 'INT ','KILL','PIPE','QUIT','USR1','USR2','NOFP','TRAP');
  639. procedure print_signal_name(sig : longint);
  640. begin
  641. if ((sig >= SIGABRT) and (sig <= SIGTRAP)) then
  642. begin
  643. err('Exiting due to signal SIG');
  644. err(signames[sig-sigabrt]);
  645. end
  646. else
  647. begin
  648. err('Exiting due to signal $');
  649. itox(sig, 4);
  650. end;
  651. errln('');
  652. end;
  653. function _raise(sig : longint) : longint;cdecl;
  654. var
  655. temp : SignalHandler;
  656. begin
  657. if(sig < 0) or (sig > SIGMAX) then
  658. exit(-1);
  659. temp:=signal_list[sig];
  660. if (temp = SignalHandler(@SIG_IGN)) then
  661. exit(0);
  662. if (temp = SignalHandler(@SIG_DFL)) then
  663. begin
  664. print_signal_name(sig);
  665. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  666. exit(-1);
  667. end;
  668. { this is incompatible with dxegen-dxeload stuff PM }
  669. if ((cardinal(temp) < cardinal(@starttext)) or
  670. (cardinal(temp) > cardinal(@endtext))) then
  671. begin
  672. errln('Bad signal handler, ');
  673. print_signal_name(sig);
  674. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  675. exit(-1);
  676. end;
  677. { WARNING !!! temp can be a pascal or a C
  678. function... thus %esp can be modified here !!!
  679. This might be dangerous for some optimizations ?? PM }
  680. temp(sig);
  681. exit(0);
  682. end;
  683. {$ifdef CREATE_C_FUNCTIONS}
  684. function c_raise(sig : longint) : longint;cdecl;[public,alias : '_raise'];
  685. begin
  686. c_raise:=_raise(sig);
  687. end;
  688. {$endif CREATE_C_FUNCTIONS}
  689. {****************************************************************************
  690. Exceptions
  691. ****************************************************************************}
  692. var
  693. ___djgpp_selector_limit: cardinal; external name '___djgpp_selector_limit';
  694. {$ifdef CREATE_C_FUNCTIONS}
  695. {$ifdef IN_DPMIEXCP_UNIT}
  696. procedure __exit(c:longint);cdecl;external;
  697. {$endif}
  698. function except_to_sig(excep : longint) : longint;
  699. begin
  700. case excep of
  701. 5,8,9,11,12,13,14,
  702. 18, 19 : exit(SIGSEGV);
  703. 0,4,16 : exit(SIGFPE);
  704. 1,3 : exit(SIGTRAP);
  705. 7 : exit(SIGNOFP);
  706. else
  707. begin
  708. case excep of
  709. $75 : exit(SIGFPE);
  710. $78 : exit(SIGTIMR);
  711. $1b,
  712. $79 : exit(SIGINT);
  713. $7a : exit(SIGQUIT);
  714. else
  715. exit(SIGILL);
  716. end;
  717. end;
  718. end;
  719. end;
  720. procedure show_call_frame(djgpp_exception_state : pexception_state);
  721. begin
  722. errln('Call frame traceback EIPs:');
  723. errln(BackTraceStrFunc(Pointer(djgpp_exception_state^.__eip)));
  724. dump_stack(stderr,Pointer(djgpp_exception_state^.__ebp));
  725. end;
  726. const
  727. EXCEPTIONCOUNT = 20;
  728. exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (
  729. 'Division by Zero',
  730. 'Debug',
  731. 'NMI',
  732. 'Breakpoint',
  733. 'Overflow',
  734. 'Bounds Check',
  735. 'Invalid Opcode',
  736. 'Coprocessor not available',
  737. 'Double Fault',
  738. 'Coprocessor overrun',
  739. 'Invalid TSS',
  740. 'Segment Not Present',
  741. 'Stack Fault',
  742. 'General Protection Fault',
  743. 'Page fault',
  744. ' ',
  745. 'Coprocessor Error',
  746. 'Alignment Check',
  747. 'Machine check',
  748. 'SIMD FP Error');
  749. has_error : array [0..EXCEPTIONCOUNT-1] of byte =
  750. (0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,0,0);
  751. cbrk_hooked : boolean = false;
  752. old_video_mode : byte = 3;
  753. procedure dump_selector(const name : string; sel : word);
  754. var
  755. base,limit : longint;
  756. begin
  757. err(name);
  758. err(': sel=');
  759. itox(sel, 4);
  760. if (sel<>0) then
  761. begin
  762. base:=get_segment_base_address(sel);
  763. err(' base='); itox(base, 8);
  764. limit:=get_segment_limit(sel);
  765. err(' limit='); itox(limit, 8);
  766. end;
  767. errln('');
  768. end;
  769. function farpeekb(sel : word;offset : longint) : byte;
  770. var
  771. b : byte;
  772. begin
  773. {$ifdef IN_DPMIEXCP_UNIT}
  774. seg_move(sel,offset,get_ds,longint(@b),1);
  775. {$else not IN_DPMIEXCP_UNIT}
  776. sysseg_move(sel,offset,get_ds,longint(@b),1);
  777. {$endif IN_DPMIEXCP_UNIT}
  778. farpeekb:=b;
  779. end;
  780. const message_level : byte = 0;
  781. function do_faulting_finish_message(fake : boolean) : integer;cdecl;
  782. public;
  783. var
  784. en : pchar;
  785. signum,i : longint;
  786. old_vid : byte;
  787. label
  788. simple_exit;
  789. function _my_cs: word; assembler;
  790. asm
  791. movw %cs,%ax
  792. end;
  793. begin
  794. inc(message_level);
  795. if message_level>2 then
  796. goto simple_exit;
  797. do_faulting_finish_message:=0;
  798. signum:=djgpp_exception_state_ptr^.__signum;
  799. { check video mode for original here and reset (not if PC98) }
  800. if ((go32_info_block.linear_address_of_primary_screen <> $a0000) and
  801. (farpeekb(dosmemselector, $449) <> old_video_mode)) then
  802. begin
  803. old_vid:=old_video_mode;
  804. asm
  805. pusha
  806. movzbl old_vid,%eax
  807. int $0x10
  808. popa
  809. nop
  810. end;
  811. end;
  812. if (signum >= EXCEPTIONCOUNT) then
  813. begin
  814. case signum of
  815. $75 : en:='Floating Point exception';
  816. $1b : en:='Control-Break Pressed';
  817. $79 : en:='Control-C Pressed';
  818. $7a : en:='QUIT key Pressed'
  819. else
  820. en:=nil;
  821. end;
  822. end
  823. else
  824. en:=exception_names[signum];
  825. if (en = nil) then
  826. begin
  827. if fake then
  828. err('Raised ')
  829. else
  830. err('Exception ');
  831. itox(signum, 2);
  832. err(' at eip=');
  833. (* For fake exceptions like SIGABRT report where `raise' was called. *)
  834. if fake and (djgpp_exception_state_ptr^.__cs = _my_cs)
  835. and (djgpp_exception_state_ptr^.__ebp >= djgpp_exception_state_ptr^.__esp)
  836. and (djgpp_exception_state_ptr^.__ebp >= endtext)
  837. and (djgpp_exception_state_ptr^.__ebp < ___djgpp_selector_limit) then
  838. itox(djgpp_exception_state_ptr^.__ebp + 1, 8)
  839. else
  840. itox(djgpp_exception_state_ptr^.__eip, 8);
  841. end
  842. else
  843. begin
  844. write(stderr, 'FPC ',en);
  845. err(' at eip=');
  846. itox(djgpp_exception_state_ptr^.__eip, 8);
  847. end;
  848. { Control-C should stop the program also !}
  849. {if (signum = $79) then
  850. begin
  851. errln('');
  852. exit(-1);
  853. end;}
  854. if ((signum < EXCEPTIONCOUNT) and (has_error[signum]=1)) then
  855. begin
  856. errorcode := djgpp_exception_state_ptr^.__sigmask and $ffff;
  857. if(errorcode<>0) then
  858. begin
  859. err(', error=');
  860. itox(errorcode, 4);
  861. end;
  862. end;
  863. errln('');
  864. err('eax=');
  865. itox(djgpp_exception_state_ptr^.__eax, 8);
  866. err(' ebx='); itox(djgpp_exception_state_ptr^.__ebx, 8);
  867. err(' ecx='); itox(djgpp_exception_state_ptr^.__ecx, 8);
  868. err(' edx='); itox(djgpp_exception_state_ptr^.__edx, 8);
  869. err(' esi='); itox(djgpp_exception_state_ptr^.__esi, 8);
  870. err(' edi='); itox(djgpp_exception_state_ptr^.__edi, 8);
  871. errln('');
  872. err('ebp='); itox(djgpp_exception_state_ptr^.__ebp, 8);
  873. err(' esp='); itox(djgpp_exception_state_ptr^.__esp, 8);
  874. err(' program=');
  875. errln(paramstr(0));
  876. dump_selector('cs', djgpp_exception_state_ptr^.__cs);
  877. dump_selector('ds', djgpp_exception_state_ptr^.__ds);
  878. dump_selector('es', djgpp_exception_state_ptr^.__es);
  879. dump_selector('fs', djgpp_exception_state_ptr^.__fs);
  880. dump_selector('gs', djgpp_exception_state_ptr^.__gs);
  881. dump_selector('ss', djgpp_exception_state_ptr^.__ss);
  882. errln('');
  883. if (djgpp_exception_state_ptr^.__cs = get_cs) then
  884. show_call_frame(djgpp_exception_state_ptr)
  885. {$ifdef DPMIEXCP_DEBUG}
  886. else
  887. errln('Exception occured in another context');
  888. {$endif def DPMIEXCP_DEBUG}
  889. ;
  890. if assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  891. if (djgpp_exception_state_ptr^.__exception_ptr^.__cs = get_cs) then
  892. begin
  893. Errln('First exception level stack');
  894. show_call_frame(djgpp_exception_state_ptr^.__exception_ptr);
  895. end
  896. {$ifdef DPMIEXCP_DEBUG}
  897. else
  898. begin
  899. errln('First exception occured in another context');
  900. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  901. do_faulting_finish_message(false);
  902. end;
  903. {$endif def DPMIEXCP_DEBUG}
  904. ;
  905. { must not return !! }
  906. simple_exit:
  907. if exceptions_on then
  908. djgpp_exception_toggle;
  909. __exit(-1);
  910. end;
  911. {$endif CREATE_C_FUNCTIONS}
  912. function djgpp_exception_state:pexception_state;assembler;
  913. asm
  914. movl djgpp_exception_state_ptr,%eax
  915. end;
  916. {$ifdef CREATE_C_FUNCTIONS}
  917. var
  918. _os_trueversion : word;external name '__os_trueversion';
  919. procedure djgpp_exception_processor;cdecl;[public,alias : '___djgpp_exception_processor'];
  920. var
  921. sig : longint;
  922. begin
  923. if not assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  924. exception_level:=1
  925. else
  926. inc(exception_level);
  927. sig:=djgpp_exception_state_ptr^.__signum;
  928. if (exception_level=1) or (sig=$78) then
  929. begin
  930. sig := except_to_sig(sig);
  931. if signal_list[djgpp_exception_state_ptr^.__signum]
  932. <>SignalHandler(@SIG_DFL) then
  933. _raise(djgpp_exception_state_ptr^.__signum)
  934. else
  935. _raise(sig);
  936. if (djgpp_exception_state_ptr^.__signum >= EXCEPTIONCOUNT) then
  937. { Not exception so continue OK }
  938. dpmi_longjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^, djgpp_exception_state_ptr^.__eax);
  939. { User handler did not exit or longjmp, we must exit }
  940. err('FPC cannot continue from exception, exiting due to signal ');
  941. itox(sig, 4);
  942. errln('');
  943. end
  944. else
  945. begin
  946. if exception_level>2 then
  947. begin
  948. if exception_level=3 then
  949. errln('FPC triple exception, exiting !!! ');
  950. if (exceptions_on) then
  951. djgpp_exception_toggle;
  952. __exit(1);
  953. end;
  954. err('FPC double exception, exiting due to signal ');
  955. itox(sig, 4);
  956. errln('');
  957. end;
  958. do_faulting_finish_message(djgpp_exception_state<>nil);
  959. end;
  960. type
  961. trealseginfo = tseginfo;
  962. pseginfo = ^tseginfo;
  963. var
  964. except_ori : array [0..EXCEPTIONCOUNT-1] of tseginfo;
  965. {$ifdef DPMIEXCP_DEBUG}
  966. export name '_ori_exceptions';
  967. {$endif def DPMIEXCP_DEBUG}
  968. kbd_ori : tseginfo;
  969. int0_ori,
  970. npx_ori : tseginfo;
  971. cbrk_ori,
  972. cbrk_rmcb : trealseginfo;
  973. cbrk_regs : trealregs;
  974. v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  975. procedure djgpp_exception_toggle;cdecl;
  976. [public,alias : '___djgpp_exception_toggle'];
  977. var
  978. _except : tseginfo;
  979. i : longint;
  980. begin
  981. {$ifdef DPMIEXCP_DEBUG}
  982. if exceptions_on then
  983. errln('Disabling FPC exceptions')
  984. else
  985. errln('Enabling FPC exceptions');
  986. {$endif DPMIEXCP_DEBUG}
  987. { toggle here to avoid infinite recursion }
  988. { if a subfunction calls runerror !! }
  989. exceptions_on:=not exceptions_on;
  990. v2prt0_exceptions_on:=exceptions_on;
  991. { Exceptions 18 and 19 settings generates a bug in
  992. the DJGPP debug code PM }
  993. for i:=0 to 17{EXCEPTIONCOUNT-1} do
  994. begin
  995. {$ifdef DPMIEXCP_DEBUG}
  996. errln('new exception '+hexstr(i,2)+' '+hexstr(except_ori[i].segment,4)+':'+hexstr(longint(except_ori[i].offset),8));
  997. {$endif DPMIEXCP_DEBUG}
  998. { Windows 2000 seems to not set carryflag on func 0x210 :( PM }
  999. if (_os_trueversion <> $532) and get_pm_exception_handler(i,_except) then
  1000. begin
  1001. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  1002. begin
  1003. {$ifdef DPMIEXCP_DEBUG}
  1004. errln('Using DPMI 1.0 functions');
  1005. {$endif DPMIEXCP_DEBUG}
  1006. if not set_pm_exception_handler(i,except_ori[i]) then
  1007. errln('error setting exception nø'+hexstr(i,2));
  1008. end;
  1009. except_ori[i]:=_except;
  1010. end
  1011. else
  1012. begin
  1013. if get_exception_handler(i,_except) then
  1014. begin
  1015. {$ifdef DPMIEXCP_DEBUG}
  1016. errln('Using DPMI 0.9 functions');
  1017. {$endif DPMIEXCP_DEBUG}
  1018. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  1019. begin
  1020. if not set_exception_handler(i,except_ori[i]) then
  1021. errln('error setting exception nø'+hexstr(i,2));
  1022. end;
  1023. except_ori[i]:=_except;
  1024. end;
  1025. end;
  1026. {$ifdef DPMIEXCP_DEBUG}
  1027. errln('prev exception '+hexstr(i,2)+' '+hexstr(_except.segment,4)+':'+hexstr(longint(_except.offset),8));
  1028. {$endif DPMIEXCP_DEBUG}
  1029. end;
  1030. get_pm_interrupt($75,_except);
  1031. set_pm_interrupt($75,npx_ori);
  1032. npx_ori:=_except;
  1033. get_pm_interrupt($0,_except);
  1034. set_pm_interrupt($0,int0_ori);
  1035. int0_ori:=_except;
  1036. get_pm_interrupt(9,_except);
  1037. set_pm_interrupt(9,kbd_ori);
  1038. kbd_ori:=_except;
  1039. if (cbrk_hooked) then
  1040. begin
  1041. set_rm_interrupt(cbrk_vect,cbrk_ori);
  1042. free_rm_callback(cbrk_rmcb);
  1043. cbrk_hooked := false;
  1044. {$ifdef DPMIEXCP_DEBUG}
  1045. errln('back to ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  1046. {$endif DPMIEXCP_DEBUG}
  1047. end
  1048. else
  1049. begin
  1050. get_rm_interrupt(cbrk_vect, cbrk_ori);
  1051. {$ifdef DPMIEXCP_DEBUG}
  1052. errln('ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  1053. {$endif DPMIEXCP_DEBUG}
  1054. get_rm_callback(@djgpp_cbrk_hdlr, cbrk_regs, cbrk_rmcb);
  1055. set_rm_interrupt(cbrk_vect, cbrk_rmcb);
  1056. {$ifdef DPMIEXCP_DEBUG}
  1057. errln('now rm cbrk '+hexstr(cbrk_rmcb.segment,4)+':'+hexstr(longint(cbrk_rmcb.offset),4));
  1058. {$endif DPMIEXCP_DEBUG}
  1059. cbrk_hooked := true;
  1060. end;
  1061. end;
  1062. {$endif CREATE_C_FUNCTIONS}
  1063. function dpmi_set_coprocessor_emulation(flag : longint) : longint;cdecl;
  1064. var
  1065. res : longint;
  1066. begin
  1067. asm
  1068. pushl %ebx
  1069. movl flag,%ebx
  1070. movl $0xe01,%eax
  1071. int $0x31
  1072. jc .L_coproc_error
  1073. xorl %eax,%eax
  1074. .L_coproc_error:
  1075. movl %eax,res
  1076. popl %ebx
  1077. end;
  1078. dpmi_set_coprocessor_emulation:=res;
  1079. end;
  1080. {$ifdef CREATE_C_FUNCTIONS}
  1081. var
  1082. _swap_in : pointer;external name '_swap_in';
  1083. _swap_out : pointer;external name '_swap_out';
  1084. _exception_exit : pointer;external name '_exception_exit';
  1085. const
  1086. STUBINFO_END = $54;
  1087. procedure __maybe_fix_w2k_ntvdm_bug;cdecl;[public,alias : '___maybe_fix_w2k_ntvdm_bug'];
  1088. var
  1089. psp_sel : word;
  1090. begin
  1091. if _os_trueversion = $532 then
  1092. begin
  1093. { avoid NTVDM bug on NT,2000 or XP }
  1094. { see dpmiexcp.c source of DJGPP PM }
  1095. if stub_info^.size < STUBINFO_END then
  1096. begin
  1097. asm
  1098. movb $0x51,%ah
  1099. int $0x21
  1100. movb $0x50,%ah
  1101. int $0x21
  1102. end;
  1103. end
  1104. else
  1105. begin
  1106. psp_sel:=stub_info^.psp_selector;
  1107. asm
  1108. pushl %ebx
  1109. movw psp_sel,%bx
  1110. movb $0x50,%ah
  1111. int $0x21
  1112. popl %ebx
  1113. end;
  1114. end;
  1115. end;
  1116. end;
  1117. procedure dpmiexcp_exit{(status : longint)};cdecl;[public,alias : 'excep_exit'];
  1118. { We need to restore hardware interrupt handlers even if somebody calls
  1119. `_exit' directly, or else we crash the machine in nested programs.
  1120. We only toggle the handlers if the original keyboard handler is intact
  1121. (otherwise, they might have already toggled them). }
  1122. begin
  1123. (*
  1124. void __maybe_fix_w2k_ntvdm_bug(void)
  1125. if (_osmajor == 5 && _get_dos_version(1) == 0x532) /* Windows NT, 2000 or XP? */
  1126. {
  1127. if(_stubinfo->size < STUBINFO_END) /* V2load'ed image, stubinfo PSP bad */
  1128. /* Protected mode call to SetPSP - uses BX from GetPSP (0x51) */
  1129. asm volatile("movb $0x51, %%ah \n\
  1130. int $0x21 \n\
  1131. movb $0x50, %%ah \n\
  1132. int $0x21 "
  1133. : : : "ax", "bx" ); /* output, input, regs */
  1134. else
  1135. /* Protected mode call to SetPSP - may destroy RM PSP if not extended */
  1136. asm volatile("movw %0, %%bx \n\
  1137. movb $0x50, %%ah \n\
  1138. int $0x21 "
  1139. : /* output */
  1140. : "g" (_stubinfo->psp_selector) /* input */
  1141. : "ax", "bx" ); /* regs */
  1142. }
  1143. *)
  1144. if (exceptions_on) then
  1145. djgpp_exception_toggle;
  1146. _exception_exit:=nil;
  1147. _swap_in:=nil;
  1148. _swap_out:=nil;
  1149. __maybe_fix_w2k_ntvdm_bug;
  1150. { restore the FPU state }
  1151. dpmi_set_coprocessor_emulation(1);
  1152. end;
  1153. { _exit in dpmiexcp.c
  1154. is already present in v2prt0.as PM}
  1155. { used by dos.pp for swap vectors }
  1156. procedure dpmi_swap_in;cdecl;[public,alias : 'swap_in'];
  1157. begin
  1158. if not (exceptions_on) then
  1159. djgpp_exception_toggle;
  1160. end;
  1161. procedure dpmi_swap_out;cdecl;[public,alias : 'swap_out'];
  1162. begin
  1163. if (exceptions_on) then
  1164. djgpp_exception_toggle;
  1165. end;
  1166. var
  1167. ___djgpp_app_DS : word;external name '___djgpp_app_DS';
  1168. ___djgpp_our_DS : word;external name '___djgpp_our_DS';
  1169. __djgpp_sigint_mask : word;external name '___djgpp_sigint_mask';
  1170. __djgpp_sigint_key : word;external name '___djgpp_sigint_key';
  1171. __djgpp_sigquit_mask : word;external name '___djgpp_sigquit_mask';
  1172. __djgpp_sigquit_key : word;external name '___djgpp_sigquit_key';
  1173. { to avoid loading of C lib version of dpmiexcp
  1174. I need to have all exported assembler labels
  1175. of dpmiexcp.c in this unit.
  1176. DJGPP v2.03 add to new functions:
  1177. __djgpp_set_sigint_key
  1178. __djgpp_set_sigquit_key
  1179. that I implement here simply translating C code PM }
  1180. Const
  1181. LSHIFT = 1;
  1182. RSHIFT = 2;
  1183. CTRL = 4;
  1184. ALT = 8;
  1185. DEFAULT_SIGINT = $042e; { Ctrl-C: scan code 2Eh, kb status 04h }
  1186. DEFAULT_SIGQUIT = $042b; { Ctrl-\: scan code 2Bh, kb status 04h }
  1187. DEFAULT_SIGINT_98 = $042b; { Ctrl-C: scan code 2Bh, kb status 04h }
  1188. DEFAULT_SIGQUIT_98 = $040d; { Ctrl-\: scan code 0Dh, kb status 04h }
  1189. { Make it so the key NEW_KEY will generate the signal SIG.
  1190. NEW_KEY must include the keyboard status byte in bits 8-15 and the
  1191. scan code in bits 0-7. }
  1192. function set_signal_key(sig,new_key : longint) : longint;
  1193. type
  1194. pword = ^word;
  1195. var
  1196. old_key : longint;
  1197. mask,key : pword;
  1198. kb_status : word;
  1199. begin
  1200. if (sig = SIGINT) then
  1201. begin
  1202. mask := @__djgpp_sigint_mask;
  1203. key := @__djgpp_sigint_key;
  1204. end
  1205. else if (sig = SIGQUIT) then
  1206. begin
  1207. mask := @__djgpp_sigquit_mask;
  1208. key := @__djgpp_sigquit_key;
  1209. end
  1210. else
  1211. exit(-1);
  1212. old_key := key^;
  1213. key^ := new_key and $ffff;
  1214. kb_status := key^ shr 8;
  1215. mask^ := $f; { Alt, Ctrl and Shift bits only }
  1216. { Mask off the RShift bit unless they explicitly asked for it.
  1217. Our keyboard handler pretends that LShift is pressed when they
  1218. press RShift. }
  1219. if ((kb_status and RSHIFT) = 0) then
  1220. mask^ :=mask^ and not RSHIFT;
  1221. { Mask off the LShift bit if any of the Ctrl or Alt are set
  1222. since Shift doesn't matter when Ctrl and/or Alt are pressed. }
  1223. if (kb_status and (CTRL or ALT))<>0 then
  1224. mask^:= mask^ and not LSHIFT;
  1225. exit(old_key);
  1226. end;
  1227. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  1228. begin
  1229. __djgpp_set_sigint_key:=set_signal_key(SIGINT, new_key);
  1230. end;
  1231. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  1232. begin
  1233. __djgpp_set_sigquit_key:=set_signal_key(SIGQUIT, new_key);
  1234. end;
  1235. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  1236. var
  1237. fake_exception : texception_state;
  1238. begin
  1239. if (sig >= SIGABRT) and (sig <= SIGTRAP) then
  1240. begin
  1241. if djgpp_exception_state_ptr=nil then
  1242. begin
  1243. { This is a software signal, like SIGABRT or SIGKILL.
  1244. Fill the exception structure, so we get the traceback. }
  1245. djgpp_exception_state_ptr:=@fake_exception;
  1246. if (dpmi_setjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^)<>0) then
  1247. begin
  1248. errln('Bad longjmp to __djgpp_exception_state--aborting');
  1249. do_faulting_finish_message(true); { does not return }
  1250. end
  1251. else
  1252. { Fake the exception number. 7Ah is the last one hardwired
  1253. inside exceptn.S, for SIGQUIT. }
  1254. djgpp_exception_state_ptr^.__signum:=$7a + 1 + sig - SIGABRT;
  1255. end;
  1256. end;
  1257. print_signal_name(sig);
  1258. if assigned(djgpp_exception_state_ptr) then
  1259. { This exits, does not return. }
  1260. do_faulting_finish_message(djgpp_exception_state_ptr=@fake_exception);
  1261. __exit(-1);
  1262. __djgpp__traceback_exit:=0;
  1263. end;
  1264. procedure djgpp_int0;
  1265. begin
  1266. HandleError(200);
  1267. end;
  1268. procedure djgpp_exception_setup;cdecl;
  1269. [public,alias : '___djgpp_exception_setup'];
  1270. var
  1271. temp_kbd,
  1272. temp_npx : pointer;
  1273. _except,
  1274. old_kbd : tseginfo;
  1275. locksize : longint;
  1276. i : longint;
  1277. begin
  1278. if assigned(_exception_exit) then
  1279. exit;
  1280. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1281. begin
  1282. __djgpp_set_sigint_key(DEFAULT_SIGINT);
  1283. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT);
  1284. end
  1285. else
  1286. begin { for PC98 }
  1287. __djgpp_set_sigint_key(DEFAULT_SIGINT_98);
  1288. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT_98);
  1289. end;
  1290. _exception_exit:=@dpmiexcp_exit;
  1291. _swap_in:=@dpmi_swap_in;
  1292. _swap_out:=@dpmi_swap_out;
  1293. { reset signals }
  1294. for i := 0 to SIGMAX do
  1295. signal_list[i] := SignalHandler(@SIG_DFL);
  1296. { app_DS only used when converting HW interrupts to exceptions }
  1297. asm
  1298. movw %ds,___djgpp_app_DS
  1299. movw %ds,___djgpp_our_DS
  1300. end;
  1301. djgpp_dos_sel:=dosmemselector;
  1302. { lock addresses which may see HW interrupts }
  1303. lock_code(@djgpp_hw_lock_start,@djgpp_hw_lock_end-@djgpp_hw_lock_start);
  1304. _except.segment:=get_cs;
  1305. { the first 18 exceptions start at offset +8 since exception
  1306. #18 and #19 had to be put in front of the table. }
  1307. _except.offset:=@djgpp_exception_table + 8;
  1308. for i:=0 to 17 do
  1309. begin
  1310. except_ori[i] := _except; { New value to set }
  1311. inc(_except.offset,4); { This is the size of push n, jmp }
  1312. end;
  1313. except_ori[18].segment := _except.segment;
  1314. except_ori[19].segment := _except.segment;
  1315. except_ori[18].offset := @djgpp_exception_table;
  1316. except_ori[19].offset := @djgpp_exception_table + 4;
  1317. kbd_ori.segment:=_except.segment;
  1318. npx_ori.segment:=_except.segment;
  1319. npx_ori.offset:=@djgpp_npx_hdlr;
  1320. int0_ori.segment:=_except.segment;
  1321. int0_ori.offset:=@djgpp_int0;
  1322. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1323. kbd_ori.offset:=@djgpp_kbd_hdlr
  1324. else
  1325. begin
  1326. kbd_ori.offset:=@djgpp_kbd_hdlr_pc98;
  1327. cbrk_vect := $06;
  1328. _except.offset:=@djgpp_iret;
  1329. set_pm_interrupt($23,_except);
  1330. end;
  1331. _except.offset:=@djgpp_i24;
  1332. set_pm_interrupt($24, _except);
  1333. get_pm_interrupt(9,djgpp_old_kbd);
  1334. djgpp_exception_toggle; { Set new values & save old values }
  1335. { get original video mode and save }
  1336. old_video_mode := farpeekb(dosmemselector, $449);
  1337. end;
  1338. {$endif CREATE_C_FUNCTIONS}
  1339. function djgpp_set_ctrl_c(enable : boolean) : boolean;cdecl;
  1340. begin
  1341. djgpp_set_ctrl_c:=(djgpp_hwint_flags and 1)=0;
  1342. if enable then
  1343. djgpp_hwint_flags:=djgpp_hwint_flags and (not 1)
  1344. else
  1345. djgpp_hwint_flags:=djgpp_hwint_flags or 1;
  1346. end;
  1347. {$ifdef CREATE_C_FUNCTIONS}
  1348. function c_djgpp_set_ctrl_c(enable : longint) : boolean;cdecl;[public,alias : '___djgpp_set_ctrl_c'];
  1349. begin
  1350. c_djgpp_set_ctrl_c:=djgpp_set_ctrl_c(boolean(enable));
  1351. end;
  1352. {$endif def CREATE_C_FUNCTIONS}
  1353. {$ifdef IN_DPMIEXCP_UNIT}
  1354. procedure ResetDefaultHandlers;
  1355. begin
  1356. Signal(SIGSEGV,@SIG_DFL);
  1357. Signal(SIGFPE,@SIG_DFL);
  1358. Signal(SIGNOFP,@SIG_DFL);
  1359. Signal(SIGTRAP,@SIG_DFL);
  1360. Signal(SIGTIMR,@SIG_DFL);
  1361. Signal(SIGINT,@SIG_DFL);
  1362. Signal(SIGQUIT,@SIG_DFL);
  1363. Signal(SIGILL,@SIG_DFL);
  1364. end;
  1365. {$endif IN_DPMIEXCP_UNIT}
  1366. procedure InitDPMIExcp;
  1367. begin
  1368. {$ifdef CREATE_C_FUNCTIONS}
  1369. djgpp_ds_alias:=v2prt0_ds_alias;
  1370. djgpp_exception_setup;
  1371. {$endif CREATE_C_FUNCTIONS}
  1372. end;
  1373. {$ifndef IN_SYSTEM}
  1374. begin
  1375. {$ifdef CREATE_C_FUNCTIONS}
  1376. InitDPMIExcp;
  1377. {$else not CREATE_C_FUNCTIONS}
  1378. ResetDefaultHandlers;
  1379. {$endif CREATE_C_FUNCTIONS}
  1380. end.
  1381. {$else IN_SYSTEM}
  1382. const
  1383. FPU_ControlWord : word = $1332;
  1384. function HandleException(sig : longint) : longint;cdecl;
  1385. var
  1386. truesig : longint;
  1387. ErrorOfSig : longint;
  1388. FpuStatus,FPUControl : word;
  1389. eip,ebp : longint;
  1390. begin
  1391. if assigned(djgpp_exception_state_ptr) then
  1392. truesig:=djgpp_exception_state_ptr^.__signum
  1393. else
  1394. truesig:=sig;
  1395. ErrorOfSig:=0;
  1396. case truesig of
  1397. {exception_names : array[0..EXCEPTIONCOUNT-1] of pchar = (}
  1398. 0 : ErrorOfSig:=200; {'Division by Zero'}
  1399. 5 : ErrorOfSig:=201; {'Bounds Check'}
  1400. 12 : ErrorOfSig:=202; {'Stack Fault'}
  1401. 7, {'Coprocessor not available'}
  1402. 9, {'Coprocessor overrun'}
  1403. SIGNOFP : ErrorOfSig:=207;
  1404. 16,SIGFPE,$75 : begin
  1405. { This needs special handling }
  1406. { to discriminate between 205,206 and 207 }
  1407. if truesig=$75 then
  1408. fpustatus:=djgpp_exception_state_ptr^.__sigmask and $ffff
  1409. else
  1410. asm
  1411. fnstsw %ax
  1412. fnclex
  1413. movw %ax,fpustatus
  1414. end;
  1415. if (FpuStatus and FPU_Invalid)<>0 then
  1416. ErrorOfSig:=216
  1417. else if (FpuStatus and FPU_Denormal)<>0 then
  1418. ErrorOfSig:=216
  1419. else if (FpuStatus and FPU_DivisionByZero)<>0 then
  1420. ErrorOfSig:=200
  1421. else if (FpuStatus and FPU_Overflow)<>0 then
  1422. ErrorOfSig:=205
  1423. else if (FpuStatus and FPU_Underflow)<>0 then
  1424. ErrorOfSig:=206
  1425. else
  1426. ErrorOfSig:=207; {'Coprocessor Error'}
  1427. { if exceptions then Reset FPU and reload control word }
  1428. if (FPUStatus and FPU_ExceptionMask)<>0 then
  1429. asm
  1430. fninit
  1431. fldcw FPU_ControlWord
  1432. end;
  1433. end;
  1434. 4 : ErrorOfSig:=215; {'Overflow'}
  1435. 1, {'Debug'}
  1436. 2, {'NMI'}
  1437. 3, {'Breakpoint'}
  1438. 6, {'Invalid Opcode'}
  1439. 8, {'Double Fault'}
  1440. 10, {'Invalid TSS'}
  1441. 11, {'Segment Not Present'}
  1442. 13, {'General Protection Fault'}
  1443. 14, {'Page fault'}
  1444. 15, {' ',}
  1445. 17, {'Alignment Check',}
  1446. 18, {'Machine Check',}
  1447. 19, {'SSE FP error'}
  1448. SIGSEGV,SIGTRAP,SIGTIMR,SIGINT,SIGQUIT
  1449. : ErrorOfSig:=216;
  1450. end;
  1451. if assigned(djgpp_exception_state_ptr) then
  1452. Begin
  1453. if exception_level>0 then
  1454. dec(exception_level);
  1455. eip:=djgpp_exception_state_ptr^.__eip;
  1456. ebp:=djgpp_exception_state_ptr^.__ebp;
  1457. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  1458. HandleErrorAddrFrame(ErrorOfSig,pointer(eip),pointer(ebp));
  1459. End
  1460. else
  1461. { probably higher level is required }
  1462. HandleErrorFrame(ErrorOfSig,get_caller_frame(get_frame));
  1463. HandleException:=0;
  1464. end;
  1465. procedure InstallDefaultHandlers;
  1466. begin
  1467. Signal(SIGSEGV,@HandleException);
  1468. Signal(SIGFPE,@HandleException);
  1469. Signal(SIGNOFP,@HandleException);
  1470. Signal(SIGTRAP,@HandleException);
  1471. Signal(SIGTIMR,@HandleException);
  1472. Signal(SIGINT,@HandleException);
  1473. Signal(SIGQUIT,@HandleException);
  1474. Signal(SIGILL,@HandleException);
  1475. end;
  1476. {$endif IN_SYSTEM}