dpmiexcp.pp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661
  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. {$IFNDEF FPC_DOTTEDUNITS}
  18. Unit DpmiExcp;
  19. {$ENDIF FPC_DOTTEDUNITS}
  20. { If linking to C code we must avoid loading of the dpmiexcp.o
  21. in libc.a from the equivalent C code
  22. => all global functions from dpmiexcp.c must be aliased PM
  23. Problem this is only valid for DJGPP v2.01 }
  24. interface
  25. {$ifdef NO_EXCEPTIONS_IN_SYSTEM}
  26. uses
  27. go32;
  28. {$endif NO_EXCEPTIONS_IN_SYSTEM}
  29. {$endif ndef IN_SYSTEM}
  30. { No stack checking ! }
  31. {$S-}
  32. { Decide if we want to create the C functions or not }
  33. {$ifdef EXCEPTIONS_IN_SYSTEM}
  34. { If exceptions are in system the C functions must be
  35. inserted in the system unit }
  36. {$ifdef IN_DPMIEXCP_UNIT}
  37. {$undef CREATE_C_FUNCTIONS}
  38. {$else not IN_DPMIEXCP_UNIT}
  39. {$define CREATE_C_FUNCTIONS}
  40. {$endif ndef IN_DPMIEXCP_UNIT}
  41. {$else not EXCEPTIONS_IN_SYSTEM}
  42. {$define CREATE_C_FUNCTIONS}
  43. {$endif not EXCEPTIONS_IN_SYSTEM}
  44. { Error Messages }
  45. function do_faulting_finish_message(fake : boolean) : integer;cdecl;
  46. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  47. {$ifndef CREATE_C_FUNCTIONS}
  48. external;
  49. {$endif CREATE_C_FUNCTIONS}
  50. { SetJmp/LongJmp }
  51. type
  52. { must also contain exception_state !! }
  53. pdpmi_jmp_buf = ^dpmi_jmp_buf;
  54. dpmi_jmp_buf = packed record
  55. eax,ebx,ecx,edx,esi,edi,ebp,esp,eip,flags : longint;
  56. cs,ds,es,fs,gs,ss : word;
  57. sigmask : longint; { for POSIX signals only }
  58. signum : longint; { for expansion ie 386 exception number }
  59. exception_ptr : pdpmi_jmp_buf; { pointer to previous exception if exists }
  60. end;
  61. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  62. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  63. {$ifndef CREATE_C_FUNCTIONS}
  64. external name 'FPC_setjmp';
  65. {$endif CREATE_C_FUNCTIONS}
  66. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  67. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  68. {$ifndef CREATE_C_FUNCTIONS}
  69. external name 'FPC_longjmp';
  70. {$endif CREATE_C_FUNCTIONS}
  71. { Signals }
  72. const
  73. SIGABRT = 288;
  74. SIGFPE = 289;
  75. SIGILL = 290;
  76. SIGSEGV = 291;
  77. SIGTERM = 292;
  78. SIGALRM = 293;
  79. SIGHUP = 294;
  80. SIGINT = 295;
  81. SIGKILL = 296;
  82. SIGPIPE = 297;
  83. SIGQUIT = 298;
  84. SIGUSR1 = 299;
  85. SIGUSR2 = 300;
  86. SIGNOFP = 301;
  87. SIGTRAP = 302;
  88. SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
  89. SIGPROF = 304;
  90. SIGMAX = 320;
  91. SIG_BLOCK = 1;
  92. SIG_SETMASK = 2;
  93. SIG_UNBLOCK = 3;
  94. function SIG_DFL( x: longint) : longint;cdecl;
  95. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  96. {$ifndef CREATE_C_FUNCTIONS}
  97. external name '__djgpp_SIG_DFL';
  98. {$endif CREATE_C_FUNCTIONS}
  99. function SIG_ERR( x: longint) : longint;cdecl;
  100. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  101. {$ifndef CREATE_C_FUNCTIONS}
  102. external name '__djgpp_SIG_ERR';
  103. {$endif CREATE_C_FUNCTIONS}
  104. function SIG_IGN( x: longint) : longint;cdecl;
  105. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  106. {$ifndef CREATE_C_FUNCTIONS}
  107. external name '__djgpp_SIG_IGN';
  108. {$endif CREATE_C_FUNCTIONS}
  109. type
  110. SignalHandler = function (v : longint) : longint;cdecl;
  111. PSignalHandler = ^SignalHandler; { to be compatible with linux.pp }
  112. function signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;
  113. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  114. function _raise(sig : longint) : longint;cdecl;
  115. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  116. { Exceptions }
  117. type
  118. pexception_state = ^texception_state;
  119. texception_state = record
  120. __eax, __ebx, __ecx, __edx, __esi : longint;
  121. __edi, __ebp, __esp, __eip, __eflags : longint;
  122. __cs, __ds, __es, __fs, __gs, __ss : word;
  123. __sigmask : longint; { for POSIX signals only }
  124. __signum : longint; { for expansion }
  125. __exception_ptr : pexception_state; { pointer to previous exception }
  126. __fpu_state : array [0..108-1] of byte; { for future use }
  127. end;
  128. procedure djgpp_exception_toggle;cdecl;
  129. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  130. {$ifndef CREATE_C_FUNCTIONS}
  131. external name '___djgpp_exception_toggle';
  132. {$endif CREATE_C_FUNCTIONS}
  133. procedure djgpp_exception_setup;cdecl;
  134. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  135. {$ifndef CREATE_C_FUNCTIONS}
  136. external name '___djgpp_exception_setup';
  137. {$endif CREATE_C_FUNCTIONS}
  138. function djgpp_exception_state : pexception_state;
  139. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  140. function djgpp_set_ctrl_c(enable : boolean) : boolean;cdecl;
  141. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  142. { Other }
  143. function dpmi_set_coprocessor_emulation(flag : longint) : longint;cdecl;
  144. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  145. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  146. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  147. {$ifndef CREATE_C_FUNCTIONS}
  148. external;
  149. {$endif CREATE_C_FUNCTIONS}
  150. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  151. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  152. {$ifndef CREATE_C_FUNCTIONS}
  153. external;
  154. {$endif CREATE_C_FUNCTIONS}
  155. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  156. {$ifdef IN_SYSTEM}forward;{$endif IN_SYSTEM}
  157. {$ifndef CREATE_C_FUNCTIONS}
  158. external;
  159. {$endif CREATE_C_FUNCTIONS}
  160. {$ifndef IN_SYSTEM}
  161. implementation
  162. {$endif IN_SYSTEM}
  163. {$asmmode ATT}
  164. {$ifdef CREATE_C_FUNCTIONS}
  165. {$L exceptn.o}
  166. var
  167. v2prt0_ds_alias : word;external name '___v2prt0_ds_alias';
  168. djgpp_ds_alias : word;external name '___djgpp_ds_alias';
  169. djgpp_old_kbd : tseginfo;external name '___djgpp_old_kbd';
  170. djgpp_hw_lock_start : longint;external name '___djgpp_hw_lock_start';
  171. djgpp_hw_lock_end : longint;external name '___djgpp_hw_lock_end';
  172. djgpp_dos_sel : word;external name '___djgpp_dos_sel';
  173. djgpp_exception_table : array[0..0] of pointer;external name '___djgpp_exception_table';
  174. dosmemselector : word;external name '_core_selector';
  175. procedure djgpp_i24;external name '___djgpp_i24';
  176. procedure djgpp_iret;external name '___djgpp_iret';
  177. procedure djgpp_npx_hdlr;external name '___djgpp_npx_hdlr';
  178. procedure djgpp_kbd_hdlr;external name '___djgpp_kbd_hdlr';
  179. procedure djgpp_kbd_hdlr_pc98;external name '___djgpp_kbd_hdlr_pc98';
  180. procedure djgpp_cbrk_hdlr;external name '___djgpp_cbrk_hdlr';
  181. var
  182. exceptions_on : boolean;
  183. { old_int00 : tseginfo;cvar;external;
  184. old_int75 : tseginfo;cvar;external; }
  185. const
  186. cbrk_vect : byte = $1b;
  187. exception_level : longint = 0;
  188. {$endif CREATE_C_FUNCTIONS}
  189. var
  190. endtext : longint;external name '_etext';
  191. starttext : longint;external name 'start';
  192. djgpp_exception_state_ptr : pexception_state;external name '___djgpp_exception_state_ptr';
  193. djgpp_hwint_flags : longint;external name '___djgpp_hwint_flags';
  194. {$ifndef IN_DPMIEXCP_UNIT}
  195. {****************************************************************************
  196. DPMI functions copied from go32 unit
  197. ****************************************************************************}
  198. const
  199. int31error : word = 0;
  200. procedure test_int31(flag : longint); stdcall; { stack-args! }
  201. begin
  202. asm
  203. pushl %ebx
  204. movw $0,INT31ERROR
  205. movl flag,%ebx
  206. testb $1,%bl
  207. jz .Lti31_1
  208. movw %ax,INT31ERROR
  209. xorl %eax,%eax
  210. jmp .Lti31_2
  211. .Lti31_1:
  212. movl $1,%eax
  213. .Lti31_2:
  214. popl %ebx
  215. end;
  216. end;
  217. function set_pm_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  218. begin
  219. asm
  220. movl intaddr,%eax
  221. movl (%eax),%edx
  222. movw 4(%eax),%cx
  223. movl $0x212,%eax
  224. movb e,%bl
  225. int $0x31
  226. pushf
  227. call test_int31
  228. movb %al,__RESULT
  229. end;
  230. end;
  231. function set_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  232. begin
  233. asm
  234. movl intaddr,%eax
  235. movl (%eax),%edx
  236. movw 4(%eax),%cx
  237. movl $0x203,%eax
  238. movb e,%bl
  239. int $0x31
  240. pushf
  241. call test_int31
  242. movb %al,__RESULT
  243. end;
  244. end;
  245. function get_pm_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  246. begin
  247. asm
  248. movl $0x210,%eax
  249. movb e,%bl
  250. int $0x31
  251. pushf
  252. call test_int31
  253. movb %al,__RESULT
  254. movl intaddr,%eax
  255. movl %edx,(%eax)
  256. movw %cx,4(%eax)
  257. end;
  258. end;
  259. function get_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  260. begin
  261. asm
  262. pushl %ebx
  263. movl $0x202,%eax
  264. movb e,%bl
  265. int $0x31
  266. pushf
  267. call test_int31
  268. movb %al,__RESULT
  269. movl intaddr,%eax
  270. movl %edx,(%eax)
  271. movw %cx,4(%eax)
  272. popl %ebx
  273. end;
  274. end;
  275. function get_segment_base_address(d : word) : longint;
  276. begin
  277. asm
  278. pushl %ebx
  279. movw d,%bx
  280. movl $6,%eax
  281. int $0x31
  282. xorl %eax,%eax
  283. movw %dx,%ax
  284. shll $16,%ecx
  285. orl %ecx,%eax
  286. movl %eax,__RESULT
  287. popl %ebx
  288. end;
  289. end;
  290. function get_segment_limit(d : word) : longint;
  291. begin
  292. asm
  293. movzwl d,%eax
  294. lsl %eax,%eax
  295. jz .L_ok2
  296. xorl %eax,%eax
  297. .L_ok2:
  298. movl %eax,__RESULT
  299. end;
  300. end;
  301. function set_rm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  302. begin
  303. asm
  304. pushl %ebx
  305. movl intaddr,%eax
  306. movw (%eax),%dx
  307. movw 4(%eax),%cx
  308. movl $0x201,%eax
  309. movb vector,%bl
  310. int $0x31
  311. pushf
  312. call test_int31
  313. movb %al,__RESULT
  314. popl %ebx
  315. end;
  316. end;
  317. function get_rm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  318. begin
  319. asm
  320. pushl %ebx
  321. movb vector,%bl
  322. movl $0x200,%eax
  323. int $0x31
  324. pushf
  325. call test_int31
  326. movb %al,__RESULT
  327. movl intaddr,%eax
  328. movzwl %dx,%edx
  329. movl %edx,(%eax)
  330. movw %cx,4(%eax)
  331. popl %ebx
  332. end;
  333. end;
  334. function free_rm_callback(var intaddr : tseginfo) : boolean;
  335. begin
  336. asm
  337. movl intaddr,%eax
  338. movw (%eax),%dx
  339. movw 4(%eax),%cx
  340. movl $0x304,%eax
  341. int $0x31
  342. pushf
  343. call test_int31
  344. movb %al,__RESULT
  345. end;
  346. end;
  347. function get_rm_callback(pm_func : pointer;const reg : trealregs;var rmcb : tseginfo) : boolean;
  348. begin
  349. asm
  350. pushl %esi
  351. pushl %edi
  352. movl pm_func,%esi
  353. movl reg,%edi
  354. pushw %es
  355. movw v2prt0_ds_alias,%ax
  356. movw %ax,%es
  357. pushw %ds
  358. movw %cs,%ax
  359. movw %ax,%ds
  360. movl $0x303,%eax
  361. int $0x31
  362. popw %ds
  363. popw %es
  364. pushf
  365. call test_int31
  366. movb %al,__RESULT
  367. movl rmcb,%eax
  368. movzwl %dx,%edx
  369. movl %edx,(%eax)
  370. movw %cx,4(%eax)
  371. popl %edi
  372. popl %esi
  373. end;
  374. end;
  375. function lock_linear_region(linearaddr, size : longint) : boolean;
  376. begin
  377. asm
  378. pushl %ebx
  379. pushl %esi
  380. pushl %edi
  381. movl $0x600,%eax
  382. movl linearaddr,%ecx
  383. movl %ecx,%ebx
  384. shrl $16,%ebx
  385. movl size,%esi
  386. movl %esi,%edi
  387. shrl $16,%esi
  388. int $0x31
  389. pushf
  390. call test_int31
  391. movb %al,__RESULT
  392. popl %edi
  393. popl %esi
  394. popl %ebx
  395. end;
  396. end;
  397. function lock_code(functionaddr : pointer;size : longint) : boolean;
  398. var
  399. linearaddr : longint;
  400. begin
  401. linearaddr:=longint(functionaddr)+get_segment_base_address(get_cs);
  402. lock_code:=lock_linear_region(linearaddr,size);
  403. end;
  404. {$endif ndef IN_DPMIEXCP_UNIT}
  405. {****************************************************************************
  406. Helpers
  407. ****************************************************************************}
  408. procedure err(const x : shortstring);
  409. begin
  410. write(stderr, x);
  411. end;
  412. procedure errln(const x : shortstring);
  413. begin
  414. writeln(stderr, x);
  415. end;
  416. procedure itox(v,len : longint);
  417. var
  418. st : shortstring;
  419. begin
  420. st:=hexstr(v,len);
  421. err(st);
  422. end;
  423. {****************************************************************************
  424. SetJmp/LongJmp
  425. ****************************************************************************}
  426. {$ifdef CREATE_C_FUNCTIONS}
  427. function c_setjmp(var rec : dpmi_jmp_buf) : longint;cdecl;[public, alias : '_setjmp'];
  428. begin
  429. asm
  430. { unset the frame pointer just set }
  431. movl %ebp,%esp
  432. popl %ebp
  433. {$ifndef REGCALL}
  434. { here we need to be subtle :
  435. - we need to return with the arg still on the stack
  436. - but we also need to jmp to FPC_setjmp and not to call it
  437. because otherwise the return address is wrong !!
  438. For this we shift the return address down and
  439. duplicate the rec on stack }
  440. subl $8,%esp
  441. movl %eax,(%esp)
  442. movl 8(%esp),%eax
  443. movl %eax,4(%esp)
  444. movl 12(%esp),%eax
  445. movl %eax,8(%esp)
  446. { stack is now:
  447. (%esp) eax <= we're popping it in the next instruction
  448. 4(%esp) return addr
  449. 8(%esp) rec <= automatically removed by dpmi_setjmp
  450. 12(%esp) rec <= the caller will remove this
  451. }
  452. popl %eax
  453. jmp dpmi_setjmp
  454. {$ELSE REGCALL}
  455. { this is easier with regcall convention
  456. because dpmi_setjmp expects rec arg in $eax
  457. We don't need to touch the stack. We must leave the parameter
  458. there since this is a cdecl function (the caller will remove it)
  459. }
  460. movl 4(%esp), %eax
  461. jmp dpmi_setjmp
  462. {$ENDIF REGCALL}
  463. end;
  464. end;
  465. {$endif CREATE_C_FUNCTIONS}
  466. {$ifdef CREATE_C_FUNCTIONS}
  467. function dpmi_setjmp(var rec : dpmi_jmp_buf) : longint;
  468. [public, alias : 'FPC_setjmp'];
  469. begin
  470. asm
  471. pushl %edi
  472. movl rec,%edi
  473. movl %eax,(%edi)
  474. movl %ebx,4(%edi)
  475. movl %ecx,8(%edi)
  476. movl %edx,12(%edi)
  477. movl %esi,16(%edi)
  478. {$ifndef REGCALL}
  479. { load edi }
  480. movl -4(%ebp),%eax
  481. {$ELSE REGCALL}
  482. { load edi }
  483. movl (%esp),%eax
  484. {$ENDIF REGCALL}
  485. { ... and store it }
  486. movl %eax,20(%edi)
  487. { ebp ... }
  488. movl (%ebp),%eax
  489. movl %eax,24(%edi)
  490. {$ifndef REGCALL}
  491. { esp ... }
  492. movl %esp,%eax
  493. addl $12,%eax
  494. {$ELSE REGCALL}
  495. { for esp, use ebp ... }
  496. movl %ebp,%eax
  497. addl $8,%eax
  498. {$ENDIF REGCALL}
  499. movl %eax,28(%edi)
  500. { the return address }
  501. movl 4(%ebp),%eax
  502. movl %eax,32(%edi)
  503. { flags ... }
  504. pushfl
  505. popl 36(%edi)
  506. { !!!!! the segment registers, not yet needed }
  507. { you need them if the exception comes from
  508. an interrupt or a seg_move }
  509. movw %cs,40(%edi)
  510. movw %ds,42(%edi)
  511. movw %es,44(%edi)
  512. movw %fs,46(%edi)
  513. movw %gs,48(%edi)
  514. movw %ss,50(%edi)
  515. movl djgpp_exception_state_ptr, %eax
  516. movl %eax, 60(%edi)
  517. { restore EDI }
  518. popl %edi
  519. { we come from the initial call }
  520. xorl %eax,%eax
  521. movl %eax,__RESULT
  522. { leave USING RET inside CDECL functions is risky as
  523. some registers are pushed at entry
  524. ret $4 not anymore since cdecl !! }
  525. end;
  526. end;
  527. {$endif CREATE_C_FUNCTIONS}
  528. {$ifdef CREATE_C_FUNCTIONS}
  529. procedure c_longjmp(var rec : dpmi_jmp_buf;return_value : longint);cdecl;[public, alias : '_longjmp'];
  530. begin
  531. dpmi_longjmp(rec,return_value);
  532. { never gets here !! so pascal stack convention is no problem }
  533. end;
  534. {$endif CREATE_C_FUNCTIONS}
  535. {$ifdef CREATE_C_FUNCTIONS}
  536. procedure dpmi_longjmp(var rec : dpmi_jmp_buf;return_value : longint);
  537. [public, alias : 'FPC_longjmp'];
  538. begin
  539. if (exception_level>0) then
  540. dec(exception_level);
  541. asm
  542. { copy from longjmp.S }
  543. { Adapted to avoid being sensitive to
  544. argument being on stack or in registers 2006-12-21 PM }
  545. movl rec,%edi { get dpmi_jmp_buf }
  546. movl return_value,%eax { store retval in j->eax }
  547. { restore compiler shit }
  548. popl %ebp
  549. movl %eax,0(%edi)
  550. movw 46(%edi),%fs
  551. movw 48(%edi),%gs
  552. movl 4(%edi),%ebx
  553. movl 8(%edi),%ecx
  554. movl 12(%edi),%edx
  555. movl 24(%edi),%ebp
  556. { Now for some uglyness. The dpmi_jmp_buf structure may be ABOVE the
  557. point on the new SS:ESP we are moving to. We don't allow overlap,
  558. but do force that it always be valid. We will use ES:ESI for
  559. our new stack before swapping to it. }
  560. movw 50(%edi),%es
  561. movl 28(%edi),%esi
  562. subl $28,%esi { We need 7 working longwords on stack }
  563. movl 60(%edi),%eax
  564. movl %eax,%es:(%esi) { Exception pointer }
  565. movzwl 42(%edi),%eax
  566. movl %eax,%es:4(%esi) { DS }
  567. movl 20(%edi),%eax
  568. movl %eax,%es:8(%esi) { EDI }
  569. movl 16(%edi),%eax
  570. movl %eax,%es:12(%esi) { ESI }
  571. movl 32(%edi),%eax
  572. movl %eax,%es:16(%esi) { EIP - start of IRET frame }
  573. movl 40(%edi),%eax
  574. movl %eax,%es:20(%esi) { CS }
  575. movl 36(%edi),%eax
  576. movl %eax,%es:24(%esi) { EFLAGS }
  577. movl 0(%edi),%eax
  578. movw 44(%edi),%es
  579. movw 50(%edi),%ss
  580. movl %esi,%esp
  581. popl djgpp_exception_state_ptr
  582. popl %ds
  583. popl %edi
  584. popl %esi
  585. iret { actually jump to new cs:eip loading flags }
  586. end;
  587. end;
  588. {$endif CREATE_C_FUNCTIONS}
  589. {****************************************************************************
  590. Signals
  591. ****************************************************************************}
  592. var
  593. signal_list : Array[0..SIGMAX] of SignalHandler;cvar;
  594. {$ifndef CREATE_C_FUNCTIONS}external;{$else}public;{$endif}
  595. {$ifdef CREATE_C_FUNCTIONS}
  596. function SIG_ERR(x:longint):longint;cdecl;[public,alias : '___djgpp_SIG_ERR'];
  597. begin
  598. SIG_ERR:=-1;
  599. end;
  600. function SIG_IGN(x:longint):longint;cdecl;[public,alias : '___djgpp_SIG_IGN'];
  601. begin
  602. SIG_IGN:=-1;
  603. end;
  604. function SIG_DFL(x:longint):longint;cdecl;[public,alias : '___djgpp_SIG_DFL'];
  605. begin
  606. SIG_DFL:=0;
  607. end;
  608. {$endif CREATE_C_FUNCTIONS}
  609. function signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;
  610. var
  611. temp : SignalHandler;
  612. begin
  613. if ((sig < 0) or (sig > SIGMAX) or (sig = SIGKILL)) then
  614. begin
  615. signal:=@SIG_ERR;
  616. runerror(201);
  617. end;
  618. temp := signal_list[sig];
  619. signal_list[sig] := func;
  620. signal:=temp;
  621. end;
  622. {$ifdef CREATE_C_FUNCTIONS}
  623. { C counter part }
  624. function c_signal(sig : longint;func : SignalHandler) : SignalHandler;cdecl;[public,alias : '_signal'];
  625. var
  626. temp : SignalHandler;
  627. begin
  628. temp:=signal(sig,func);
  629. c_signal:=temp;
  630. end;
  631. {$endif CREATE_C_FUNCTIONS}
  632. const
  633. signames : array [0..14] of string[4] = (
  634. 'ABRT','FPE ','ILL ','SEGV','TERM','ALRM','HUP ',
  635. 'INT ','KILL','PIPE','QUIT','USR1','USR2','NOFP','TRAP');
  636. procedure print_signal_name(sig : longint);
  637. begin
  638. if ((sig >= SIGABRT) and (sig <= SIGTRAP)) then
  639. begin
  640. err('Exiting due to signal SIG');
  641. err(signames[sig-sigabrt]);
  642. end
  643. else
  644. begin
  645. err('Exiting due to signal $');
  646. itox(sig, 4);
  647. end;
  648. errln('');
  649. end;
  650. function _raise(sig : longint) : longint;cdecl;
  651. var
  652. temp : SignalHandler;
  653. begin
  654. if(sig < 0) or (sig > SIGMAX) then
  655. exit(-1);
  656. temp:=signal_list[sig];
  657. if (temp = SignalHandler(@SIG_IGN)) then
  658. exit(0);
  659. if (temp = SignalHandler(@SIG_DFL)) then
  660. begin
  661. print_signal_name(sig);
  662. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  663. exit(-1);
  664. end;
  665. { this is incompatible with dxegen-dxeload stuff PM }
  666. if ((cardinal(temp) < cardinal(@starttext)) or
  667. (cardinal(temp) > cardinal(@endtext))) then
  668. begin
  669. errln('Bad signal handler, ');
  670. print_signal_name(sig);
  671. do_faulting_finish_message(djgpp_exception_state<>nil); { Exits, does not return }
  672. exit(-1);
  673. end;
  674. { WARNING !!! temp can be a pascal or a C
  675. function... thus %esp can be modified here !!!
  676. This might be dangerous for some optimizations ?? PM }
  677. temp(sig);
  678. exit(0);
  679. end;
  680. {$ifdef CREATE_C_FUNCTIONS}
  681. function c_raise(sig : longint) : longint;cdecl;[public,alias : '_raise'];
  682. begin
  683. c_raise:=_raise(sig);
  684. end;
  685. {$endif CREATE_C_FUNCTIONS}
  686. {****************************************************************************
  687. Exceptions
  688. ****************************************************************************}
  689. var
  690. ___djgpp_selector_limit: cardinal; external name '___djgpp_selector_limit';
  691. {$ifdef CREATE_C_FUNCTIONS}
  692. {$ifdef IN_DPMIEXCP_UNIT}
  693. procedure __exit(c:longint);cdecl;external;
  694. {$endif}
  695. function except_to_sig(excep : longint) : longint;
  696. begin
  697. case excep of
  698. 5,8,9,11,12,13,14,
  699. 18, 19 : exit(SIGSEGV);
  700. 0,4,16 : exit(SIGFPE);
  701. 1,3 : exit(SIGTRAP);
  702. 7 : exit(SIGNOFP);
  703. else
  704. begin
  705. case excep of
  706. $75 : exit(SIGFPE);
  707. $78 : exit(SIGTIMR);
  708. $1b,
  709. $79 : exit(SIGINT);
  710. $7a : exit(SIGQUIT);
  711. else
  712. exit(SIGILL);
  713. end;
  714. end;
  715. end;
  716. end;
  717. procedure show_call_frame(djgpp_exception_state : pexception_state);
  718. begin
  719. errln('Call frame traceback EIPs:');
  720. errln(BackTraceStrFunc(Pointer(djgpp_exception_state^.__eip)));
  721. dump_stack(stderr,Pointer(djgpp_exception_state^.__ebp));
  722. end;
  723. const
  724. EXCEPTIONCOUNT = 20;
  725. exception_names : array[0..EXCEPTIONCOUNT-1] of PAnsiChar = (
  726. 'Division by Zero',
  727. 'Debug',
  728. 'NMI',
  729. 'Breakpoint',
  730. 'Overflow',
  731. 'Bounds Check',
  732. 'Invalid Opcode',
  733. 'Coprocessor not available',
  734. 'Double Fault',
  735. 'Coprocessor overrun',
  736. 'Invalid TSS',
  737. 'Segment Not Present',
  738. 'Stack Fault',
  739. 'General Protection Fault',
  740. 'Page fault',
  741. ' ',
  742. 'Coprocessor Error',
  743. 'Alignment Check',
  744. 'Machine check',
  745. 'SIMD FP Error');
  746. has_error : array [0..EXCEPTIONCOUNT-1] of byte =
  747. (0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,0,0);
  748. cbrk_hooked : boolean = false;
  749. old_video_mode : byte = 3;
  750. procedure dump_selector(const name : shortstring; sel : word);
  751. var
  752. base,limit : longint;
  753. begin
  754. err(name);
  755. err(': sel=');
  756. itox(sel, 4);
  757. if (sel<>0) then
  758. begin
  759. base:=get_segment_base_address(sel);
  760. err(' base='); itox(base, 8);
  761. limit:=get_segment_limit(sel);
  762. err(' limit='); itox(limit, 8);
  763. end;
  764. errln('');
  765. end;
  766. function farpeekb(sel : word;offset : longint) : byte;
  767. var
  768. b : byte;
  769. begin
  770. {$ifdef IN_DPMIEXCP_UNIT}
  771. seg_move(sel,offset,get_ds,longint(@b),1);
  772. {$else not IN_DPMIEXCP_UNIT}
  773. sysseg_move(sel,offset,get_ds,longint(@b),1);
  774. {$endif IN_DPMIEXCP_UNIT}
  775. farpeekb:=b;
  776. end;
  777. const message_level : byte = 0;
  778. function do_faulting_finish_message(fake : boolean) : integer;cdecl;
  779. public;
  780. var
  781. en : PAnsiChar;
  782. signum,i : longint;
  783. old_vid : byte;
  784. label
  785. simple_exit;
  786. function _my_cs: word; assembler;
  787. asm
  788. movw %cs,%ax
  789. end;
  790. begin
  791. inc(message_level);
  792. if message_level>2 then
  793. goto simple_exit;
  794. do_faulting_finish_message:=0;
  795. signum:=djgpp_exception_state_ptr^.__signum;
  796. { check video mode for original here and reset (not if PC98) }
  797. if ((go32_info_block.linear_address_of_primary_screen <> $a0000) and
  798. (farpeekb(dosmemselector, $449) <> old_video_mode)) then
  799. begin
  800. old_vid:=old_video_mode;
  801. asm
  802. pusha
  803. movzbl old_vid,%eax
  804. int $0x10
  805. popa
  806. nop
  807. end;
  808. end;
  809. if (signum >= EXCEPTIONCOUNT) then
  810. begin
  811. case signum of
  812. $75 : en:='Floating Point exception';
  813. $1b : en:='Control-Break Pressed';
  814. $79 : en:='Control-C Pressed';
  815. $7a : en:='QUIT key Pressed'
  816. else
  817. en:=nil;
  818. end;
  819. end
  820. else
  821. en:=exception_names[signum];
  822. if (en = nil) then
  823. begin
  824. if fake then
  825. err('Raised ')
  826. else
  827. err('Exception ');
  828. itox(signum, 2);
  829. err(' at eip=');
  830. (* For fake exceptions like SIGABRT report where `raise' was called. *)
  831. if fake and (djgpp_exception_state_ptr^.__cs = _my_cs)
  832. and (djgpp_exception_state_ptr^.__ebp >= djgpp_exception_state_ptr^.__esp)
  833. and (djgpp_exception_state_ptr^.__ebp >= endtext)
  834. and (djgpp_exception_state_ptr^.__ebp < ___djgpp_selector_limit) then
  835. itox(djgpp_exception_state_ptr^.__ebp + 1, 8)
  836. else
  837. itox(djgpp_exception_state_ptr^.__eip, 8);
  838. end
  839. else
  840. begin
  841. write(stderr, 'FPC ',en);
  842. err(' at eip=');
  843. itox(djgpp_exception_state_ptr^.__eip, 8);
  844. end;
  845. { Control-C should stop the program also !}
  846. {if (signum = $79) then
  847. begin
  848. errln('');
  849. exit(-1);
  850. end;}
  851. if ((signum < EXCEPTIONCOUNT) and (has_error[signum]=1)) then
  852. begin
  853. errorcode := djgpp_exception_state_ptr^.__sigmask and $ffff;
  854. if(errorcode<>0) then
  855. begin
  856. err(', error=');
  857. itox(errorcode, 4);
  858. end;
  859. end;
  860. errln('');
  861. err('eax=');
  862. itox(djgpp_exception_state_ptr^.__eax, 8);
  863. err(' ebx='); itox(djgpp_exception_state_ptr^.__ebx, 8);
  864. err(' ecx='); itox(djgpp_exception_state_ptr^.__ecx, 8);
  865. err(' edx='); itox(djgpp_exception_state_ptr^.__edx, 8);
  866. err(' esi='); itox(djgpp_exception_state_ptr^.__esi, 8);
  867. err(' edi='); itox(djgpp_exception_state_ptr^.__edi, 8);
  868. errln('');
  869. err('ebp='); itox(djgpp_exception_state_ptr^.__ebp, 8);
  870. err(' esp='); itox(djgpp_exception_state_ptr^.__esp, 8);
  871. err(' program=');
  872. errln(paramstr(0));
  873. dump_selector('cs', djgpp_exception_state_ptr^.__cs);
  874. dump_selector('ds', djgpp_exception_state_ptr^.__ds);
  875. dump_selector('es', djgpp_exception_state_ptr^.__es);
  876. dump_selector('fs', djgpp_exception_state_ptr^.__fs);
  877. dump_selector('gs', djgpp_exception_state_ptr^.__gs);
  878. dump_selector('ss', djgpp_exception_state_ptr^.__ss);
  879. errln('');
  880. if (djgpp_exception_state_ptr^.__cs = get_cs) then
  881. show_call_frame(djgpp_exception_state_ptr)
  882. {$ifdef DPMIEXCP_DEBUG}
  883. else
  884. errln('Exception occurred in another context');
  885. {$endif def DPMIEXCP_DEBUG}
  886. ;
  887. if assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  888. if (djgpp_exception_state_ptr^.__exception_ptr^.__cs = get_cs) then
  889. begin
  890. Errln('First exception level stack');
  891. show_call_frame(djgpp_exception_state_ptr^.__exception_ptr);
  892. end
  893. {$ifdef DPMIEXCP_DEBUG}
  894. else
  895. begin
  896. errln('First exception occurred in another context');
  897. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  898. do_faulting_finish_message(false);
  899. end;
  900. {$endif def DPMIEXCP_DEBUG}
  901. ;
  902. { must not return !! }
  903. simple_exit:
  904. if exceptions_on then
  905. djgpp_exception_toggle;
  906. __exit(-1);
  907. end;
  908. {$endif CREATE_C_FUNCTIONS}
  909. function djgpp_exception_state:pexception_state;assembler;
  910. asm
  911. movl djgpp_exception_state_ptr,%eax
  912. end;
  913. {$ifdef CREATE_C_FUNCTIONS}
  914. var
  915. _os_trueversion : word;external name '__os_trueversion';
  916. procedure djgpp_exception_processor;cdecl;[public,alias : '___djgpp_exception_processor'];
  917. var
  918. sig : longint;
  919. begin
  920. if not assigned(djgpp_exception_state_ptr^.__exception_ptr) then
  921. exception_level:=1
  922. else
  923. inc(exception_level);
  924. sig:=djgpp_exception_state_ptr^.__signum;
  925. if (exception_level=1) or (sig=$78) then
  926. begin
  927. sig := except_to_sig(sig);
  928. if signal_list[djgpp_exception_state_ptr^.__signum]
  929. <>SignalHandler(@SIG_DFL) then
  930. _raise(djgpp_exception_state_ptr^.__signum)
  931. else
  932. _raise(sig);
  933. if (djgpp_exception_state_ptr^.__signum >= EXCEPTIONCOUNT) then
  934. { Not exception so continue OK }
  935. dpmi_longjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^, djgpp_exception_state_ptr^.__eax);
  936. { User handler did not exit or longjmp, we must exit }
  937. err('FPC cannot continue from exception, exiting due to signal ');
  938. itox(sig, 4);
  939. errln('');
  940. end
  941. else
  942. begin
  943. if exception_level>2 then
  944. begin
  945. if exception_level=3 then
  946. errln('FPC triple exception, exiting !!! ');
  947. if (exceptions_on) then
  948. djgpp_exception_toggle;
  949. __exit(1);
  950. end;
  951. err('FPC double exception, exiting due to signal ');
  952. itox(sig, 4);
  953. errln('');
  954. end;
  955. do_faulting_finish_message(djgpp_exception_state<>nil);
  956. end;
  957. type
  958. trealseginfo = tseginfo;
  959. pseginfo = ^tseginfo;
  960. var
  961. except_ori : array [0..EXCEPTIONCOUNT-1] of tseginfo;
  962. {$ifdef DPMIEXCP_DEBUG}
  963. export name '_ori_exceptions';
  964. {$endif def DPMIEXCP_DEBUG}
  965. kbd_ori : tseginfo;
  966. int0_ori,
  967. npx_ori : tseginfo;
  968. cbrk_ori,
  969. cbrk_rmcb : trealseginfo;
  970. cbrk_regs : trealregs;
  971. v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  972. procedure djgpp_exception_toggle;cdecl;
  973. [public,alias : '___djgpp_exception_toggle'];
  974. var
  975. _except : tseginfo;
  976. i : longint;
  977. begin
  978. {$ifdef DPMIEXCP_DEBUG}
  979. if exceptions_on then
  980. errln('Disabling FPC exceptions')
  981. else
  982. errln('Enabling FPC exceptions');
  983. {$endif DPMIEXCP_DEBUG}
  984. { toggle here to avoid infinite recursion }
  985. { if a subfunction calls runerror !! }
  986. exceptions_on:=not exceptions_on;
  987. v2prt0_exceptions_on:=exceptions_on;
  988. { Exceptions 18 and 19 settings generates a bug in
  989. the DJGPP debug code PM }
  990. for i:=0 to 17{EXCEPTIONCOUNT-1} do
  991. begin
  992. {$ifdef DPMIEXCP_DEBUG}
  993. errln('new exception '+hexstr(i,2)+' '+hexstr(except_ori[i].segment,4)+':'+hexstr(longint(except_ori[i].offset),8));
  994. {$endif DPMIEXCP_DEBUG}
  995. { Windows 2000 seems to not set carryflag on func 0x210 :( PM }
  996. if (_os_trueversion <> $532) and get_pm_exception_handler(i,_except) then
  997. begin
  998. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  999. begin
  1000. {$ifdef DPMIEXCP_DEBUG}
  1001. errln('Using DPMI 1.0 functions');
  1002. {$endif DPMIEXCP_DEBUG}
  1003. if not set_pm_exception_handler(i,except_ori[i]) then
  1004. errln('error setting exception nø'+hexstr(i,2));
  1005. end;
  1006. except_ori[i]:=_except;
  1007. end
  1008. else
  1009. begin
  1010. if get_exception_handler(i,_except) then
  1011. begin
  1012. {$ifdef DPMIEXCP_DEBUG}
  1013. errln('Using DPMI 0.9 functions');
  1014. {$endif DPMIEXCP_DEBUG}
  1015. if (i <> 2) {or (_crt0_startup_flags & _CRT0_FLAG_NMI_SIGNAL))} then
  1016. begin
  1017. if not set_exception_handler(i,except_ori[i]) then
  1018. errln('error setting exception nø'+hexstr(i,2));
  1019. end;
  1020. except_ori[i]:=_except;
  1021. end;
  1022. end;
  1023. {$ifdef DPMIEXCP_DEBUG}
  1024. errln('prev exception '+hexstr(i,2)+' '+hexstr(_except.segment,4)+':'+hexstr(longint(_except.offset),8));
  1025. {$endif DPMIEXCP_DEBUG}
  1026. end;
  1027. get_pm_interrupt($75,_except);
  1028. set_pm_interrupt($75,npx_ori);
  1029. npx_ori:=_except;
  1030. get_pm_interrupt($0,_except);
  1031. set_pm_interrupt($0,int0_ori);
  1032. int0_ori:=_except;
  1033. get_pm_interrupt(9,_except);
  1034. set_pm_interrupt(9,kbd_ori);
  1035. kbd_ori:=_except;
  1036. if (cbrk_hooked) then
  1037. begin
  1038. set_rm_interrupt(cbrk_vect,cbrk_ori);
  1039. free_rm_callback(cbrk_rmcb);
  1040. cbrk_hooked := false;
  1041. {$ifdef DPMIEXCP_DEBUG}
  1042. errln('back to ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  1043. {$endif DPMIEXCP_DEBUG}
  1044. end
  1045. else
  1046. begin
  1047. get_rm_interrupt(cbrk_vect, cbrk_ori);
  1048. {$ifdef DPMIEXCP_DEBUG}
  1049. errln('ori rm cbrk '+hexstr(cbrk_ori.segment,4)+':'+hexstr(longint(cbrk_ori.offset),4));
  1050. {$endif DPMIEXCP_DEBUG}
  1051. get_rm_callback(@djgpp_cbrk_hdlr, cbrk_regs, cbrk_rmcb);
  1052. set_rm_interrupt(cbrk_vect, cbrk_rmcb);
  1053. {$ifdef DPMIEXCP_DEBUG}
  1054. errln('now rm cbrk '+hexstr(cbrk_rmcb.segment,4)+':'+hexstr(longint(cbrk_rmcb.offset),4));
  1055. {$endif DPMIEXCP_DEBUG}
  1056. cbrk_hooked := true;
  1057. end;
  1058. end;
  1059. {$endif CREATE_C_FUNCTIONS}
  1060. function dpmi_set_coprocessor_emulation(flag : longint) : longint;cdecl;
  1061. var
  1062. res : longint;
  1063. begin
  1064. asm
  1065. pushl %ebx
  1066. movl flag,%ebx
  1067. movl $0xe01,%eax
  1068. int $0x31
  1069. jc .L_coproc_error
  1070. xorl %eax,%eax
  1071. .L_coproc_error:
  1072. movl %eax,res
  1073. popl %ebx
  1074. end;
  1075. dpmi_set_coprocessor_emulation:=res;
  1076. end;
  1077. {$ifdef CREATE_C_FUNCTIONS}
  1078. var
  1079. _swap_in : pointer;external name '_swap_in';
  1080. _swap_out : pointer;external name '_swap_out';
  1081. _exception_exit : pointer;external name '_exception_exit';
  1082. const
  1083. STUBINFO_END = $54;
  1084. procedure __maybe_fix_w2k_ntvdm_bug;cdecl;[public,alias : '___maybe_fix_w2k_ntvdm_bug'];
  1085. var
  1086. psp_sel : word;
  1087. begin
  1088. if _os_trueversion = $532 then
  1089. begin
  1090. { avoid NTVDM bug on NT,2000 or XP }
  1091. { see dpmiexcp.c source of DJGPP PM }
  1092. if stub_info^.size < STUBINFO_END then
  1093. begin
  1094. asm
  1095. movb $0x51,%ah
  1096. int $0x21
  1097. movb $0x50,%ah
  1098. int $0x21
  1099. end;
  1100. end
  1101. else
  1102. begin
  1103. psp_sel:=stub_info^.psp_selector;
  1104. asm
  1105. pushl %ebx
  1106. movw psp_sel,%bx
  1107. movb $0x50,%ah
  1108. int $0x21
  1109. popl %ebx
  1110. end;
  1111. end;
  1112. end;
  1113. end;
  1114. procedure dpmiexcp_exit{(status : longint)};cdecl;[public,alias : 'excep_exit'];
  1115. { We need to restore hardware interrupt handlers even if somebody calls
  1116. `_exit' directly, or else we crash the machine in nested programs.
  1117. We only toggle the handlers if the original keyboard handler is intact
  1118. (otherwise, they might have already toggled them). }
  1119. begin
  1120. (*
  1121. void __maybe_fix_w2k_ntvdm_bug(void)
  1122. if (_osmajor == 5 && _get_dos_version(1) == 0x532) /* Windows NT, 2000 or XP? */
  1123. {
  1124. if(_stubinfo->size < STUBINFO_END) /* V2load'ed image, stubinfo PSP bad */
  1125. /* Protected mode call to SetPSP - uses BX from GetPSP (0x51) */
  1126. asm volatile("movb $0x51, %%ah \n\
  1127. int $0x21 \n\
  1128. movb $0x50, %%ah \n\
  1129. int $0x21 "
  1130. : : : "ax", "bx" ); /* output, input, regs */
  1131. else
  1132. /* Protected mode call to SetPSP - may destroy RM PSP if not extended */
  1133. asm volatile("movw %0, %%bx \n\
  1134. movb $0x50, %%ah \n\
  1135. int $0x21 "
  1136. : /* output */
  1137. : "g" (_stubinfo->psp_selector) /* input */
  1138. : "ax", "bx" ); /* regs */
  1139. }
  1140. *)
  1141. if (exceptions_on) then
  1142. djgpp_exception_toggle;
  1143. _exception_exit:=nil;
  1144. _swap_in:=nil;
  1145. _swap_out:=nil;
  1146. __maybe_fix_w2k_ntvdm_bug;
  1147. { restore the FPU state }
  1148. dpmi_set_coprocessor_emulation(1);
  1149. end;
  1150. { _exit in dpmiexcp.c
  1151. is already present in v2prt0.as PM}
  1152. { used by dos.pp for swap vectors }
  1153. procedure dpmi_swap_in;cdecl;[public,alias : 'swap_in'];
  1154. begin
  1155. if not (exceptions_on) then
  1156. djgpp_exception_toggle;
  1157. end;
  1158. procedure dpmi_swap_out;cdecl;[public,alias : 'swap_out'];
  1159. begin
  1160. if (exceptions_on) then
  1161. djgpp_exception_toggle;
  1162. end;
  1163. var
  1164. ___djgpp_app_DS : word;external name '___djgpp_app_DS';
  1165. ___djgpp_our_DS : word;external name '___djgpp_our_DS';
  1166. __djgpp_sigint_mask : word;external name '___djgpp_sigint_mask';
  1167. __djgpp_sigint_key : word;external name '___djgpp_sigint_key';
  1168. __djgpp_sigquit_mask : word;external name '___djgpp_sigquit_mask';
  1169. __djgpp_sigquit_key : word;external name '___djgpp_sigquit_key';
  1170. { to avoid loading of C lib version of dpmiexcp
  1171. I need to have all exported assembler labels
  1172. of dpmiexcp.c in this unit.
  1173. DJGPP v2.03 add to new functions:
  1174. __djgpp_set_sigint_key
  1175. __djgpp_set_sigquit_key
  1176. that I implement here simply translating C code PM }
  1177. Const
  1178. LSHIFT = 1;
  1179. RSHIFT = 2;
  1180. CTRL = 4;
  1181. ALT = 8;
  1182. DEFAULT_SIGINT = $042e; { Ctrl-C: scan code 2Eh, kb status 04h }
  1183. DEFAULT_SIGQUIT = $042b; { Ctrl-\: scan code 2Bh, kb status 04h }
  1184. DEFAULT_SIGINT_98 = $042b; { Ctrl-C: scan code 2Bh, kb status 04h }
  1185. DEFAULT_SIGQUIT_98 = $040d; { Ctrl-\: scan code 0Dh, kb status 04h }
  1186. { Make it so the key NEW_KEY will generate the signal SIG.
  1187. NEW_KEY must include the keyboard status byte in bits 8-15 and the
  1188. scan code in bits 0-7. }
  1189. function set_signal_key(sig,new_key : longint) : longint;
  1190. type
  1191. pword = ^word;
  1192. var
  1193. old_key : longint;
  1194. mask,key : pword;
  1195. kb_status : word;
  1196. begin
  1197. if (sig = SIGINT) then
  1198. begin
  1199. mask := @__djgpp_sigint_mask;
  1200. key := @__djgpp_sigint_key;
  1201. end
  1202. else if (sig = SIGQUIT) then
  1203. begin
  1204. mask := @__djgpp_sigquit_mask;
  1205. key := @__djgpp_sigquit_key;
  1206. end
  1207. else
  1208. exit(-1);
  1209. old_key := key^;
  1210. key^ := new_key and $ffff;
  1211. kb_status := key^ shr 8;
  1212. mask^ := $f; { Alt, Ctrl and Shift bits only }
  1213. { Mask off the RShift bit unless they explicitly asked for it.
  1214. Our keyboard handler pretends that LShift is pressed when they
  1215. press RShift. }
  1216. if ((kb_status and RSHIFT) = 0) then
  1217. mask^ :=mask^ and not RSHIFT;
  1218. { Mask off the LShift bit if any of the Ctrl or Alt are set
  1219. since Shift doesn't matter when Ctrl and/or Alt are pressed. }
  1220. if (kb_status and (CTRL or ALT))<>0 then
  1221. mask^:= mask^ and not LSHIFT;
  1222. exit(old_key);
  1223. end;
  1224. function __djgpp_set_sigint_key(new_key : longint) : longint;cdecl;
  1225. begin
  1226. __djgpp_set_sigint_key:=set_signal_key(SIGINT, new_key);
  1227. end;
  1228. function __djgpp_set_sigquit_key(new_key : longint) : longint;cdecl;
  1229. begin
  1230. __djgpp_set_sigquit_key:=set_signal_key(SIGQUIT, new_key);
  1231. end;
  1232. function __djgpp__traceback_exit(sig : longint) : longint;cdecl;
  1233. var
  1234. fake_exception : texception_state;
  1235. begin
  1236. if (sig >= SIGABRT) and (sig <= SIGTRAP) then
  1237. begin
  1238. if djgpp_exception_state_ptr=nil then
  1239. begin
  1240. { This is a software signal, like SIGABRT or SIGKILL.
  1241. Fill the exception structure, so we get the traceback. }
  1242. djgpp_exception_state_ptr:=@fake_exception;
  1243. if (dpmi_setjmp(pdpmi_jmp_buf(djgpp_exception_state_ptr)^)<>0) then
  1244. begin
  1245. errln('Bad longjmp to __djgpp_exception_state--aborting');
  1246. do_faulting_finish_message(true); { does not return }
  1247. end
  1248. else
  1249. { Fake the exception number. 7Ah is the last one hardwired
  1250. inside exceptn.S, for SIGQUIT. }
  1251. djgpp_exception_state_ptr^.__signum:=$7a + 1 + sig - SIGABRT;
  1252. end;
  1253. end;
  1254. print_signal_name(sig);
  1255. if assigned(djgpp_exception_state_ptr) then
  1256. { This exits, does not return. }
  1257. do_faulting_finish_message(djgpp_exception_state_ptr=@fake_exception);
  1258. __exit(-1);
  1259. __djgpp__traceback_exit:=0;
  1260. end;
  1261. procedure djgpp_int0;
  1262. begin
  1263. HandleError(200);
  1264. end;
  1265. procedure djgpp_exception_setup;cdecl;
  1266. [public,alias : '___djgpp_exception_setup'];
  1267. var
  1268. temp_kbd,
  1269. temp_npx : pointer;
  1270. _except,
  1271. old_kbd : tseginfo;
  1272. locksize : longint;
  1273. i : longint;
  1274. begin
  1275. if assigned(_exception_exit) then
  1276. exit;
  1277. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1278. begin
  1279. __djgpp_set_sigint_key(DEFAULT_SIGINT);
  1280. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT);
  1281. end
  1282. else
  1283. begin { for PC98 }
  1284. __djgpp_set_sigint_key(DEFAULT_SIGINT_98);
  1285. __djgpp_set_sigquit_key(DEFAULT_SIGQUIT_98);
  1286. end;
  1287. _exception_exit:=@dpmiexcp_exit;
  1288. _swap_in:=@dpmi_swap_in;
  1289. _swap_out:=@dpmi_swap_out;
  1290. { reset signals }
  1291. for i := 0 to SIGMAX do
  1292. signal_list[i] := SignalHandler(@SIG_DFL);
  1293. { app_DS only used when converting HW interrupts to exceptions }
  1294. asm
  1295. movw %ds,___djgpp_app_DS
  1296. movw %ds,___djgpp_our_DS
  1297. end;
  1298. djgpp_dos_sel:=dosmemselector;
  1299. { lock addresses which may see HW interrupts }
  1300. lock_code(@djgpp_hw_lock_start,@djgpp_hw_lock_end-@djgpp_hw_lock_start);
  1301. _except.segment:=get_cs;
  1302. { the first 18 exceptions start at offset +8 since exception
  1303. #18 and #19 had to be put in front of the table. }
  1304. _except.offset:=@djgpp_exception_table + 8;
  1305. for i:=0 to 17 do
  1306. begin
  1307. except_ori[i] := _except; { New value to set }
  1308. inc(_except.offset,4); { This is the size of push n, jmp }
  1309. end;
  1310. except_ori[18].segment := _except.segment;
  1311. except_ori[19].segment := _except.segment;
  1312. except_ori[18].offset := @djgpp_exception_table;
  1313. except_ori[19].offset := @djgpp_exception_table + 4;
  1314. kbd_ori.segment:=_except.segment;
  1315. npx_ori.segment:=_except.segment;
  1316. npx_ori.offset:=@djgpp_npx_hdlr;
  1317. int0_ori.segment:=_except.segment;
  1318. int0_ori.offset:=@djgpp_int0;
  1319. if (go32_info_block.linear_address_of_primary_screen <> $a0000) then
  1320. kbd_ori.offset:=@djgpp_kbd_hdlr
  1321. else
  1322. begin
  1323. kbd_ori.offset:=@djgpp_kbd_hdlr_pc98;
  1324. cbrk_vect := $06;
  1325. _except.offset:=@djgpp_iret;
  1326. set_pm_interrupt($23,_except);
  1327. end;
  1328. _except.offset:=@djgpp_i24;
  1329. set_pm_interrupt($24, _except);
  1330. get_pm_interrupt(9,djgpp_old_kbd);
  1331. djgpp_exception_toggle; { Set new values & save old values }
  1332. { get original video mode and save }
  1333. old_video_mode := farpeekb(dosmemselector, $449);
  1334. end;
  1335. {$endif CREATE_C_FUNCTIONS}
  1336. function djgpp_set_ctrl_c(enable : boolean) : boolean;cdecl;
  1337. begin
  1338. djgpp_set_ctrl_c:=(djgpp_hwint_flags and 1)=0;
  1339. if enable then
  1340. djgpp_hwint_flags:=djgpp_hwint_flags and (not 1)
  1341. else
  1342. djgpp_hwint_flags:=djgpp_hwint_flags or 1;
  1343. end;
  1344. {$ifdef CREATE_C_FUNCTIONS}
  1345. function c_djgpp_set_ctrl_c(enable : longint) : boolean;cdecl;[public,alias : '___djgpp_set_ctrl_c'];
  1346. begin
  1347. c_djgpp_set_ctrl_c:=djgpp_set_ctrl_c(boolean(enable));
  1348. end;
  1349. {$endif def CREATE_C_FUNCTIONS}
  1350. {$ifdef IN_DPMIEXCP_UNIT}
  1351. procedure ResetDefaultHandlers;
  1352. begin
  1353. Signal(SIGSEGV,@SIG_DFL);
  1354. Signal(SIGFPE,@SIG_DFL);
  1355. Signal(SIGNOFP,@SIG_DFL);
  1356. Signal(SIGTRAP,@SIG_DFL);
  1357. Signal(SIGTIMR,@SIG_DFL);
  1358. Signal(SIGINT,@SIG_DFL);
  1359. Signal(SIGQUIT,@SIG_DFL);
  1360. Signal(SIGILL,@SIG_DFL);
  1361. end;
  1362. {$endif IN_DPMIEXCP_UNIT}
  1363. procedure InitDPMIExcp;
  1364. begin
  1365. {$ifdef CREATE_C_FUNCTIONS}
  1366. djgpp_ds_alias:=v2prt0_ds_alias;
  1367. djgpp_exception_setup;
  1368. {$endif CREATE_C_FUNCTIONS}
  1369. end;
  1370. {$ifndef IN_SYSTEM}
  1371. begin
  1372. {$ifdef CREATE_C_FUNCTIONS}
  1373. InitDPMIExcp;
  1374. {$else not CREATE_C_FUNCTIONS}
  1375. ResetDefaultHandlers;
  1376. {$endif CREATE_C_FUNCTIONS}
  1377. end.
  1378. {$else IN_SYSTEM}
  1379. { Default handler for SIGINT. Default action is to quit silently.
  1380. However, if a CtrlBreakHandler has been installed, call it and continue if
  1381. it returned true.
  1382. If you want RTE 217 to be generated, use HandleException instead as the
  1383. SIGINT handler }
  1384. function SIGINT_Handler(x:longint):longint;cdecl;
  1385. var
  1386. iscbreak : boolean;
  1387. begin
  1388. iscbreak:=assigned(djgpp_exception_state_ptr) and
  1389. (djgpp_exception_state_ptr^.__signum=$1b);
  1390. if assigned(CtrlBreakHandler) and CtrlBreakHandler(iscbreak) then
  1391. exit(0); //no need to do cleanups, dpmi_longjmp will do it for us
  1392. halt;
  1393. end;
  1394. const
  1395. FPU_ControlWord : word = $1332;
  1396. function HandleException(sig : longint) : longint;cdecl;
  1397. var
  1398. truesig : longint;
  1399. ErrorOfSig : longint;
  1400. FpuStatus,FPUControl : word;
  1401. eip,ebp : longint;
  1402. begin
  1403. if assigned(djgpp_exception_state_ptr) then
  1404. truesig:=djgpp_exception_state_ptr^.__signum
  1405. else
  1406. truesig:=sig;
  1407. ErrorOfSig:=0;
  1408. case truesig of
  1409. {exception_names : array[0..EXCEPTIONCOUNT-1] of PAnsiChar = (}
  1410. 0 : ErrorOfSig:=200; {'Division by Zero'}
  1411. 5 : ErrorOfSig:=201; {'Bounds Check'}
  1412. 12 : ErrorOfSig:=202; {'Stack Fault'}
  1413. 7, {'Coprocessor not available'}
  1414. 9, {'Coprocessor overrun'}
  1415. SIGNOFP : ErrorOfSig:=207;
  1416. 16,SIGFPE,$75 : begin
  1417. { This needs special handling }
  1418. { to discriminate between 205,206 and 207 }
  1419. if truesig=$75 then
  1420. fpustatus:=djgpp_exception_state_ptr^.__sigmask and $ffff
  1421. else
  1422. asm
  1423. fnstsw %ax
  1424. fnclex
  1425. movw %ax,fpustatus
  1426. end;
  1427. if (FpuStatus and FPU_Invalid)<>0 then
  1428. ErrorOfSig:=216
  1429. else if (FpuStatus and FPU_Denormal)<>0 then
  1430. ErrorOfSig:=216
  1431. else if (FpuStatus and FPU_DivisionByZero)<>0 then
  1432. ErrorOfSig:=208
  1433. else if (FpuStatus and FPU_Overflow)<>0 then
  1434. ErrorOfSig:=205
  1435. else if (FpuStatus and FPU_Underflow)<>0 then
  1436. ErrorOfSig:=206
  1437. else
  1438. ErrorOfSig:=207; {'Coprocessor Error'}
  1439. { if exceptions then Reset FPU and reload control word }
  1440. if (FPUStatus and FPU_ExceptionMask)<>0 then
  1441. SysResetFPU;
  1442. end;
  1443. 4 : ErrorOfSig:=215; {'Overflow'}
  1444. 1, {'Debug'}
  1445. 2, {'NMI'}
  1446. 3, {'Breakpoint'}
  1447. 6, {'Invalid Opcode'}
  1448. 8, {'Double Fault'}
  1449. 10, {'Invalid TSS'}
  1450. 11, {'Segment Not Present'}
  1451. 13, {'General Protection Fault'}
  1452. 14, {'Page fault'}
  1453. 15, {' ',}
  1454. 17, {'Alignment Check',}
  1455. 18, {'Machine Check',}
  1456. 19, {'SSE FP error'}
  1457. SIGSEGV,SIGTRAP,SIGTIMR,SIGQUIT,SIGILL:
  1458. ErrorOfSig:=216;
  1459. $1b, $79, SIGINT : ErrorOfSig:=217;
  1460. end;
  1461. if assigned(djgpp_exception_state_ptr) then
  1462. Begin
  1463. if exception_level>0 then
  1464. dec(exception_level);
  1465. eip:=djgpp_exception_state_ptr^.__eip;
  1466. ebp:=djgpp_exception_state_ptr^.__ebp;
  1467. djgpp_exception_state_ptr:=djgpp_exception_state_ptr^.__exception_ptr;
  1468. HandleErrorAddrFrame(ErrorOfSig,pointer(eip),pointer(ebp));
  1469. End
  1470. else
  1471. { probably higher level is required }
  1472. HandleErrorFrame(ErrorOfSig,get_caller_frame(get_frame));
  1473. HandleException:=0;
  1474. end;
  1475. procedure InstallDefaultHandlers;
  1476. begin
  1477. Signal(SIGSEGV,@HandleException);
  1478. Signal(SIGFPE,@HandleException);
  1479. Signal(SIGNOFP,@HandleException);
  1480. Signal(SIGTRAP,@HandleException);
  1481. Signal(SIGTIMR,@HandleException);
  1482. Signal(SIGINT,@SIGINT_Handler);
  1483. Signal(SIGQUIT,@HandleException);
  1484. Signal(SIGILL,@HandleException);
  1485. end;
  1486. {$endif IN_SYSTEM}