sparc.inc 12 KB

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