i8086.inc 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  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:PAnsiChar):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. {$ifdef VER3_2}
  625. function InterLockedDecrement (var Target: smallint) : smallint;nostackframe;assembler;
  626. {$else VER3_2}
  627. {$define FPC_SYSTEM_HAS_ATOMIC_DEC_16}
  628. function fpc_atomic_dec_16 (var Target: smallint) : smallint;nostackframe;assembler;
  629. {$endif VER3_2}
  630. asm
  631. mov si, sp
  632. {$ifdef FPC_X86_DATA_NEAR}
  633. mov bx, ss:[si + 2 + extra_param_offset] // Target
  634. {$else FPC_X86_DATA_NEAR}
  635. mov cx, ds
  636. lds bx, ss:[si + 2 + extra_param_offset] // Target
  637. {$endif FPC_X86_DATA_NEAR}
  638. pushf
  639. cli
  640. sub word [bx], 1
  641. mov ax, [bx]
  642. popf
  643. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  644. mov ds, cx
  645. {$endif}
  646. end;
  647. {$ifdef VER3_2}
  648. function InterLockedDecrement (var Target: longint) : longint;nostackframe;assembler;
  649. {$else VER3_2}
  650. {$define FPC_SYSTEM_HAS_ATOMIC_DEC_32}
  651. function fpc_atomic_dec_32 (var Target: longint) : longint;nostackframe;assembler;
  652. {$endif VER3_2}
  653. asm
  654. mov si, sp
  655. {$ifdef FPC_X86_DATA_NEAR}
  656. mov bx, ss:[si + 2 + extra_param_offset] // Target
  657. {$else FPC_X86_DATA_NEAR}
  658. mov cx, ds
  659. lds bx, ss:[si + 2 + extra_param_offset] // Target
  660. {$endif FPC_X86_DATA_NEAR}
  661. pushf
  662. cli
  663. sub word [bx], 1
  664. sbb word [bx+2], 0
  665. mov ax, [bx]
  666. mov dx, [bx+2]
  667. popf
  668. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  669. mov ds, cx
  670. {$endif}
  671. end;
  672. {$ifdef VER3_2}
  673. function InterLockedIncrement (var Target: smallint) : smallint;nostackframe;assembler;
  674. {$else VER3_2}
  675. {$define FPC_SYSTEM_HAS_ATOMIC_INC_16}
  676. function fpc_atomic_inc_16 (var Target: smallint) : smallint;nostackframe;assembler;
  677. {$endif VER3_2}
  678. asm
  679. mov si, sp
  680. {$ifdef FPC_X86_DATA_NEAR}
  681. mov bx, ss:[si + 2 + extra_param_offset] // Target
  682. {$else FPC_X86_DATA_NEAR}
  683. mov cx, ds
  684. lds bx, ss:[si + 2 + extra_param_offset] // Target
  685. {$endif FPC_X86_DATA_NEAR}
  686. pushf
  687. cli
  688. add word [bx], 1
  689. mov ax, [bx]
  690. popf
  691. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  692. mov ds, cx
  693. {$endif}
  694. end;
  695. {$ifdef VER3_2}
  696. function InterLockedIncrement (var Target: longint) : longint;nostackframe;assembler;
  697. {$else VER3_2}
  698. {$define FPC_SYSTEM_HAS_ATOMIC_INC_32}
  699. function fpc_atomic_inc_32 (var Target: longint) : longint;nostackframe;assembler;
  700. {$endif VER3_2}
  701. asm
  702. mov si, sp
  703. {$ifdef FPC_X86_DATA_NEAR}
  704. mov bx, ss:[si + 2 + extra_param_offset] // Target
  705. {$else FPC_X86_DATA_NEAR}
  706. mov cx, ds
  707. lds bx, ss:[si + 2 + extra_param_offset] // Target
  708. {$endif FPC_X86_DATA_NEAR}
  709. pushf
  710. cli
  711. add word [bx], 1
  712. adc word [bx+2], 0
  713. mov ax, [bx]
  714. mov dx, [bx+2]
  715. popf
  716. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  717. mov ds, cx
  718. {$endif}
  719. end;
  720. {$ifdef VER3_2}
  721. function InterLockedExchange (var Target: smallint;Source : smallint) : smallint;nostackframe;assembler;
  722. {$else VER3_2}
  723. {$define FPC_SYSTEM_HAS_ATOMIC_XCHG_16}
  724. function fpc_atomic_xchg_16 (var Target: smallint;Source : smallint) : smallint;nostackframe;assembler;
  725. {$endif VER3_2}
  726. asm
  727. mov si, sp
  728. {$ifdef FPC_X86_DATA_NEAR}
  729. mov bx, ss:[si + 4 + extra_param_offset] // Target
  730. {$else FPC_X86_DATA_NEAR}
  731. mov cx, ds
  732. lds bx, ss:[si + 4 + extra_param_offset] // Target
  733. {$endif FPC_X86_DATA_NEAR}
  734. mov ax, ss:[si + 2 + extra_param_offset] // Source
  735. xchg word [bx], ax
  736. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  737. mov ds, cx
  738. {$endif}
  739. end;
  740. {$ifdef VER3_2}
  741. function InterLockedExchange (var Target: longint;Source : longint) : longint;nostackframe;assembler;
  742. {$else VER3_2}
  743. {$define FPC_SYSTEM_HAS_ATOMIC_XCHG_32}
  744. function fpc_atomic_xchg_32 (var Target: longint;Source : longint) : longint;nostackframe;assembler;
  745. {$endif VER3_2}
  746. asm
  747. mov si, sp
  748. {$ifdef FPC_X86_DATA_NEAR}
  749. mov bx, ss:[si + 6 + extra_param_offset] // Target
  750. {$else FPC_X86_DATA_NEAR}
  751. mov cx, ds
  752. lds bx, ss:[si + 6 + extra_param_offset] // Target
  753. {$endif FPC_X86_DATA_NEAR}
  754. mov ax, ss:[si + 2 + extra_param_offset] // Lo(Source)
  755. mov dx, ss:[si + 4 + extra_param_offset] // Hi(Source)
  756. pushf
  757. cli
  758. xchg word [bx], ax
  759. xchg word [bx+2], dx
  760. popf
  761. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  762. mov ds, cx
  763. {$endif}
  764. end;
  765. {$ifdef VER3_2}
  766. function InterLockedExchangeAdd (var Target: smallint;Source : smallint) : smallint;nostackframe;assembler;
  767. {$else VER3_2}
  768. {$define FPC_SYSTEM_HAS_ATOMIC_ADD_16}
  769. function fpc_atomic_add_16 (var Target: smallint;Value : smallint) : smallint;nostackframe;assembler;
  770. {$endif VER3_2}
  771. asm
  772. mov si, sp
  773. {$ifdef FPC_X86_DATA_NEAR}
  774. mov bx, ss:[si + 4 + extra_param_offset] // Target
  775. {$else FPC_X86_DATA_NEAR}
  776. mov cx, ds
  777. lds bx, ss:[si + 4 + extra_param_offset] // Target
  778. {$endif FPC_X86_DATA_NEAR}
  779. mov di, ss:[si + 2 + extra_param_offset] // Source
  780. pushf
  781. cli
  782. mov ax, [bx]
  783. add word [bx], di
  784. popf
  785. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  786. mov ds, cx
  787. {$endif}
  788. end;
  789. {$ifdef VER3_2}
  790. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;nostackframe;assembler;
  791. {$else VER3_2}
  792. {$define FPC_SYSTEM_HAS_ATOMIC_ADD_32}
  793. function fpc_atomic_add_32 (var Target: longint;Value : longint) : longint;nostackframe;assembler;
  794. {$endif VER3_2}
  795. asm
  796. mov si, sp
  797. {$ifdef FPC_X86_DATA_NEAR}
  798. mov bx, ss:[si + 6 + extra_param_offset] // Target
  799. {$else FPC_X86_DATA_NEAR}
  800. mov cx, ds
  801. lds bx, ss:[si + 6 + extra_param_offset] // Target
  802. {$endif FPC_X86_DATA_NEAR}
  803. mov di, ss:[si + 2 + extra_param_offset] // Lo(Source)
  804. mov si, ss:[si + 4 + extra_param_offset] // Hi(Source)
  805. pushf
  806. cli
  807. mov ax, [bx]
  808. mov dx, [bx+2]
  809. add word [bx], di
  810. adc word [bx+2], si
  811. popf
  812. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  813. mov ds, cx
  814. {$endif}
  815. end;
  816. {$ifdef VER3_2}
  817. function InterlockedCompareExchange(var Target: smallint; NewValue: smallint; Comperand: smallint): smallint;assembler;
  818. {$else VER3_2}
  819. {$define FPC_SYSTEM_HAS_ATOMIC_CMP_XCHG_16}
  820. function fpc_atomic_cmp_xchg_16 (var Target: smallint; NewValue: smallint; Comparand: smallint): smallint;[public,alias:'FPC_ATOMIC_CMP_XCHG_16'];assembler;
  821. {$endif VER3_2}
  822. asm
  823. {$ifdef FPC_X86_DATA_NEAR}
  824. mov bx, [Target] // Target
  825. {$else FPC_X86_DATA_NEAR}
  826. mov cx, ds
  827. lds bx, [Target] // Target
  828. {$endif FPC_X86_DATA_NEAR}
  829. {$ifdef VER3_2}
  830. mov di, [Comperand]
  831. {$else VER3_2}
  832. mov di, [Comparand]
  833. {$endif VER3_2}
  834. pushf
  835. cli
  836. mov ax, [bx]
  837. cmp ax, di
  838. jne @@not_equal
  839. mov di, [NewValue]
  840. mov [bx], di
  841. @@not_equal:
  842. popf
  843. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  844. mov ds, cx
  845. {$endif}
  846. end;
  847. {$ifdef VER3_2}
  848. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;assembler;
  849. {$else VER3_2}
  850. {$define FPC_SYSTEM_HAS_ATOMIC_CMP_XCHG_32}
  851. function fpc_atomic_cmp_xchg_32 (var Target: longint; NewValue: longint; Comparand: longint) : longint;assembler;
  852. {$endif VER3_2}
  853. asm
  854. {$ifdef FPC_X86_DATA_NEAR}
  855. mov bx, [Target] // Target
  856. {$else FPC_X86_DATA_NEAR}
  857. mov cx, ds
  858. lds bx, [Target] // Target
  859. {$endif FPC_X86_DATA_NEAR}
  860. {$ifdef VER3_2}
  861. mov di, word [Comperand]
  862. mov si, word [Comperand+2]
  863. {$else VER3_2}
  864. mov di, word [Comparand]
  865. mov si, word [Comparand+2]
  866. {$endif VER3_2}
  867. pushf
  868. cli
  869. mov ax, [bx]
  870. mov dx, [bx+2]
  871. cmp ax, di
  872. jne @@not_equal
  873. cmp dx, si
  874. jne @@not_equal
  875. mov di, word [NewValue]
  876. mov si, word [NewValue+2]
  877. mov [bx], di
  878. mov [bx+2], si
  879. @@not_equal:
  880. popf
  881. {$if defined(FPC_X86_DATA_FAR) or defined(FPC_X86_DATA_HUGE)}
  882. mov ds, cx
  883. {$endif}
  884. end;
  885. {****************************************************************************
  886. Stack checking
  887. ****************************************************************************}
  888. procedure fpc_stackcheck_i8086;[public,alias:'FPC_STACKCHECK_I8086'];compilerproc;assembler;nostackframe;
  889. const
  890. STACK_MARGIN=512;
  891. asm
  892. { on entry: AX = required stack size to check if available
  893. (function is called before stack allocation) }
  894. {$ifdef FPC_MM_HUGE}
  895. push ds
  896. push ax
  897. mov ax, SEG @DATA
  898. mov ds, ax
  899. pop ax
  900. {$endif FPC_MM_HUGE}
  901. add ax, STACK_MARGIN
  902. jc @@stack_overflow
  903. add ax, word ptr [__stkbottom]
  904. jc @@stack_overflow
  905. cmp ax, sp
  906. ja @@stack_overflow
  907. @@no_overflow:
  908. {$ifdef FPC_MM_HUGE}
  909. pop ds
  910. {$endif FPC_MM_HUGE}
  911. ret
  912. @@stack_overflow:
  913. { check StackError flag, to avoid recursive calls from the exit routines }
  914. cmp byte ptr [StackError], 1
  915. je @@no_overflow
  916. mov byte ptr [StackError], 1
  917. { cleanup return address (and maybe saved ds) from call to this function }
  918. {$if defined(FPC_MM_HUGE)}
  919. add sp, 6
  920. {$elseif defined(FPC_X86_CODE_FAR)}
  921. pop ax
  922. pop ax
  923. {$else}
  924. pop ax
  925. {$endif}
  926. { call HandleError(202) }
  927. {$ifdef CPU8086}
  928. xor ax, ax
  929. push ax
  930. mov al, 202
  931. push ax
  932. {$else}
  933. push 0
  934. push 202
  935. {$endif}
  936. call HandleError
  937. end;
  938. {****************************************************************************
  939. BSR/BSF
  940. ****************************************************************************}
  941. const
  942. bsr8bit: array [Byte] of Byte = (
  943. $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,
  944. 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,
  945. 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,
  946. 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,
  947. 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,
  948. 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,
  949. 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,
  950. 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
  951. );
  952. bsf8bit: array [Byte] of Byte = (
  953. $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,
  954. 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,
  955. 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,
  956. 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,
  957. 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,
  958. 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,
  959. 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,
  960. 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
  961. );
  962. {$define FPC_SYSTEM_HAS_BSR_BYTE}
  963. function BsrByte(const AValue: Byte): Byte;
  964. begin
  965. BsrByte := bsr8bit[AValue];
  966. end;
  967. {$define FPC_SYSTEM_HAS_BSF_BYTE}
  968. function BsfByte(const AValue: Byte): Byte;
  969. begin
  970. BsfByte := bsf8bit[AValue];
  971. end;
  972. {$define FPC_SYSTEM_HAS_BSR_WORD}
  973. function BsrWord(const AValue: Word): Byte; assembler;
  974. asm
  975. lea bx, bsr8bit
  976. xor cl, cl
  977. mov ax, word [AValue]
  978. test ah, ah
  979. jz @@0
  980. mov cl, 8
  981. mov al, ah
  982. @@0: xlatb
  983. add al, cl
  984. end;
  985. {$define FPC_SYSTEM_HAS_BSF_WORD}
  986. function BsfWord(const AValue: Word): Byte; assembler;
  987. asm
  988. lea bx, bsf8bit
  989. xor cl, cl
  990. mov ax, word [AValue]
  991. test al, al
  992. jnz @@0
  993. or al, ah
  994. jz @@0
  995. add cl, 8
  996. @@0: xlatb
  997. add al, cl
  998. end;
  999. {$define FPC_SYSTEM_HAS_BSR_DWORD}
  1000. function BsrDword(const AValue: DWord): Byte; assembler;
  1001. asm
  1002. lea bx, bsr8bit
  1003. mov cl, 16
  1004. mov ax, word [AValue+2]
  1005. test ax, ax
  1006. jnz @@0
  1007. xor cl, cl
  1008. mov ax, word [AValue]
  1009. @@0: test ah, ah
  1010. jz @@1
  1011. add cl, 8
  1012. mov al, ah
  1013. @@1: xlatb
  1014. add al, cl
  1015. end;
  1016. {$define FPC_SYSTEM_HAS_BSF_DWORD}
  1017. function BsfDword(const AValue: DWord): Byte; assembler;
  1018. asm
  1019. lea bx, bsf8bit
  1020. xor cl, cl
  1021. mov ax, word [AValue]
  1022. test ax, ax
  1023. jnz @@0
  1024. or ax, word [AValue+2]
  1025. jz @@1
  1026. mov cl, 16
  1027. @@0: test al, al
  1028. jnz @@1
  1029. add cl, 8
  1030. mov al, ah
  1031. @@1: xlatb
  1032. add al, cl
  1033. end;
  1034. {$define FPC_SYSTEM_HAS_BSR_QWORD}
  1035. function BsrQword(const AValue: QWord): Byte; assembler;
  1036. asm
  1037. lea bx, bsr8bit
  1038. mov cl, 48
  1039. mov ax, word [AValue+6]
  1040. test ax, ax
  1041. jnz @@0
  1042. mov cl, 32
  1043. or ax, word [AValue+4]
  1044. jnz @@0
  1045. mov cl, 16
  1046. or ax, word [AValue+2]
  1047. jnz @@0
  1048. xor cl, cl
  1049. mov ax, word [AValue]
  1050. @@0: test ah, ah
  1051. jz @@1
  1052. add cl, 8
  1053. mov al, ah
  1054. @@1: xlatb
  1055. add al, cl
  1056. end;
  1057. {$define FPC_SYSTEM_HAS_BSF_QWORD}
  1058. function BsfQword(const AValue: QWord): Byte; assembler;
  1059. asm
  1060. lea bx, bsf8bit
  1061. xor cl, cl
  1062. mov ax, word [AValue]
  1063. test ax, ax
  1064. jnz @@0
  1065. mov cl, 16
  1066. or ax, word [AValue+2]
  1067. jnz @@0
  1068. mov cl, 32
  1069. or ax, word [AValue+4]
  1070. jnz @@0
  1071. xor cl, cl
  1072. or ax, word [AValue+6]
  1073. jz @@1
  1074. mov cl, 48
  1075. @@0: test al, al
  1076. jnz @@1
  1077. add cl, 8
  1078. mov al, ah
  1079. @@1: xlatb
  1080. add al, cl
  1081. end;
  1082. {****************************************************************************
  1083. HexStr
  1084. ****************************************************************************}
  1085. {$define FPC_HAS_HEXSTR_POINTER_SHORTSTR}
  1086. function HexStr(Val: NearPointer): ShortString;
  1087. begin
  1088. HexStr:=HexStr(Word(Val),4);
  1089. end;
  1090. function HexStr(Val: NearCsPointer): ShortString;
  1091. begin
  1092. HexStr:='CS:'+HexStr(Word(Val),4);
  1093. end;
  1094. function HexStr(Val: NearDsPointer): ShortString;
  1095. begin
  1096. HexStr:='DS:'+HexStr(Word(Val),4);
  1097. end;
  1098. function HexStr(Val: NearEsPointer): ShortString;
  1099. begin
  1100. HexStr:='ES:'+HexStr(Word(Val),4);
  1101. end;
  1102. function HexStr(Val: NearSsPointer): ShortString;
  1103. begin
  1104. HexStr:='SS:'+HexStr(Word(Val),4);
  1105. end;
  1106. function HexStr(Val: NearFsPointer): ShortString;
  1107. begin
  1108. HexStr:='FS:'+HexStr(Word(Val),4);
  1109. end;
  1110. function HexStr(Val: NearGsPointer): ShortString;
  1111. begin
  1112. HexStr:='GS:'+HexStr(Word(Val),4);
  1113. end;
  1114. function HexStr(Val: FarPointer): ShortString;
  1115. type
  1116. TFarPointerRec = record
  1117. Offset, Segment: Word;
  1118. end;
  1119. begin
  1120. HexStr:=HexStr(TFarPointerRec(Val).Segment,4)+':'+HexStr(TFarPointerRec(Val).Offset,4);
  1121. end;
  1122. function HexStr(Val: HugePointer): ShortString;{$ifdef SYSTEMINLINE}inline;{$endif}
  1123. begin
  1124. HexStr:=HexStr(FarPointer(Val));
  1125. end;
  1126. {****************************************************************************
  1127. FPU
  1128. ****************************************************************************}
  1129. const
  1130. { Internal constants for use in system unit }
  1131. FPU_Invalid = 1;
  1132. FPU_Denormal = 2;
  1133. FPU_DivisionByZero = 4;
  1134. FPU_Overflow = 8;
  1135. FPU_Underflow = $10;
  1136. FPU_StackUnderflow = $20;
  1137. FPU_StackOverflow = $40;
  1138. FPU_ExceptionMask = $ff;
  1139. { Detects the FPU and initializes the Test8087 variable (and Default8087CW):
  1140. 0 = NO FPU
  1141. 1 = 8087
  1142. 2 = 80287
  1143. 3 = 80387+ }
  1144. procedure DetectFPU;
  1145. var
  1146. localfpucw: word;
  1147. begin
  1148. asm
  1149. xor bx, bx { initialization, 0=NO FPU }
  1150. { FPU presence detection }
  1151. fninit
  1152. mov byte [localfpucw + 1], 0
  1153. nop
  1154. fnstcw localfpucw
  1155. cmp byte [localfpucw + 1], 3
  1156. jne @@Done { No FPU? }
  1157. inc bx
  1158. { FPU found; now test if it's a 8087 }
  1159. and byte [localfpucw], $7F { clear the interrupt enable mask (IEM) }
  1160. fldcw localfpucw
  1161. fdisi { try to set the interrupt enable mask }
  1162. fstcw localfpucw
  1163. test byte [localfpucw], $80 { IEM set? }
  1164. jnz @@Done { if yes, we have an 8087 }
  1165. inc bx
  1166. { we have a 287+; now test if it's a 80287 }
  1167. finit
  1168. fld1
  1169. fldz
  1170. fdiv { calculate 1/0 }
  1171. fld st { copy the value }
  1172. fchs { change the sign }
  1173. fcompp { compare. if the FPU distinguishes +inf from -inf, it's a 387+ }
  1174. fstsw localfpucw
  1175. mov ah, byte [localfpucw + 1]
  1176. sahf
  1177. je @@Done
  1178. inc bx { 387+ }
  1179. @@Done:
  1180. mov Test8087, bl
  1181. end ['AX','BX'];
  1182. if Test8087<=2 then
  1183. Default8087CW:=$1330
  1184. else
  1185. Default8087CW:=$1332;
  1186. end;
  1187. {$ifndef FPC_SYSTEM_HAS_SYSINITFPU}
  1188. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  1189. Procedure SysInitFPU; assembler;
  1190. asm
  1191. fninit
  1192. fldcw Default8087CW
  1193. fwait
  1194. end;
  1195. {$endif ndef FPC_SYSTEM_HAS_SYSINITFPU}
  1196. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  1197. Procedure SysResetFPU; assembler;
  1198. asm
  1199. fninit
  1200. fwait
  1201. fldcw Default8087CW
  1202. end;
  1203. {$I int32p.inc}
  1204. {$I hugeptr.inc}