dpmiexcp.pp 45 KB

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