i8086.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  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. procedure fpc_cpuinit;
  13. begin
  14. end;
  15. {$ifndef FPC_SYSTEM_HAS_FILLCHAR}
  16. {$define FPC_SYSTEM_HAS_FILLCHAR}
  17. procedure FillChar(var x;count:SizeInt;value:byte);assembler;nostackframe;
  18. asm
  19. mov bx, sp
  20. mov cx, ss:[bx + 4 + extra_param_offset] // count
  21. or cx, cx
  22. jle @@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. {$ifndef FPC_SYSTEM_HAS_MOVE}
  100. {$define FPC_SYSTEM_HAS_MOVE}
  101. procedure Move(const source;var dest;count:SizeInt);[public, alias: 'FPC_MOVE'];assembler;nostackframe;
  102. asm
  103. mov bx, sp
  104. mov cx, ss:[bx + 2 + extra_param_offset] // count
  105. or cx, cx
  106. jle @@Done
  107. mov ax, ds // for far data models, backup ds; for near data models, use to initialize es
  108. {$ifdef FPC_X86_DATA_NEAR}
  109. mov es, ax
  110. mov si, ss:[bx + 6 + extra_param_offset] // @source
  111. mov di, ss:[bx + 4 + extra_param_offset] // @dest
  112. {$else FPC_X86_DATA_NEAR}
  113. lds si, ss:[bx + 8 + extra_param_offset] // @source
  114. les di, ss:[bx + 4 + extra_param_offset] // @dest
  115. {$endif FPC_X86_DATA_NEAR}
  116. cmp si, di
  117. jb @@BackwardsMove
  118. {$ifdef FPC_ENABLED_CLD}
  119. cld
  120. {$endif FPC_ENABLED_CLD}
  121. shr cx, 1
  122. rep movsw
  123. adc cx, cx
  124. rep movsb
  125. jmp @@AfterMove // todo, add mov ds,ax & ret here for performance reasons
  126. @@BackwardsMove:
  127. std
  128. add si, cx
  129. add di, cx
  130. dec si
  131. dec di
  132. rep movsb // todo: movsw
  133. cld
  134. @@AfterMove:
  135. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  136. mov ds, ax
  137. {$endif}
  138. @@Done:
  139. end;
  140. {$endif FPC_SYSTEM_HAS_MOVE}
  141. {$define FPC_SYSTEM_HAS_SPTR}
  142. Function Sptr : Pointer;assembler;nostackframe;
  143. asm
  144. mov ax, sp
  145. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  146. mov dx, ss
  147. {$endif}
  148. end;
  149. {$define FPC_SYSTEM_HAS_PTR}
  150. function Ptr(sel,off: Word):farpointer;{$ifdef SYSTEMINLINE}inline;{$endif}assembler;nostackframe;
  151. asm
  152. mov si, sp
  153. mov ax, ss:[si + 2 + extra_param_offset] // off
  154. mov dx, ss:[si + 4 + extra_param_offset] // sel
  155. end;
  156. {$define FPC_SYSTEM_HAS_CSEG}
  157. function CSeg: Word;{$ifdef SYSTEMINLINE}inline;{$endif}assembler;nostackframe;
  158. asm
  159. mov ax, cs
  160. end;
  161. {$define FPC_SYSTEM_HAS_DSEG}
  162. function DSeg: Word;{$ifdef SYSTEMINLINE}inline;{$endif}assembler;nostackframe;
  163. asm
  164. mov ax, ds
  165. end;
  166. {$define FPC_SYSTEM_HAS_SSEG}
  167. function SSeg: Word;{$ifdef SYSTEMINLINE}inline;{$endif}assembler;nostackframe;
  168. asm
  169. mov ax, ss
  170. end;
  171. {$IFNDEF INTERNAL_BACKTRACE}
  172. {$define FPC_SYSTEM_HAS_GET_FRAME}
  173. function get_frame:pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  174. asm
  175. mov ax, bp
  176. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  177. mov dx, ss
  178. {$endif}
  179. end;
  180. {$ENDIF not INTERNAL_BACKTRACE}
  181. {$define FPC_SYSTEM_HAS_GET_PC_ADDR}
  182. Function Get_pc_addr : CodePointer;assembler;nostackframe;
  183. asm
  184. mov bx, sp
  185. mov ax, ss:[bx]
  186. {$ifdef FPC_X86_CODE_FAR}
  187. mov dx, ss:[bx+2]
  188. {$endif FPC_X86_CODE_FAR}
  189. end;
  190. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  191. function get_caller_addr(framebp:pointer;addr:codepointer=nil):codepointer;nostackframe;assembler;
  192. asm
  193. mov si, sp
  194. {$ifdef FPC_X86_CODE_FAR}
  195. xor dx, dx
  196. {$endif FPC_X86_CODE_FAR}
  197. {$ifdef FPC_X86_DATA_NEAR}
  198. mov ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  199. or ax, ax
  200. jz @@Lg_a_null
  201. xchg ax, bx // 1 byte shorter than a mov
  202. mov ax, [bx+2]
  203. {$ifdef FPC_X86_CODE_FAR}
  204. mov dx, [bx+4]
  205. {$endif FPC_X86_CODE_FAR}
  206. {$else FPC_X86_DATA_NEAR}
  207. les ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  208. mov dx, es
  209. or dx, ax
  210. jz @@Lg_a_null
  211. xchg ax, bx // 1 byte shorter than a mov
  212. mov ax, es:[bx+2]
  213. {$ifdef FPC_X86_CODE_FAR}
  214. mov dx, es:[bx+4]
  215. {$endif FPC_X86_CODE_FAR}
  216. {$endif FPC_X86_DATA_NEAR}
  217. @@Lg_a_null:
  218. end;
  219. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  220. function get_caller_frame(framebp:pointer;addr:codepointer=nil):pointer;nostackframe;assembler;
  221. asm
  222. {$ifdef FPC_X86_DATA_NEAR}
  223. mov si, sp
  224. mov ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  225. or ax, ax
  226. jz @@Lgnf_null
  227. xchg ax, si // 1 byte shorter than a mov
  228. lodsw
  229. @@Lgnf_null:
  230. {$else FPC_X86_DATA_NEAR}
  231. mov si, sp
  232. les ax, ss:[si + 4 + extra_param_offset + extra_param_offset] // framebp
  233. mov dx, es
  234. or dx, ax
  235. jz @@Lgnf_null
  236. xchg ax, si // 1 byte shorter than a mov
  237. seges lodsw
  238. mov dx, es
  239. @@Lgnf_null:
  240. {$endif FPC_X86_DATA_NEAR}
  241. end;
  242. {TODO: use smallint?}
  243. function InterLockedDecrement (var Target: longint) : longint;nostackframe;assembler;
  244. asm
  245. mov si, sp
  246. {$ifdef FPC_X86_DATA_NEAR}
  247. mov bx, ss:[si + 2 + extra_param_offset] // Target
  248. {$else FPC_X86_DATA_NEAR}
  249. mov cx, ds
  250. lds bx, ss:[si + 2 + extra_param_offset] // Target
  251. {$endif FPC_X86_DATA_NEAR}
  252. pushf
  253. cli
  254. sub word [bx], 1
  255. sbb word [bx+2], 0
  256. mov ax, [bx]
  257. mov dx, [bx+2]
  258. popf
  259. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  260. mov ds, cx
  261. {$endif}
  262. end;
  263. {TODO: use smallint?}
  264. function InterLockedIncrement (var Target: longint) : longint;nostackframe;assembler;
  265. asm
  266. mov si, sp
  267. {$ifdef FPC_X86_DATA_NEAR}
  268. mov bx, ss:[si + 2 + extra_param_offset] // Target
  269. {$else FPC_X86_DATA_NEAR}
  270. mov cx, ds
  271. lds bx, ss:[si + 2 + extra_param_offset] // Target
  272. {$endif FPC_X86_DATA_NEAR}
  273. pushf
  274. cli
  275. add word [bx], 1
  276. adc word [bx+2], 0
  277. mov ax, [bx]
  278. mov dx, [bx+2]
  279. popf
  280. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  281. mov ds, cx
  282. {$endif}
  283. end;
  284. {TODO: use smallint?}
  285. function InterLockedExchange (var Target: longint;Source : longint) : longint;nostackframe;assembler;
  286. asm
  287. mov si, sp
  288. {$ifdef FPC_X86_DATA_NEAR}
  289. mov bx, ss:[si + 6 + extra_param_offset] // Target
  290. {$else FPC_X86_DATA_NEAR}
  291. mov cx, ds
  292. lds bx, ss:[si + 6 + extra_param_offset] // Target
  293. {$endif FPC_X86_DATA_NEAR}
  294. mov ax, ss:[si + 2 + extra_param_offset] // Lo(Source)
  295. mov dx, ss:[si + 4 + extra_param_offset] // Hi(Source)
  296. pushf
  297. cli
  298. xchg word [bx], ax
  299. xchg word [bx+2], dx
  300. popf
  301. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  302. mov ds, cx
  303. {$endif}
  304. end;
  305. {TODO: use smallint?}
  306. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;nostackframe;assembler;
  307. asm
  308. mov si, sp
  309. {$ifdef FPC_X86_DATA_NEAR}
  310. mov bx, ss:[si + 6 + extra_param_offset] // Target
  311. {$else FPC_X86_DATA_NEAR}
  312. mov cx, ds
  313. lds bx, ss:[si + 6 + extra_param_offset] // Target
  314. {$endif FPC_X86_DATA_NEAR}
  315. mov di, ss:[si + 2 + extra_param_offset] // Lo(Source)
  316. mov si, ss:[si + 4 + extra_param_offset] // Hi(Source)
  317. pushf
  318. cli
  319. mov ax, [bx]
  320. mov dx, [bx+2]
  321. add word [bx], di
  322. adc word [bx+2], si
  323. popf
  324. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  325. mov ds, cx
  326. {$endif}
  327. end;
  328. {TODO: use smallint?}
  329. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;assembler;
  330. asm
  331. {$ifdef FPC_X86_DATA_NEAR}
  332. mov bx, [Target] // Target
  333. {$else FPC_X86_DATA_NEAR}
  334. mov cx, ds
  335. lds bx, [Target] // Target
  336. {$endif FPC_X86_DATA_NEAR}
  337. mov di, [Comperand]
  338. mov si, [Comperand+2]
  339. pushf
  340. cli
  341. mov ax, [bx]
  342. mov dx, [bx+2]
  343. cmp ax, di
  344. jne @@not_equal
  345. cmp dx, si
  346. jne @@not_equal
  347. mov di, [NewValue]
  348. mov si, [NewValue+2]
  349. mov [bx], di
  350. mov [bx+2], si
  351. @@not_equal:
  352. popf
  353. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  354. mov ds, cx
  355. {$endif}
  356. end;
  357. {****************************************************************************
  358. BSR/BSF
  359. ****************************************************************************}
  360. const
  361. bsr8bit: array [Byte] of Byte = (
  362. $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,
  363. 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,
  364. 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,
  365. 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,
  366. 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,
  367. 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,
  368. 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,
  369. 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
  370. );
  371. bsf8bit: array [Byte] of Byte = (
  372. $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,
  373. 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,
  374. 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,
  375. 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,
  376. 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,
  377. 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,
  378. 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,
  379. 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
  380. );
  381. {$define FPC_SYSTEM_HAS_BSR_BYTE}
  382. function BsrByte(const AValue: Byte): Byte;
  383. begin
  384. BsrByte := bsr8bit[AValue];
  385. end;
  386. {$define FPC_SYSTEM_HAS_BSF_BYTE}
  387. function BsfByte(const AValue: Byte): Byte;
  388. begin
  389. BsfByte := bsf8bit[AValue];
  390. end;
  391. {$define FPC_SYSTEM_HAS_BSR_WORD}
  392. function BsrWord(const AValue: Word): Byte; assembler;
  393. asm
  394. lea bx, bsr8bit
  395. xor cl, cl
  396. mov ax, word [AValue]
  397. test ah, ah
  398. jz @@0
  399. mov cl, 8
  400. mov al, ah
  401. @@0: xlatb
  402. add al, cl
  403. end;
  404. {$define FPC_SYSTEM_HAS_BSF_WORD}
  405. function BsfWord(const AValue: Word): Byte; assembler;
  406. asm
  407. lea bx, bsf8bit
  408. xor cl, cl
  409. mov ax, word [AValue]
  410. test al, al
  411. jnz @@0
  412. or al, ah
  413. jz @@0
  414. add cl, 8
  415. @@0: xlatb
  416. add al, cl
  417. end;
  418. {$define FPC_SYSTEM_HAS_BSR_DWORD}
  419. function BsrDword(const AValue: DWord): Byte; assembler;
  420. asm
  421. lea bx, bsr8bit
  422. mov cl, 16
  423. mov ax, word [AValue+2]
  424. test ax, ax
  425. jnz @@0
  426. xor cl, cl
  427. mov ax, word [AValue]
  428. @@0: test ah, ah
  429. jz @@1
  430. add cl, 8
  431. mov al, ah
  432. @@1: xlatb
  433. add al, cl
  434. end;
  435. {$define FPC_SYSTEM_HAS_BSF_DWORD}
  436. function BsfDword(const AValue: DWord): Byte; assembler;
  437. asm
  438. lea bx, bsf8bit
  439. xor cl, cl
  440. mov ax, word [AValue]
  441. test ax, ax
  442. jnz @@0
  443. or ax, word [AValue+2]
  444. jz @@1
  445. mov cl, 16
  446. @@0: test al, al
  447. jnz @@1
  448. add cl, 8
  449. mov al, ah
  450. @@1: xlatb
  451. add al, cl
  452. end;
  453. {$define FPC_SYSTEM_HAS_BSR_QWORD}
  454. function BsrQword(const AValue: QWord): Byte; assembler;
  455. asm
  456. lea bx, bsr8bit
  457. mov cl, 48
  458. mov ax, word [AValue+6]
  459. test ax, ax
  460. jnz @@0
  461. mov cl, 32
  462. or ax, word [AValue+4]
  463. jnz @@0
  464. mov cl, 16
  465. or ax, word [AValue+2]
  466. jnz @@0
  467. xor cl, cl
  468. mov ax, word [AValue]
  469. @@0: test ah, ah
  470. jz @@1
  471. add cl, 8
  472. mov al, ah
  473. @@1: xlatb
  474. add al, cl
  475. end;
  476. {$define FPC_SYSTEM_HAS_BSF_QWORD}
  477. function BsfQword(const AValue: QWord): Byte; assembler;
  478. asm
  479. lea bx, bsf8bit
  480. xor cl, cl
  481. mov ax, word [AValue]
  482. test ax, ax
  483. jnz @@0
  484. mov cl, 16
  485. or ax, word [AValue+2]
  486. jnz @@0
  487. mov cl, 32
  488. or ax, word [AValue+4]
  489. jnz @@0
  490. xor cl, cl
  491. or ax, word [AValue+6]
  492. jz @@1
  493. mov cl, 48
  494. @@0: test al, al
  495. jnz @@1
  496. add cl, 8
  497. mov al, ah
  498. @@1: xlatb
  499. add al, cl
  500. end;
  501. {****************************************************************************
  502. HexStr
  503. ****************************************************************************}
  504. {$define FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  505. function HexStr(Val: NearPointer): ShortString;
  506. begin
  507. HexStr:=HexStr(Word(Val),4);
  508. end;
  509. function HexStr(Val: FarPointer): ShortString;
  510. type
  511. TFarPointerRec = record
  512. Offset, Segment: Word;
  513. end;
  514. begin
  515. HexStr:=HexStr(TFarPointerRec(Val).Segment,4)+':'+HexStr(TFarPointerRec(Val).Offset,4);
  516. end;
  517. function HexStr(Val: HugePointer): ShortString;{$ifdef SYSTEMINLINE}inline;{$endif}
  518. begin
  519. HexStr:=HexStr(FarPointer(Val));
  520. end;
  521. {****************************************************************************
  522. FPU
  523. ****************************************************************************}
  524. const
  525. { Internal constants for use in system unit }
  526. FPU_Invalid = 1;
  527. FPU_Denormal = 2;
  528. FPU_DivisionByZero = 4;
  529. FPU_Overflow = 8;
  530. FPU_Underflow = $10;
  531. FPU_StackUnderflow = $20;
  532. FPU_StackOverflow = $40;
  533. FPU_ExceptionMask = $ff;
  534. { Detects the FPU and initializes the Test8087 variable (and Default8087CW):
  535. 0 = NO FPU
  536. 1 = 8087
  537. 2 = 80287
  538. 3 = 80387+ }
  539. procedure DetectFPU;
  540. var
  541. localfpucw: word;
  542. begin
  543. asm
  544. xor bx, bx { initialization, 0=NO FPU }
  545. { FPU presence detection }
  546. fninit
  547. mov byte [localfpucw + 1], 0
  548. nop
  549. fnstcw localfpucw
  550. cmp byte [localfpucw + 1], 3
  551. jne @@Done { No FPU? }
  552. inc bx
  553. { FPU found; now test if it's a 8087 }
  554. and byte [localfpucw], $7F { clear the interrupt enable mask (IEM) }
  555. fldcw localfpucw
  556. fdisi { try to set the interrupt enable mask }
  557. fstcw localfpucw
  558. test byte [localfpucw], $80 { IEM set? }
  559. jnz @@Done { if yes, we have an 8087 }
  560. inc bx
  561. { we have a 287+; now test if it's a 80287 }
  562. finit
  563. fld1
  564. fldz
  565. fdiv { calculate 1/0 }
  566. fld st { copy the value }
  567. fchs { change the sign }
  568. fcompp { compare. if the FPU distinguishes +inf from -inf, it's a 387+ }
  569. fstsw localfpucw
  570. mov ah, byte [localfpucw + 1]
  571. sahf
  572. je @@Done
  573. inc bx { 387+ }
  574. @@Done:
  575. mov Test8087, bl
  576. end ['AX','BX'];
  577. if Test8087<=2 then
  578. Default8087CW:=$1330
  579. else
  580. Default8087CW:=$1332;
  581. end;
  582. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  583. Procedure SysInitFPU;
  584. var
  585. { these locals are so we don't have to hack pic code in the assembler }
  586. localfpucw: word;
  587. begin
  588. localfpucw:=Default8087CW;
  589. asm
  590. fninit
  591. fldcw localfpucw
  592. fwait
  593. end;
  594. end;
  595. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  596. Procedure SysResetFPU;
  597. var
  598. { these locals are so we don't have to hack pic code in the assembler }
  599. localfpucw: word;
  600. begin
  601. localfpucw:=Default8087CW;
  602. asm
  603. fninit
  604. fwait
  605. fldcw localfpucw
  606. end;
  607. end;
  608. {$I int32p.inc}
  609. {$I hugeptr.inc}