sparc.inc 11 KB

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