sparc.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2002-2004 by the Free Pascal development team.
  4. Processor dependent implementation for the system unit for
  5. Sparc
  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. {****************************************************************************
  13. SPARC specific stuff
  14. ****************************************************************************}
  15. function get_fsr : dword;assembler;[public, alias: 'FPC_GETFSR'];
  16. var
  17. fsr : dword;
  18. asm
  19. st %fsr,fsr
  20. ld fsr,%l0
  21. st %l0,__result
  22. end;
  23. procedure set_fsr(fsr : dword);assembler;[public, alias: 'FPC_SETFSR'];
  24. var
  25. _fsr : dword;
  26. asm
  27. // force memory location
  28. st fsr,_fsr
  29. ld _fsr,%fsr
  30. end;
  31. function get_got : pointer;assembler;nostackframe;[public, alias: 'FPC_GETGOT'];
  32. asm
  33. retl
  34. add %o7,%l7,%l7
  35. end;
  36. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  37. Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
  38. begin
  39. softfloat_exception_mask:=float_flag_underflow or float_flag_inexact or float_flag_denormal;
  40. { enable div by 0 and invalid operation fpu exceptions
  41. round towards zero; ieee compliant arithmetics }
  42. set_fsr((get_fsr and $3fbfffff) or $09000000);
  43. end;
  44. {$define FPC_SYSTEM_HAS_SYSRESETFPU}
  45. Procedure SysResetFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
  46. begin
  47. softfloat_exception_flags:=0;
  48. end;
  49. procedure fpc_cpuinit;
  50. begin
  51. SysResetFPU;
  52. if not(IsLibrary) then
  53. SysInitFPU;
  54. end;
  55. {$define FPC_SYSTEM_HAS_GET_FRAME}
  56. function get_frame:pointer;assembler;nostackframe;
  57. asm
  58. mov %fp,%o0
  59. end;
  60. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  61. function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
  62. asm
  63. { framebp = %o0 }
  64. subcc %o0,0,%o0
  65. be .Lframezero
  66. nop
  67. { flush register windows, so they are stored in the stack }
  68. ta 3
  69. ld [%o0+60],%o0
  70. { check if new %o0 register is zero }
  71. subcc %o0,0,%o0
  72. be .Lframezero
  73. nop
  74. { if not zero, add 8 to skip jmpl and delay slot }
  75. add %o0,8,%o0
  76. .Lframezero:
  77. end;
  78. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  79. function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
  80. asm
  81. { framebp = %o0 }
  82. subcc %o0,0,%o0
  83. be .Lframezero
  84. nop
  85. { flush register windows, so they are stored in the stack }
  86. ta 3
  87. ld [%o0+56],%o0
  88. .Lframezero:
  89. end;
  90. {$define FPC_SYSTEM_HAS_SPTR}
  91. function Sptr:Pointer;assembler;nostackframe;
  92. asm
  93. mov %sp,%o0
  94. end;
  95. {$ifndef FPC_SYSTEM_HAS_MOVE}
  96. {$define FPC_SYSTEM_HAS_MOVE}
  97. procedure Move(const source;var dest;count:longint);[public, alias: 'FPC_MOVE'];assembler;
  98. {
  99. Registers:
  100. %l0 temp. to do copying
  101. %l1 inc/decrement
  102. %l2/l3/l4/l5 qword move
  103. }
  104. asm
  105. // count < 0 ?
  106. cmp %g0,%i2
  107. bge .Lmoveexit
  108. nop
  109. // possible overlap?
  110. cmp %i0,%i1
  111. bcc .Lnopossibleoverlap
  112. nop
  113. // source < dest ....
  114. add %i0,%i2,%l0
  115. // overlap?
  116. cmp %l0,%i1
  117. // source+count < dest ?
  118. bcs .Lnopossibleoverlap
  119. nop
  120. .Lcopybackward:
  121. // check alignment of source and dest
  122. or %i0,%i1,%l0
  123. // move src and dest to the end of the blocks
  124. // assuming 16 byte block size
  125. sub %i2,1,%l1
  126. add %i0,%l1,%i0
  127. add %i1,%l1,%i1
  128. {
  129. // everything 16 byte aligned ?
  130. andcc %l0,15,%l0
  131. be .Lmovetwordwise
  132. // load direction in delay slot
  133. mov -16,%l1
  134. // adjust according to block size
  135. add %i0,8,%i0
  136. add %i1,8,%i1
  137. andcc %l0,7,%l0
  138. be .Lmoveqwordwise
  139. mov -8,%l1
  140. // adjust according to block size
  141. add %i0,4,%i0
  142. add %i1,4,%i1
  143. andcc %l0,3,%l0
  144. be .Lmovedwordwise
  145. mov -4,%l1
  146. // adjust according to block size
  147. add %i0,2,%i0
  148. add %i1,2,%i1
  149. andcc %l0,1,%l0
  150. be .Lmovewordwise
  151. mov -2,%l1
  152. // adjust according to block size
  153. add %i0,1,%i0
  154. add %i1,1,%i1
  155. }
  156. ba .Lmovebytewise
  157. mov -1,%l1
  158. .Lnopossibleoverlap:
  159. // check alignment of source and dest
  160. or %i0,%i1,%l0
  161. // everything 16 byte aligned ?
  162. andcc %l0,15,%l0
  163. be .Lmovetwordwise
  164. // load direction in delay slot
  165. mov 16,%l1
  166. andcc %l0,7,%l0
  167. be .Lmoveqwordwise
  168. mov 8,%l1
  169. andcc %l0,3,%l0
  170. be .Lmovedwordwise
  171. mov 4,%l1
  172. andcc %l0,1,%l0
  173. be .Lmovewordwise
  174. mov 2,%l1
  175. ba .Lmovebytewise
  176. mov 1,%l1
  177. .Lmovetwordwise:
  178. srl %i2,4,%l6
  179. cmp %g0,%l6
  180. sll %l6,4,%l7
  181. be .Lmoveqwordwise_shift
  182. nop
  183. .Lmovetwordwise_loop:
  184. ld [%i0],%l2
  185. ld [%i0+4],%l3
  186. subcc %l6,1,%l6
  187. ld [%i0+8],%l4
  188. ld [%i0+12],%l5
  189. add %i0,%l1,%i0
  190. st %l2,[%i1]
  191. st %l3,[%i1+4]
  192. st %l4,[%i1+8]
  193. st %l5,[%i1+12]
  194. add %i1,%l1,%i1
  195. bne .Lmovetwordwise_loop
  196. nop
  197. subcc %i2,%l7,%i2
  198. be .Lmoveexit
  199. nop
  200. .Lmoveqwordwise_shift:
  201. sra %l1,1,%l1
  202. .Lmoveqwordwise:
  203. srl %i2,3,%l6
  204. cmp %g0,%l6
  205. sll %l6,3,%l7
  206. be .Lmovedwordwise_shift
  207. nop
  208. .Lmoveqwordwise_loop:
  209. ld [%i0],%l2
  210. ld [%i0+4],%l3
  211. subcc %l6,1,%l6
  212. add %i0,%l1,%i0
  213. st %l2,[%i1]
  214. st %l3,[%i1+4]
  215. add %i1,%l1,%i1
  216. bne .Lmoveqwordwise_loop
  217. nop
  218. subcc %i2,%l7,%i2
  219. be .Lmoveexit
  220. nop
  221. .Lmovedwordwise_shift:
  222. sra %l1,1,%l1
  223. .Lmovedwordwise:
  224. srl %i2,2,%l6
  225. cmp %g0,%l6
  226. sll %l6,2,%l7
  227. be .Lmovewordwise_shift
  228. nop
  229. .Lmovedwordwise_loop:
  230. ld [%i0],%l0
  231. subcc %l6,1,%l6
  232. add %i0,%l1,%i0
  233. st %l0,[%i1]
  234. add %i1,%l1,%i1
  235. bne .Lmovedwordwise_loop
  236. nop
  237. subcc %i2,%l7,%i2
  238. be .Lmoveexit
  239. nop
  240. .Lmovewordwise_shift:
  241. sra %l1,1,%l1
  242. .Lmovewordwise:
  243. srl %i2,1,%l6
  244. cmp %g0,%l6
  245. sll %l6,1,%l7
  246. be .Lmovebytewise_shift
  247. nop
  248. .Lmovewordwise_loop:
  249. lduh [%i0],%l0
  250. subcc %l6,1,%l6
  251. add %i0,%l1,%i0
  252. sth %l0,[%i1]
  253. add %i1,%l1,%i1
  254. bne .Lmovewordwise_loop
  255. nop
  256. subcc %i2,%l7,%i2
  257. be .Lmoveexit
  258. nop
  259. .Lmovebytewise_shift:
  260. sra %l1,1,%l1
  261. .Lmovebytewise:
  262. cmp %g0,%i2
  263. be .Lmoveexit
  264. nop
  265. ldub [%i0],%l0
  266. subcc %i2,1,%i2
  267. add %i0,%l1,%i0
  268. stb %l0,[%i1]
  269. add %i1,%l1,%i1
  270. bne .Lmovebytewise
  271. nop
  272. .Lmoveexit:
  273. end;
  274. {$endif FPC_SYSTEM_HAS_MOVE}
  275. {****************************************************************************
  276. Integer math
  277. ****************************************************************************}
  278. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  279. function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}nostackframe;
  280. asm
  281. sra %o0,31,%g1
  282. add %o0,%g1,%o0
  283. xor %o0,%g1,%o0
  284. end;
  285. var
  286. fpc_system_lock : byte;export name 'fpc_system_lock';
  287. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  288. function declocked(var l : longint) : boolean;assembler;nostackframe;
  289. asm
  290. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  291. worse the effort, especially while waiting :)
  292. }
  293. .Ldeclocked1:
  294. sethi %hi(fpc_system_lock), %g1
  295. or %g1,%lo(fpc_system_lock), %g1
  296. ldstub [%g1],%g1
  297. cmp %g1,0
  298. bne .Ldeclocked1
  299. nop
  300. ld [%o0],%g1
  301. sub %g1,1,%g1
  302. st %g1,[%o0]
  303. subcc %g1,1,%g0
  304. addx %g0,%g0,%o0
  305. { unlock }
  306. sethi %hi(fpc_system_lock), %g1
  307. or %g1,%lo(fpc_system_lock), %g1
  308. stb %g0,[%g1]
  309. end;
  310. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  311. procedure inclocked(var l : longint);assembler;nostackframe;
  312. asm
  313. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  314. worse the effort, especially while waiting :)
  315. }
  316. .Linclocked1:
  317. sethi %hi(fpc_system_lock), %g1
  318. or %g1,%lo(fpc_system_lock), %g1
  319. ldstub [%g1],%g1
  320. cmp %g1,0
  321. bne .Linclocked1
  322. nop
  323. ld [%o0],%g1
  324. add %g1,1,%g1
  325. st %g1,[%o0]
  326. { unlock }
  327. sethi %hi(fpc_system_lock), %g1
  328. or %g1,%lo(fpc_system_lock), %g1
  329. stb %g0,[%g1]
  330. end;
  331. function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
  332. asm
  333. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  334. worse the effort, especially while waiting :)
  335. }
  336. .LInterLockedDecrement1:
  337. sethi %hi(fpc_system_lock), %g1
  338. or %g1,%lo(fpc_system_lock), %g1
  339. ldstub [%g1],%g1
  340. cmp %g1,0
  341. bne .LInterLockedDecrement1
  342. nop
  343. ld [%o0],%g1
  344. sub %g1,1,%g1
  345. st %g1,[%o0]
  346. mov %g1,%o0
  347. { unlock }
  348. sethi %hi(fpc_system_lock), %g1
  349. or %g1,%lo(fpc_system_lock), %g1
  350. stb %g0,[%g1]
  351. end;
  352. function InterLockedIncrement (var Target: longint) : longint; assembler; nostackframe;
  353. asm
  354. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  355. worse the effort, especially while waiting :)
  356. }
  357. .LInterLockedIncrement1:
  358. sethi %hi(fpc_system_lock), %g1
  359. or %g1,%lo(fpc_system_lock), %g1
  360. ldstub [%g1],%g1
  361. cmp %g1,0
  362. bne .LInterLockedIncrement1
  363. nop
  364. ld [%o0],%g1
  365. add %g1,1,%g1
  366. st %g1,[%o0]
  367. mov %g1,%o0
  368. { unlock }
  369. sethi %hi(fpc_system_lock), %g1
  370. or %g1,%lo(fpc_system_lock), %g1
  371. stb %g0,[%g1]
  372. end;
  373. function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler; nostackframe;
  374. asm
  375. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  376. worse the effort, especially while waiting :)
  377. }
  378. .LInterLockedExchange1:
  379. sethi %hi(fpc_system_lock), %g1
  380. or %g1,%lo(fpc_system_lock), %g1
  381. ldstub [%g1],%g1
  382. cmp %g1,0
  383. bne .LInterLockedExchange1
  384. nop
  385. ld [%o0],%g1
  386. st %o1,[%o0]
  387. mov %g1,%o0
  388. { unlock }
  389. sethi %hi(fpc_system_lock), %g1
  390. or %g1,%lo(fpc_system_lock), %g1
  391. stb %g0,[%g1]
  392. end;
  393. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler; nostackframe;
  394. asm
  395. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  396. worse the effort, especially while waiting :)
  397. }
  398. .LInterLockedExchangeAdd1:
  399. sethi %hi(fpc_system_lock), %g1
  400. or %g1,%lo(fpc_system_lock), %g1
  401. ldstub [%g1],%g1
  402. cmp %g1,0
  403. bne .LInterLockedExchangeAdd1
  404. nop
  405. ld [%o0],%g1
  406. add %g1,%o1,%o1
  407. st %o1,[%o0]
  408. mov %g1,%o0
  409. { unlock }
  410. sethi %hi(fpc_system_lock), %g1
  411. or %g1,%lo(fpc_system_lock), %g1
  412. stb %g0,[%g1]
  413. end;
  414. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler; nostackframe;
  415. asm
  416. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  417. worse the effort, especially while waiting :)
  418. }
  419. { input: address of target in o0, newvalue in o1, comparand in o2 }
  420. { output: value stored in target before entry of the function }
  421. { side-effect: NewValue stored in target if (target = comparand) }
  422. .LInterlockedCompareExchange1:
  423. sethi %hi(fpc_system_lock), %g1
  424. or %g1,%lo(fpc_system_lock), %g1
  425. ldstub [%g1],%g1
  426. cmp %g1,0
  427. bne .LInterlockedCompareExchange1
  428. nop
  429. ld [%o0],%g1
  430. cmp %g1,%o2
  431. bne .LInterlockedCompareExchange2
  432. nop
  433. st %o1,[%o0]
  434. .LInterlockedCompareExchange2:
  435. mov %g1,%o0
  436. { unlock }
  437. sethi %hi(fpc_system_lock), %g1
  438. or %g1,%lo(fpc_system_lock), %g1
  439. stb %g0,[%g1]
  440. end;
  441. {$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
  442. {$define FPC_SYSTEM_HAS_MEM_BARRIER}
  443. const
  444. LoadLoad = $01;
  445. StoreLoad = $02;
  446. LoadStore = $04;
  447. StoreStore = $08;
  448. LookAside = $10;
  449. MemIssue = $20;
  450. Sync = $40;
  451. procedure ReadBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  452. asm
  453. {$ifdef FPC_HAS_MEMBAR}
  454. ba,pt .L1
  455. membar LoadLoad
  456. .L1:
  457. {$endif}
  458. end;
  459. procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
  460. begin
  461. { reads imply barrier on earlier reads depended on }
  462. end;
  463. procedure ReadWriteBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  464. asm
  465. {$ifdef FPC_HAS_MEMBAR}
  466. ba,pt .L1
  467. membar LoadLoad + LoadStore + StoreLoad + StoreStore
  468. .L1:
  469. {$endif}
  470. end;
  471. procedure WriteBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
  472. asm
  473. {$ifdef FPC_HAS_MEMBAR}
  474. ba,pt .L1
  475. stbar
  476. .L1:
  477. {$endif}
  478. end;
  479. {$endif}