2
0

sparc64.inc 13 KB

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