dpmiexcp.pp 46 KB

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