sparc.inc 12 KB

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