sparc.inc 11 KB

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