i8086.inc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2013 by the Free Pascal development team.
  4. Processor dependent implementation for the system unit for
  5. intel i8086+
  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. {$define FPC_SYSTEM_HAS_FPC_CPUINIT}
  13. procedure fpc_cpuinit;
  14. begin
  15. end;
  16. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  17. {$define FPC_SYSTEM_HAS_FILLCHAR}
  18. procedure FillChar(var x;count:SizeUInt;value:byte);assembler;nostackframe;
  19. asm
  20. mov bx, sp
  21. mov cx, ss:[bx + 4 + extra_param_offset] // count
  22. jcxz @@Done
  23. {$ifdef FPC_X86_DATA_NEAR}
  24. mov di, ss:[bx + 6 + extra_param_offset] // @x
  25. mov ax, ds
  26. mov es, ax
  27. {$else FPC_X86_DATA_NEAR}
  28. les di, ss:[bx + 6 + extra_param_offset] // @x
  29. {$endif FPC_X86_DATA_NEAR}
  30. mov al, ss:[bx + 2 + extra_param_offset] // value
  31. mov ah, al
  32. shr cx, 1
  33. {$ifdef FPC_ENABLED_CLD}
  34. cld
  35. {$endif FPC_ENABLED_CLD}
  36. rep stosw
  37. adc cx, cx
  38. rep stosb
  39. @@Done:
  40. end;
  41. {$endif FPC_SYSTEM_HAS_FILLCHAR}
  42. {$ifndef FPC_SYSTEM_HAS_FILLWORD}
  43. {$define FPC_SYSTEM_HAS_FILLWORD}
  44. procedure FillWord(var x;count : SizeInt;value : word);assembler;nostackframe;
  45. asm
  46. mov bx, sp
  47. mov cx, ss:[bx + 4 + extra_param_offset] // count
  48. or cx, cx
  49. jle @@Done
  50. {$ifdef FPC_X86_DATA_NEAR}
  51. mov di, ss:[bx + 6 + extra_param_offset] // @x
  52. mov ax, ds
  53. mov es, ax
  54. {$else FPC_X86_DATA_NEAR}
  55. les di, ss:[bx + 6 + extra_param_offset] // @x
  56. {$endif FPC_X86_DATA_NEAR}
  57. mov ax, ss:[bx + 2 + extra_param_offset] // value
  58. {$ifdef FPC_ENABLED_CLD}
  59. cld
  60. {$endif FPC_ENABLED_CLD}
  61. rep stosw
  62. @@Done:
  63. end;
  64. {$endif FPC_SYSTEM_HAS_FILLWORD}
  65. {$ifndef FPC_SYSTEM_HAS_FILLDWORD}
  66. {$define FPC_SYSTEM_HAS_FILLDWORD}
  67. procedure FillDWord(var x;count : SizeInt;value : dword);assembler;nostackframe;
  68. asm
  69. mov bx, sp
  70. mov cx, ss:[bx + 6 + extra_param_offset] // count
  71. or cx, cx
  72. jle @@Done
  73. {$ifdef FPC_X86_DATA_NEAR}
  74. mov di, ss:[bx + 8 + extra_param_offset] // @x
  75. mov ax, ds
  76. mov es, ax
  77. {$else FPC_X86_DATA_NEAR}
  78. les di, ss:[bx + 8 + extra_param_offset] // @x
  79. {$endif FPC_X86_DATA_NEAR}
  80. mov ax, ss:[bx + 2 + extra_param_offset] // lo(value)
  81. mov bx, ss:[bx + 4 + extra_param_offset] // hi(value)
  82. {$ifdef FPC_ENABLED_CLD}
  83. cld
  84. {$endif FPC_ENABLED_CLD}
  85. cmp ax, bx
  86. jne @@lo_hi_different
  87. shl cx, 1
  88. rep stosw
  89. jmp @@Done
  90. @@lo_hi_different:
  91. stosw
  92. xchg ax, bx
  93. stosw
  94. xchg ax, bx
  95. loop @@lo_hi_different
  96. @@Done:
  97. end;
  98. {$endif FPC_SYSTEM_HAS_FILLDWORD}
  99. procedure MoveData(srcseg,srcoff,destseg,destoff:Word;n:Word);assembler;nostackframe;
  100. asm
  101. mov bx, sp
  102. mov cx, ss:[bx + 2 + extra_param_offset] // count
  103. jcxz @@Done
  104. mov ax, ds // backup ds
  105. lds si, ss:[bx + 8 + extra_param_offset] // @source
  106. les di, ss:[bx + 4 + extra_param_offset] // @dest
  107. cmp si, di
  108. jb @@BackwardsMove
  109. {$ifdef FPC_ENABLED_CLD}
  110. cld
  111. {$endif FPC_ENABLED_CLD}
  112. shr cx, 1
  113. rep movsw
  114. adc cx, cx
  115. rep movsb
  116. jmp @@AfterMove // todo, add mov ds,ax & ret here for performance reasons
  117. @@BackwardsMove:
  118. std
  119. add si, cx
  120. add di, cx
  121. dec si
  122. dec di
  123. dec si
  124. dec di
  125. shr cx, 1
  126. rep movsw
  127. adc cx, cx
  128. inc si
  129. inc di
  130. rep movsb
  131. cld
  132. @@AfterMove:
  133. mov ds, ax
  134. @@Done:
  135. end;
  136. {$ifndef FPC_SYSTEM_HAS_MOVE}
  137. {$define FPC_SYSTEM_HAS_MOVE}
  138. procedure Move(const source;var dest;count:SizeUInt);[public, alias: 'FPC_MOVE'];assembler;nostackframe;
  139. asm
  140. mov bx, sp
  141. mov cx, ss:[bx + 2 + extra_param_offset] // count
  142. jcxz @@Done
  143. mov ax, ds // for far data models, backup ds; for near data models, use to initialize es
  144. {$ifdef FPC_X86_DATA_NEAR}
  145. mov es, ax
  146. mov si, ss:[bx + 6 + extra_param_offset] // @source
  147. mov di, ss:[bx + 4 + extra_param_offset] // @dest
  148. {$else FPC_X86_DATA_NEAR}
  149. lds si, ss:[bx + 8 + extra_param_offset] // @source
  150. les di, ss:[bx + 4 + extra_param_offset] // @dest
  151. {$endif FPC_X86_DATA_NEAR}
  152. cmp si, di
  153. jb @@BackwardsMove
  154. {$ifdef FPC_ENABLED_CLD}
  155. cld
  156. {$endif FPC_ENABLED_CLD}
  157. shr cx, 1
  158. rep movsw
  159. adc cx, cx
  160. rep movsb
  161. jmp @@AfterMove // todo, add mov ds,ax & ret here for performance reasons
  162. @@BackwardsMove:
  163. std
  164. add si, cx
  165. add di, cx
  166. dec si
  167. dec di
  168. dec si
  169. dec di
  170. shr cx, 1
  171. rep movsw
  172. adc cx, cx
  173. inc si
  174. inc di
  175. rep movsb
  176. cld
  177. @@AfterMove:
  178. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  179. mov ds, ax
  180. {$endif}
  181. @@Done:
  182. end;
  183. {$endif FPC_SYSTEM_HAS_MOVE}
  184. {$ifndef FPC_SYSTEM_HAS_INDEXBYTE}
  185. {$define FPC_SYSTEM_HAS_INDEXBYTE}
  186. function IndexByte(Const buf;len:SizeInt;b:byte):SizeInt; assembler; nostackframe;
  187. asm
  188. mov bx, sp
  189. mov cx, ss:[bx + 4 + extra_param_offset] // len
  190. jcxz @@NotFound
  191. {$ifdef FPC_X86_DATA_NEAR}
  192. mov di, ss:[bx + 6 + extra_param_offset] // @buf
  193. mov ax, ds
  194. mov es, ax
  195. {$else FPC_X86_DATA_NEAR}
  196. les di, ss:[bx + 6 + extra_param_offset] // @buf
  197. {$endif FPC_X86_DATA_NEAR}
  198. mov si, di // save the start of the buffer in si
  199. mov al, ss:[bx + 2 + extra_param_offset] // b
  200. {$ifdef FPC_ENABLED_CLD}
  201. cld
  202. {$endif FPC_ENABLED_CLD}
  203. repne scasb
  204. je @@Found
  205. @@NotFound:
  206. mov ax, 0FFFFh // return -1
  207. jmp @@Done
  208. @@Found:
  209. sub di, si
  210. xchg ax, di
  211. dec ax
  212. @@Done:
  213. end;
  214. {$endif FPC_SYSTEM_HAS_INDEXBYTE}
  215. {$ifndef FPC_SYSTEM_HAS_INDEXWORD}
  216. {$define FPC_SYSTEM_HAS_INDEXWORD}
  217. function IndexWord(Const buf;len:SizeInt;b:word):SizeInt; assembler; nostackframe;
  218. asm
  219. mov bx, sp
  220. mov cx, ss:[bx + 4 + extra_param_offset] // len
  221. jcxz @@NotFound
  222. {$ifdef FPC_X86_DATA_NEAR}
  223. mov di, ss:[bx + 6 + extra_param_offset] // @buf
  224. mov ax, ds
  225. mov es, ax
  226. {$else FPC_X86_DATA_NEAR}
  227. les di, ss:[bx + 6 + extra_param_offset] // @buf
  228. {$endif FPC_X86_DATA_NEAR}
  229. mov si, cx // save the length of the buffer in si
  230. mov ax, ss:[bx + 2 + extra_param_offset] // b
  231. {$ifdef FPC_ENABLED_CLD}
  232. cld
  233. {$endif FPC_ENABLED_CLD}
  234. repne scasw
  235. je @@Found
  236. @@NotFound:
  237. mov ax, 0FFFFh // return -1
  238. jmp @@Done
  239. @@Found:
  240. sub si, cx
  241. xchg ax, si
  242. dec ax
  243. @@Done:
  244. end;
  245. {$endif FPC_SYSTEM_HAS_INDEXWORD}
  246. {$ifndef FPC_SYSTEM_HAS_INDEXDWORD}
  247. {$define FPC_SYSTEM_HAS_INDEXDWORD}
  248. function IndexDWord(Const buf;len:SizeInt;b:DWord):SizeInt; assembler; nostackframe;
  249. asm
  250. mov bx, sp
  251. mov cx, ss:[bx + 6 + extra_param_offset] // len
  252. jcxz @@NotFound
  253. {$ifdef FPC_X86_DATA_NEAR}
  254. mov di, ss:[bx + 8 + extra_param_offset] // @buf
  255. mov ax, ds
  256. mov es, ax
  257. {$else FPC_X86_DATA_NEAR}
  258. les di, ss:[bx + 8 + extra_param_offset] // @buf
  259. {$endif FPC_X86_DATA_NEAR}
  260. mov si, cx // save the length of the buffer in si
  261. mov ax, ss:[bx + 2 + extra_param_offset] // b
  262. mov bx, ss:[bx + 4 + extra_param_offset]
  263. {$ifdef FPC_ENABLED_CLD}
  264. cld
  265. {$endif FPC_ENABLED_CLD}
  266. jmp @@LoopStart
  267. @@SkipWord:
  268. scasw
  269. @@LoopStart:
  270. scasw
  271. loopne @@SkipWord
  272. jne @@NotFound
  273. xchg ax, bx
  274. scasw
  275. je @@Found
  276. jcxz @@NotFound
  277. xchg ax, bx
  278. jmp @@LoopStart
  279. @@Found:
  280. sub si, cx
  281. xchg ax, si
  282. dec ax
  283. jmp @@Done
  284. @@NotFound:
  285. mov ax, 0FFFFh // return -1
  286. @@Done:
  287. end;
  288. {$endif FPC_SYSTEM_HAS_INDEXDWORD}
  289. {$ifndef FPC_SYSTEM_HAS_COMPAREBYTE}
  290. {$define FPC_SYSTEM_HAS_COMPAREBYTE}
  291. function CompareByte(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  292. asm
  293. xor ax, ax // initialize ax=0 (it's the result register, we never use it for anything else in this function)
  294. mov bx, sp
  295. mov cx, ss:[bx + 2 + extra_param_offset] // len
  296. jcxz @@Done
  297. mov dx, ds // for far data models, backup ds; for near data models, use to initialize es
  298. {$ifdef FPC_X86_DATA_NEAR}
  299. mov es, dx
  300. mov si, ss:[bx + 6 + extra_param_offset] // @buf1
  301. mov di, ss:[bx + 4 + extra_param_offset] // @buf2
  302. {$else FPC_X86_DATA_NEAR}
  303. lds si, ss:[bx + 8 + extra_param_offset] // @buf1
  304. les di, ss:[bx + 4 + extra_param_offset] // @buf2
  305. {$endif FPC_X86_DATA_NEAR}
  306. {$ifdef FPC_ENABLED_CLD}
  307. cld
  308. {$endif FPC_ENABLED_CLD}
  309. xor bx, bx
  310. shr cx, 1
  311. adc bx, bx // remainder goes to bx
  312. jcxz @@BytewiseComparison
  313. repe cmpsw
  314. je @@BytewiseComparison
  315. // we found an unequal word
  316. // let's go back and compare it bytewise
  317. mov bl, 2
  318. dec si
  319. dec si
  320. dec di
  321. dec di
  322. @@BytewiseComparison:
  323. mov cx, bx
  324. jcxz @@Equal
  325. repe cmpsb
  326. je @@Equal
  327. // ax is 0
  328. sbb ax, ax
  329. shl ax, 1
  330. inc ax
  331. @@Equal:
  332. // ax is 0
  333. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  334. mov ds, dx
  335. {$endif}
  336. @@Done:
  337. end;
  338. {$endif FPC_SYSTEM_HAS_COMPAREBYTE}
  339. {$ifndef FPC_SYSTEM_HAS_COMPAREWORD}
  340. {$define FPC_SYSTEM_HAS_COMPAREWORD}
  341. function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  342. asm
  343. xor ax, ax // initialize ax=0 (it's the result register, we never use it for anything else in this function)
  344. mov bx, sp
  345. mov cx, ss:[bx + 2 + extra_param_offset] // len
  346. jcxz @@Done
  347. mov dx, ds // for far data models, backup ds; for near data models, use to initialize es
  348. {$ifdef FPC_X86_DATA_NEAR}
  349. mov es, dx
  350. mov si, ss:[bx + 6 + extra_param_offset] // @buf1
  351. mov di, ss:[bx + 4 + extra_param_offset] // @buf2
  352. {$else FPC_X86_DATA_NEAR}
  353. lds si, ss:[bx + 8 + extra_param_offset] // @buf1
  354. les di, ss:[bx + 4 + extra_param_offset] // @buf2
  355. {$endif FPC_X86_DATA_NEAR}
  356. {$ifdef FPC_ENABLED_CLD}
  357. cld
  358. {$endif FPC_ENABLED_CLD}
  359. repe cmpsw
  360. je @@Equal
  361. // ax is 0
  362. sbb ax, ax
  363. shl ax, 1
  364. inc ax
  365. @@Equal:
  366. // ax is 0
  367. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  368. mov ds, dx
  369. {$endif}
  370. @@Done:
  371. end;
  372. {$endif FPC_SYSTEM_HAS_COMPAREWORD}
  373. {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD}
  374. {$define FPC_SYSTEM_HAS_COMPAREDWORD}
  375. function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe;
  376. asm
  377. xor ax, ax // initialize ax=0 (it's the result register, we never use it for anything else in this function)
  378. mov bx, sp
  379. mov cx, ss:[bx + 2 + extra_param_offset] // len
  380. jcxz @@Done
  381. cmp cx, 4000h
  382. jb @@NotTooBig
  383. mov cx, 4000h
  384. @@NotTooBig:
  385. shl cx, 1
  386. mov dx, ds // for far data models, backup ds; for near data models, use to initialize es
  387. {$ifdef FPC_X86_DATA_NEAR}
  388. mov es, dx
  389. mov si, ss:[bx + 6 + extra_param_offset] // @buf1
  390. mov di, ss:[bx + 4 + extra_param_offset] // @buf2
  391. {$else FPC_X86_DATA_NEAR}
  392. lds si, ss:[bx + 8 + extra_param_offset] // @buf1
  393. les di, ss:[bx + 4 + extra_param_offset] // @buf2
  394. {$endif FPC_X86_DATA_NEAR}
  395. {$ifdef FPC_ENABLED_CLD}
  396. cld
  397. {$endif FPC_ENABLED_CLD}
  398. repe cmpsw
  399. je @@Equal
  400. // ax is 0
  401. sbb ax, ax
  402. shl ax, 1
  403. inc ax
  404. shr cx, 1
  405. jnc @@Skip
  406. xchg ax, bx
  407. xor ax, ax
  408. cmpsw
  409. je @@hi_equal
  410. // ax is 0
  411. sbb ax, ax
  412. shl ax, 1
  413. inc ax
  414. jmp @@Skip
  415. @@hi_equal:
  416. xchg ax, bx
  417. @@Equal:
  418. // ax is 0
  419. @@Skip:
  420. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  421. mov ds, dx
  422. {$endif}
  423. @@Done:
  424. end;
  425. {$endif FPC_SYSTEM_HAS_COMPAREDWORD}
  426. {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  427. {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  428. function fpc_pchar_length(p:pchar):sizeint;assembler;nostackframe;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
  429. asm
  430. mov bx, sp
  431. {$ifdef FPC_X86_DATA_NEAR}
  432. mov ax, ss:[bx + 2 + extra_param_offset] // p
  433. test ax, ax
  434. jz @@Done
  435. xchg ax, di
  436. mov ax, ds
  437. mov es, ax
  438. {$else FPC_X86_DATA_NEAR}
  439. les di, ss:[bx + 2 + extra_param_offset] // p
  440. mov ax, es
  441. or ax, di
  442. jz @@Done
  443. {$endif FPC_X86_DATA_NEAR}
  444. mov cx, 0FFFFh
  445. xor ax, ax
  446. {$ifdef FPC_ENABLED_CLD}
  447. cld
  448. {$endif FPC_ENABLED_CLD}
  449. repne scasb
  450. dec ax
  451. dec ax
  452. sub ax, cx
  453. @@Done:
  454. end;
  455. {$endif FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
  456. {$ifndef FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  457. {$define FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  458. function fpc_pwidechar_length(p:pwidechar):sizeint;assembler;nostackframe;[public,alias:'FPC_PWIDECHAR_LENGTH']; compilerproc;
  459. asm
  460. mov bx, sp
  461. {$ifdef FPC_X86_DATA_NEAR}
  462. mov ax, ss:[bx + 2 + extra_param_offset] // p
  463. test ax, ax
  464. jz @@Done
  465. xchg ax, di
  466. mov ax, ds
  467. mov es, ax
  468. {$else FPC_X86_DATA_NEAR}
  469. les di, ss:[bx + 2 + extra_param_offset] // p
  470. mov ax, es
  471. or ax, di
  472. jz @@Done
  473. {$endif FPC_X86_DATA_NEAR}
  474. mov cx, 0FFFFh
  475. xor ax, ax
  476. {$ifdef FPC_ENABLED_CLD}
  477. cld
  478. {$endif FPC_ENABLED_CLD}
  479. repne scasw
  480. dec ax
  481. dec ax
  482. sub ax, cx
  483. @@Done:
  484. end;
  485. {$endif FPC_SYSTEM_HAS_FPC_PWIDECHAR_LENGTH}
  486. {$define FPC_SYSTEM_HAS_SPTR}
  487. Function Sptr : Pointer;assembler;nostackframe;
  488. asm
  489. mov ax, sp
  490. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  491. mov dx, ss
  492. {$endif}
  493. end;
  494. {$define FPC_SYSTEM_HAS_PTR}
  495. function Ptr(sel,off: Word):farpointer;{$ifdef SYSTEMINLINE}inline;{$endif}assembler;nostackframe;
  496. asm
  497. mov si, sp
  498. mov ax, ss:[si + 2 + extra_param_offset] // off
  499. mov dx, ss:[si + 4 + extra_param_offset] // sel
  500. end;
  501. {$define FPC_SYSTEM_HAS_CSEG}
  502. function CSeg: Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  503. begin
  504. CSeg:=fpc_x86_get_cs;
  505. end;
  506. {$define FPC_SYSTEM_HAS_DSEG}
  507. function DSeg: Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  508. begin
  509. DSeg:=fpc_x86_get_ds;
  510. end;
  511. {$define FPC_SYSTEM_HAS_SSEG}
  512. function SSeg: Word;{$ifdef SYSTEMINLINE}inline;{$endif}
  513. begin
  514. SSeg:=fpc_x86_get_ss;
  515. end;
  516. {$IFNDEF INTERNAL_BACKTRACE}
  517. {$define FPC_SYSTEM_HAS_GET_FRAME}
  518. function get_frame:pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  519. asm
  520. mov ax, bp
  521. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  522. mov dx, ss
  523. {$endif}
  524. end;
  525. {$ENDIF not INTERNAL_BACKTRACE}
  526. {$define FPC_SYSTEM_HAS_GET_PC_ADDR}
  527. Function Get_pc_addr : CodePointer;assembler;nostackframe;
  528. asm
  529. mov bx, sp
  530. mov ax, ss:[bx]
  531. {$ifdef FPC_X86_CODE_FAR}
  532. mov dx, ss:[bx+2]
  533. {$endif FPC_X86_CODE_FAR}
  534. end;
  535. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  536. function get_caller_addr(framebp:pointer;addr:codepointer=nil):codepointer;nostackframe;assembler;
  537. asm
  538. mov si, sp
  539. {$ifdef FPC_X86_CODE_FAR}
  540. xor dx, dx
  541. {$endif FPC_X86_CODE_FAR}
  542. {$ifdef FPC_X86_DATA_NEAR}
  543. mov ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  544. {$ifdef WIN16}
  545. mov cx, ax
  546. and al, $FE
  547. {$endif WIN16}
  548. or ax, ax
  549. jz @@Lg_a_null
  550. xchg ax, bx // 1 byte shorter than a mov
  551. mov ax, [bx+2]
  552. {$ifdef FPC_X86_CODE_FAR}
  553. {$ifdef WIN16}
  554. test cl, 1
  555. jnz @@farretaddr
  556. mov dx, ss:[si + 2 + extra_param_offset + extra_param_offset] // Seg(addr^)
  557. jmp @@retsegdone
  558. @@farretaddr:
  559. mov dx, [bx+4]
  560. @@retsegdone:
  561. {$else WIN16}
  562. mov dx, [bx+4]
  563. {$endif WIN16}
  564. {$endif FPC_X86_CODE_FAR}
  565. {$else FPC_X86_DATA_NEAR}
  566. les ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  567. {$ifdef WIN16}
  568. mov cx, ax
  569. and al, $FE
  570. {$endif WIN16}
  571. mov dx, es
  572. or dx, ax
  573. jz @@Lg_a_null
  574. xchg ax, bx // 1 byte shorter than a mov
  575. mov ax, es:[bx+2]
  576. {$ifdef FPC_X86_CODE_FAR}
  577. {$ifdef WIN16}
  578. test cl, 1
  579. jnz @@farretaddr
  580. mov dx, ss:[si + 2 + extra_param_offset + extra_param_offset] // Seg(addr^)
  581. jmp @@retsegdone
  582. @@farretaddr:
  583. mov dx, es:[bx+4]
  584. @@retsegdone:
  585. {$else WIN16}
  586. mov dx, es:[bx+4]
  587. {$endif WIN16}
  588. {$endif FPC_X86_CODE_FAR}
  589. {$endif FPC_X86_DATA_NEAR}
  590. @@Lg_a_null:
  591. end;
  592. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  593. function get_caller_frame(framebp:pointer;addr:codepointer=nil):pointer;nostackframe;assembler;
  594. asm
  595. {$ifdef FPC_X86_DATA_NEAR}
  596. mov si, sp
  597. mov ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  598. {$ifdef WIN16}
  599. and al, $FE
  600. {$endif WIN16}
  601. or ax, ax
  602. jz @@Lgnf_null
  603. xchg ax, si // 1 byte shorter than a mov
  604. lodsw
  605. @@Lgnf_null:
  606. {$else FPC_X86_DATA_NEAR}
  607. mov si, sp
  608. les ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  609. {$ifdef WIN16}
  610. and al, $FE
  611. {$endif WIN16}
  612. mov dx, es
  613. or dx, ax
  614. jz @@Lgnf_null
  615. xchg ax, si // 1 byte shorter than a mov
  616. seges lodsw
  617. {$ifdef WIN16}
  618. and al, $FE
  619. {$endif WIN16}
  620. mov dx, es
  621. @@Lgnf_null:
  622. {$endif FPC_X86_DATA_NEAR}
  623. end;
  624. function InterLockedDecrement (var Target: smallint) : smallint;nostackframe;assembler;
  625. asm
  626. mov si, sp
  627. {$ifdef FPC_X86_DATA_NEAR}
  628. mov bx, ss:[si + 2 + extra_param_offset] // Target
  629. {$else FPC_X86_DATA_NEAR}
  630. mov cx, ds
  631. lds bx, ss:[si + 2 + extra_param_offset] // Target
  632. {$endif FPC_X86_DATA_NEAR}
  633. pushf
  634. cli
  635. sub word [bx], 1
  636. mov ax, [bx]
  637. popf
  638. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  639. mov ds, cx
  640. {$endif}
  641. end;
  642. function InterLockedDecrement (var Target: longint) : longint;nostackframe;assembler;
  643. asm
  644. mov si, sp
  645. {$ifdef FPC_X86_DATA_NEAR}
  646. mov bx, ss:[si + 2 + extra_param_offset] // Target
  647. {$else FPC_X86_DATA_NEAR}
  648. mov cx, ds
  649. lds bx, ss:[si + 2 + extra_param_offset] // Target
  650. {$endif FPC_X86_DATA_NEAR}
  651. pushf
  652. cli
  653. sub word [bx], 1
  654. sbb word [bx+2], 0
  655. mov ax, [bx]
  656. mov dx, [bx+2]
  657. popf
  658. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  659. mov ds, cx
  660. {$endif}
  661. end;
  662. function InterLockedIncrement (var Target: smallint) : smallint;nostackframe;assembler;
  663. asm
  664. mov si, sp
  665. {$ifdef FPC_X86_DATA_NEAR}
  666. mov bx, ss:[si + 2 + extra_param_offset] // Target
  667. {$else FPC_X86_DATA_NEAR}
  668. mov cx, ds
  669. lds bx, ss:[si + 2 + extra_param_offset] // Target
  670. {$endif FPC_X86_DATA_NEAR}
  671. pushf
  672. cli
  673. add word [bx], 1
  674. mov ax, [bx]
  675. popf
  676. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  677. mov ds, cx
  678. {$endif}
  679. end;
  680. function InterLockedIncrement (var Target: longint) : longint;nostackframe;assembler;
  681. asm
  682. mov si, sp
  683. {$ifdef FPC_X86_DATA_NEAR}
  684. mov bx, ss:[si + 2 + extra_param_offset] // Target
  685. {$else FPC_X86_DATA_NEAR}
  686. mov cx, ds
  687. lds bx, ss:[si + 2 + extra_param_offset] // Target
  688. {$endif FPC_X86_DATA_NEAR}
  689. pushf
  690. cli
  691. add word [bx], 1
  692. adc word [bx+2], 0
  693. mov ax, [bx]
  694. mov dx, [bx+2]
  695. popf
  696. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  697. mov ds, cx
  698. {$endif}
  699. end;
  700. function InterLockedExchange (var Target: smallint;Source : smallint) : smallint;nostackframe;assembler;
  701. asm
  702. mov si, sp
  703. {$ifdef FPC_X86_DATA_NEAR}
  704. mov bx, ss:[si + 4 + extra_param_offset] // Target
  705. {$else FPC_X86_DATA_NEAR}
  706. mov cx, ds
  707. lds bx, ss:[si + 4 + extra_param_offset] // Target
  708. {$endif FPC_X86_DATA_NEAR}
  709. mov ax, ss:[si + 2 + extra_param_offset] // Source
  710. xchg word [bx], ax
  711. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  712. mov ds, cx
  713. {$endif}
  714. end;
  715. function InterLockedExchange (var Target: longint;Source : longint) : longint;nostackframe;assembler;
  716. asm
  717. mov si, sp
  718. {$ifdef FPC_X86_DATA_NEAR}
  719. mov bx, ss:[si + 6 + extra_param_offset] // Target
  720. {$else FPC_X86_DATA_NEAR}
  721. mov cx, ds
  722. lds bx, ss:[si + 6 + extra_param_offset] // Target
  723. {$endif FPC_X86_DATA_NEAR}
  724. mov ax, ss:[si + 2 + extra_param_offset] // Lo(Source)
  725. mov dx, ss:[si + 4 + extra_param_offset] // Hi(Source)
  726. pushf
  727. cli
  728. xchg word [bx], ax
  729. xchg word [bx+2], dx
  730. popf
  731. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  732. mov ds, cx
  733. {$endif}
  734. end;
  735. function InterLockedExchangeAdd (var Target: smallint;Source : smallint) : smallint;nostackframe;assembler;
  736. asm
  737. mov si, sp
  738. {$ifdef FPC_X86_DATA_NEAR}
  739. mov bx, ss:[si + 4 + extra_param_offset] // Target
  740. {$else FPC_X86_DATA_NEAR}
  741. mov cx, ds
  742. lds bx, ss:[si + 4 + extra_param_offset] // Target
  743. {$endif FPC_X86_DATA_NEAR}
  744. mov di, ss:[si + 2 + extra_param_offset] // Source
  745. pushf
  746. cli
  747. mov ax, [bx]
  748. add word [bx], di
  749. popf
  750. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  751. mov ds, cx
  752. {$endif}
  753. end;
  754. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;nostackframe;assembler;
  755. asm
  756. mov si, sp
  757. {$ifdef FPC_X86_DATA_NEAR}
  758. mov bx, ss:[si + 6 + extra_param_offset] // Target
  759. {$else FPC_X86_DATA_NEAR}
  760. mov cx, ds
  761. lds bx, ss:[si + 6 + extra_param_offset] // Target
  762. {$endif FPC_X86_DATA_NEAR}
  763. mov di, ss:[si + 2 + extra_param_offset] // Lo(Source)
  764. mov si, ss:[si + 4 + extra_param_offset] // Hi(Source)
  765. pushf
  766. cli
  767. mov ax, [bx]
  768. mov dx, [bx+2]
  769. add word [bx], di
  770. adc word [bx+2], si
  771. popf
  772. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  773. mov ds, cx
  774. {$endif}
  775. end;
  776. function InterlockedCompareExchange(var Target: smallint; NewValue: smallint; Comperand: smallint): smallint;assembler;
  777. asm
  778. {$ifdef FPC_X86_DATA_NEAR}
  779. mov bx, [Target] // Target
  780. {$else FPC_X86_DATA_NEAR}
  781. mov cx, ds
  782. lds bx, [Target] // Target
  783. {$endif FPC_X86_DATA_NEAR}
  784. mov di, [Comperand]
  785. pushf
  786. cli
  787. mov ax, [bx]
  788. cmp ax, di
  789. jne @@not_equal
  790. mov di, [NewValue]
  791. mov [bx], di
  792. @@not_equal:
  793. popf
  794. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  795. mov ds, cx
  796. {$endif}
  797. end;
  798. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;assembler;
  799. asm
  800. {$ifdef FPC_X86_DATA_NEAR}
  801. mov bx, [Target] // Target
  802. {$else FPC_X86_DATA_NEAR}
  803. mov cx, ds
  804. lds bx, [Target] // Target
  805. {$endif FPC_X86_DATA_NEAR}
  806. mov di, word [Comperand]
  807. mov si, word [Comperand+2]
  808. pushf
  809. cli
  810. mov ax, [bx]
  811. mov dx, [bx+2]
  812. cmp ax, di
  813. jne @@not_equal
  814. cmp dx, si
  815. jne @@not_equal
  816. mov di, word [NewValue]
  817. mov si, word [NewValue+2]
  818. mov [bx], di
  819. mov [bx+2], si
  820. @@not_equal:
  821. popf
  822. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  823. mov ds, cx
  824. {$endif}
  825. end;
  826. {****************************************************************************
  827. Stack checking
  828. ****************************************************************************}
  829. procedure fpc_stackcheck_i8086;[public,alias:'FPC_STACKCHECK_I8086'];compilerproc;assembler;nostackframe;
  830. const
  831. STACK_MARGIN=512;
  832. asm
  833. { on entry: AX = required stack size to check if available
  834. (function is called before stack allocation) }
  835. {$ifdef FPC_MM_HUGE}
  836. push ds
  837. push ax
  838. mov ax, SEG @DATA
  839. mov ds, ax
  840. pop ax
  841. {$endif FPC_MM_HUGE}
  842. add ax, STACK_MARGIN
  843. jc @@stack_overflow
  844. add ax, word ptr [__stkbottom]
  845. jc @@stack_overflow
  846. cmp ax, sp
  847. ja @@stack_overflow
  848. @@no_overflow:
  849. {$ifdef FPC_MM_HUGE}
  850. pop ds
  851. {$endif FPC_MM_HUGE}
  852. ret
  853. @@stack_overflow:
  854. { check StackError flag, to avoid recursive calls from the exit routines }
  855. cmp byte ptr [StackError], 1
  856. je @@no_overflow
  857. mov byte ptr [StackError], 1
  858. { cleanup return address (and maybe saved ds) from call to this function }
  859. {$if defined(FPC_MM_HUGE)}
  860. add sp, 6
  861. {$elseif defined(FPC_X86_CODE_FAR)}
  862. pop ax
  863. pop ax
  864. {$else}
  865. pop ax
  866. {$endif}
  867. { call HandleError(202) }
  868. {$ifdef CPU8086}
  869. xor ax, ax
  870. push ax
  871. mov al, 202
  872. push ax
  873. {$else}
  874. push 0
  875. push 202
  876. {$endif}
  877. call HandleError
  878. end;
  879. {****************************************************************************
  880. BSR/BSF
  881. ****************************************************************************}
  882. const
  883. bsr8bit: array [Byte] of Byte = (
  884. $ff,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  885. 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  886. 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  887. 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  888. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  889. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  890. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  891. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
  892. );
  893. bsf8bit: array [Byte] of Byte = (
  894. $ff,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  895. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  896. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  897. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  898. 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  899. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  900. 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
  901. 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
  902. );
  903. {$define FPC_SYSTEM_HAS_BSR_BYTE}
  904. function BsrByte(const AValue: Byte): Byte;
  905. begin
  906. BsrByte := bsr8bit[AValue];
  907. end;
  908. {$define FPC_SYSTEM_HAS_BSF_BYTE}
  909. function BsfByte(const AValue: Byte): Byte;
  910. begin
  911. BsfByte := bsf8bit[AValue];
  912. end;
  913. {$define FPC_SYSTEM_HAS_BSR_WORD}
  914. function BsrWord(const AValue: Word): Byte; assembler;
  915. asm
  916. lea bx, bsr8bit
  917. xor cl, cl
  918. mov ax, word [AValue]
  919. test ah, ah
  920. jz @@0
  921. mov cl, 8
  922. mov al, ah
  923. @@0: xlatb
  924. add al, cl
  925. end;
  926. {$define FPC_SYSTEM_HAS_BSF_WORD}
  927. function BsfWord(const AValue: Word): Byte; assembler;
  928. asm
  929. lea bx, bsf8bit
  930. xor cl, cl
  931. mov ax, word [AValue]
  932. test al, al
  933. jnz @@0
  934. or al, ah
  935. jz @@0
  936. add cl, 8
  937. @@0: xlatb
  938. add al, cl
  939. end;
  940. {$define FPC_SYSTEM_HAS_BSR_DWORD}
  941. function BsrDword(const AValue: DWord): Byte; assembler;
  942. asm
  943. lea bx, bsr8bit
  944. mov cl, 16
  945. mov ax, word [AValue+2]
  946. test ax, ax
  947. jnz @@0
  948. xor cl, cl
  949. mov ax, word [AValue]
  950. @@0: test ah, ah
  951. jz @@1
  952. add cl, 8
  953. mov al, ah
  954. @@1: xlatb
  955. add al, cl
  956. end;
  957. {$define FPC_SYSTEM_HAS_BSF_DWORD}
  958. function BsfDword(const AValue: DWord): Byte; assembler;
  959. asm
  960. lea bx, bsf8bit
  961. xor cl, cl
  962. mov ax, word [AValue]
  963. test ax, ax
  964. jnz @@0
  965. or ax, word [AValue+2]
  966. jz @@1
  967. mov cl, 16
  968. @@0: test al, al
  969. jnz @@1
  970. add cl, 8
  971. mov al, ah
  972. @@1: xlatb
  973. add al, cl
  974. end;
  975. {$define FPC_SYSTEM_HAS_BSR_QWORD}
  976. function BsrQword(const AValue: QWord): Byte; assembler;
  977. asm
  978. lea bx, bsr8bit
  979. mov cl, 48
  980. mov ax, word [AValue+6]
  981. test ax, ax
  982. jnz @@0
  983. mov cl, 32
  984. or ax, word [AValue+4]
  985. jnz @@0
  986. mov cl, 16
  987. or ax, word [AValue+2]
  988. jnz @@0
  989. xor cl, cl
  990. mov ax, word [AValue]
  991. @@0: test ah, ah
  992. jz @@1
  993. add cl, 8
  994. mov al, ah
  995. @@1: xlatb
  996. add al, cl
  997. end;
  998. {$define FPC_SYSTEM_HAS_BSF_QWORD}
  999. function BsfQword(const AValue: QWord): Byte; assembler;
  1000. asm
  1001. lea bx, bsf8bit
  1002. xor cl, cl
  1003. mov ax, word [AValue]
  1004. test ax, ax
  1005. jnz @@0
  1006. mov cl, 16
  1007. or ax, word [AValue+2]
  1008. jnz @@0
  1009. mov cl, 32
  1010. or ax, word [AValue+4]
  1011. jnz @@0
  1012. xor cl, cl
  1013. or ax, word [AValue+6]
  1014. jz @@1
  1015. mov cl, 48
  1016. @@0: test al, al
  1017. jnz @@1
  1018. add cl, 8
  1019. mov al, ah
  1020. @@1: xlatb
  1021. add al, cl
  1022. end;
  1023. {****************************************************************************
  1024. HexStr
  1025. ****************************************************************************}
  1026. {$define FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  1027. function HexStr(Val: NearPointer): ShortString;
  1028. begin
  1029. HexStr:=HexStr(Word(Val),4);
  1030. end;
  1031. function HexStr(Val: NearCsPointer): ShortString;
  1032. begin
  1033. HexStr:='CS:'+HexStr(Word(Val),4);
  1034. end;
  1035. function HexStr(Val: NearDsPointer): ShortString;
  1036. begin
  1037. HexStr:='DS:'+HexStr(Word(Val),4);
  1038. end;
  1039. function HexStr(Val: NearEsPointer): ShortString;
  1040. begin
  1041. HexStr:='ES:'+HexStr(Word(Val),4);
  1042. end;
  1043. function HexStr(Val: NearSsPointer): ShortString;
  1044. begin
  1045. HexStr:='SS:'+HexStr(Word(Val),4);
  1046. end;
  1047. function HexStr(Val: NearFsPointer): ShortString;
  1048. begin
  1049. HexStr:='FS:'+HexStr(Word(Val),4);
  1050. end;
  1051. function HexStr(Val: NearGsPointer): ShortString;
  1052. begin
  1053. HexStr:='GS:'+HexStr(Word(Val),4);
  1054. end;
  1055. function HexStr(Val: FarPointer): ShortString;
  1056. type
  1057. TFarPointerRec = record
  1058. Offset, Segment: Word;
  1059. end;
  1060. begin
  1061. HexStr:=HexStr(TFarPointerRec(Val).Segment,4)+':'+HexStr(TFarPointerRec(Val).Offset,4);
  1062. end;
  1063. function HexStr(Val: HugePointer): ShortString;{$ifdef SYSTEMINLINE}inline;{$endif}
  1064. begin
  1065. HexStr:=HexStr(FarPointer(Val));
  1066. end;
  1067. {****************************************************************************
  1068. FPU
  1069. ****************************************************************************}
  1070. const
  1071. { Internal constants for use in system unit }
  1072. FPU_Invalid = 1;
  1073. FPU_Denormal = 2;
  1074. FPU_DivisionByZero = 4;
  1075. FPU_Overflow = 8;
  1076. FPU_Underflow = $10;
  1077. FPU_StackUnderflow = $20;
  1078. FPU_StackOverflow = $40;
  1079. FPU_ExceptionMask = $ff;
  1080. { Detects the FPU and initializes the Test8087 variable (and Default8087CW):
  1081. 0 = NO FPU
  1082. 1 = 8087
  1083. 2 = 80287
  1084. 3 = 80387+ }
  1085. procedure DetectFPU;
  1086. var
  1087. localfpucw: word;
  1088. begin
  1089. asm
  1090. xor bx, bx { initialization, 0=NO FPU }
  1091. { FPU presence detection }
  1092. fninit
  1093. mov byte [localfpucw + 1], 0
  1094. nop
  1095. fnstcw localfpucw
  1096. cmp byte [localfpucw + 1], 3
  1097. jne @@Done { No FPU? }
  1098. inc bx
  1099. { FPU found; now test if it's a 8087 }
  1100. and byte [localfpucw], $7F { clear the interrupt enable mask (IEM) }
  1101. fldcw localfpucw
  1102. fdisi { try to set the interrupt enable mask }
  1103. fstcw localfpucw
  1104. test byte [localfpucw], $80 { IEM set? }
  1105. jnz @@Done { if yes, we have an 8087 }
  1106. inc bx
  1107. { we have a 287+; now test if it's a 80287 }
  1108. finit
  1109. fld1
  1110. fldz
  1111. fdiv { calculate 1/0 }
  1112. fld st { copy the value }
  1113. fchs { change the sign }
  1114. fcompp { compare. if the FPU distinguishes +inf from -inf, it's a 387+ }
  1115. fstsw localfpucw
  1116. mov ah, byte [localfpucw + 1]
  1117. sahf
  1118. je @@Done
  1119. inc bx { 387+ }
  1120. @@Done:
  1121. mov Test8087, bl
  1122. end ['AX','BX'];
  1123. if Test8087<=2 then
  1124. Default8087CW:=$1330
  1125. else
  1126. Default8087CW:=$1332;
  1127. end;
  1128. {$ifndef FPC_SYSTEM_HAS_SYSINITFPU}
  1129. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  1130. Procedure SysInitFPU; assembler;
  1131. asm
  1132. fninit
  1133. fldcw Default8087CW
  1134. fwait
  1135. end;
  1136. {$endif ndef FPC_SYSTEM_HAS_SYSINITFPU}
  1137. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1138. Procedure SysResetFPU; assembler;
  1139. asm
  1140. fninit
  1141. fwait
  1142. fldcw Default8087CW
  1143. end;
  1144. {$I int32p.inc}
  1145. {$I hugeptr.inc}