sparc.inc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2002-2004 by the Free Pascal development team.
  5. Processor dependent implementation for the system unit for
  6. Sparc
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. {****************************************************************************
  14. SPARC specific stuff
  15. ****************************************************************************}
  16. function get_fsr : dword;assembler;nostackframe;
  17. var
  18. fsr : dword;
  19. asm
  20. st %fsr,fsr
  21. ld fsr,%o0
  22. end;
  23. function get_got : pointer;assembler;nostackframe;[public, alias: 'FPC_GETGOT'];
  24. asm
  25. retl
  26. add %o7,%l7,%l7
  27. end;
  28. procedure set_fsr(fsr : dword);assembler;
  29. var
  30. _fsr : dword;
  31. asm
  32. // force memory location
  33. st fsr,_fsr
  34. ld _fsr,%fsr
  35. end;
  36. procedure fpc_cpuinit;
  37. begin
  38. { enable div by 0 and invalid operation fpu exceptions }
  39. { round towards zero; ieee compliant arithmetics }
  40. set_fsr((get_fsr and $3fbfffff) or $09000000);
  41. end;
  42. {$define FPC_SYSTEM_HAS_GET_FRAME}
  43. function get_frame:pointer;assembler;nostackframe;
  44. asm
  45. mov %fp,%o0
  46. end;
  47. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  48. function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
  49. asm
  50. { framebp = %o0 }
  51. { flush register windows, so they are stored in the stack }
  52. ta 3
  53. ld [%o0+60],%o0
  54. { add 8 to skip jmpl and delay slot }
  55. add %o0,8,%o0
  56. end;
  57. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  58. function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
  59. asm
  60. { flush register windows, so they are stored in the stack }
  61. ta 3
  62. { framebp = %o0 }
  63. ld [%o0+56],%o0
  64. end;
  65. {$define FPC_SYSTEM_HAS_SPTR}
  66. function Sptr:Pointer;assembler;nostackframe;
  67. asm
  68. mov %sp,%o0
  69. end;
  70. {$ifndef FPC_SYSTEM_HAS_MOVE}
  71. {$define FPC_SYSTEM_HAS_MOVE}
  72. procedure Move(const source;var dest;count:longint);[public, alias: 'FPC_MOVE'];assembler;
  73. {
  74. Registers:
  75. %l0 temp. to do copying
  76. %l1 inc/decrement
  77. %l2/l3/l4/l5 qword move
  78. }
  79. asm
  80. // count < 0 ?
  81. cmp %g0,%i2
  82. bge .Lmoveexit
  83. nop
  84. // possible overlap?
  85. cmp %i0,%i1
  86. bcc .Lnopossibleoverlap
  87. nop
  88. // source < dest ....
  89. add %i0,%i2,%l0
  90. // overlap?
  91. cmp %l0,%i1
  92. // source+count < dest ?
  93. bcs .Lnopossibleoverlap
  94. nop
  95. .Lcopybackward:
  96. // check alignment of source and dest
  97. or %i0,%i1,%l0
  98. // move src and dest to the end of the blocks
  99. // assuming 16 byte block size
  100. sub %i2,1,%l1
  101. add %i0,%l1,%i0
  102. add %i1,%l1,%i1
  103. {
  104. // everything 16 byte aligned ?
  105. andcc %l0,15,%l0
  106. be .Lmovetwordwise
  107. // load direction in delay slot
  108. mov -16,%l1
  109. // adjust according to block size
  110. add %i0,8,%i0
  111. add %i1,8,%i1
  112. andcc %l0,7,%l0
  113. be .Lmoveqwordwise
  114. mov -8,%l1
  115. // adjust according to block size
  116. add %i0,4,%i0
  117. add %i1,4,%i1
  118. andcc %l0,3,%l0
  119. be .Lmovedwordwise
  120. mov -4,%l1
  121. // adjust according to block size
  122. add %i0,2,%i0
  123. add %i1,2,%i1
  124. andcc %l0,1,%l0
  125. be .Lmovewordwise
  126. mov -2,%l1
  127. // adjust according to block size
  128. add %i0,1,%i0
  129. add %i1,1,%i1
  130. }
  131. ba .Lmovebytewise
  132. mov -1,%l1
  133. .Lnopossibleoverlap:
  134. // check alignment of source and dest
  135. or %i0,%i1,%l0
  136. // everything 16 byte aligned ?
  137. andcc %l0,15,%l0
  138. be .Lmovetwordwise
  139. // load direction in delay slot
  140. mov 16,%l1
  141. andcc %l0,7,%l0
  142. be .Lmoveqwordwise
  143. mov 8,%l1
  144. andcc %l0,3,%l0
  145. be .Lmovedwordwise
  146. mov 4,%l1
  147. andcc %l0,1,%l0
  148. be .Lmovewordwise
  149. mov 2,%l1
  150. ba .Lmovebytewise
  151. mov 1,%l1
  152. .Lmovetwordwise:
  153. srl %i2,4,%l6
  154. cmp %g0,%l6
  155. sll %l6,4,%l7
  156. be .Lmoveqwordwise_shift
  157. nop
  158. .Lmovetwordwise_loop:
  159. ld [%i0],%l2
  160. ld [%i0+4],%l3
  161. subcc %l6,1,%l6
  162. ld [%i0+8],%l4
  163. ld [%i0+12],%l5
  164. add %i0,%l1,%i0
  165. st %l2,[%i1]
  166. st %l3,[%i1+4]
  167. st %l4,[%i1+8]
  168. st %l5,[%i1+12]
  169. add %i1,%l1,%i1
  170. bne .Lmovetwordwise_loop
  171. nop
  172. subcc %i2,%l7,%i2
  173. be .Lmoveexit
  174. nop
  175. .Lmoveqwordwise_shift:
  176. sra %l1,1,%l1
  177. .Lmoveqwordwise:
  178. srl %i2,3,%l6
  179. cmp %g0,%l6
  180. sll %l6,3,%l7
  181. be .Lmovedwordwise_shift
  182. nop
  183. .Lmoveqwordwise_loop:
  184. ld [%i0],%l2
  185. ld [%i0+4],%l3
  186. subcc %l6,1,%l6
  187. add %i0,%l1,%i0
  188. st %l2,[%i1]
  189. st %l3,[%i1+4]
  190. add %i1,%l1,%i1
  191. bne .Lmoveqwordwise_loop
  192. nop
  193. subcc %i2,%l7,%i2
  194. be .Lmoveexit
  195. nop
  196. .Lmovedwordwise_shift:
  197. sra %l1,1,%l1
  198. .Lmovedwordwise:
  199. srl %i2,2,%l6
  200. cmp %g0,%l6
  201. sll %l6,2,%l7
  202. be .Lmovewordwise_shift
  203. nop
  204. .Lmovedwordwise_loop:
  205. ld [%i0],%l0
  206. subcc %l6,1,%l6
  207. add %i0,%l1,%i0
  208. st %l0,[%i1]
  209. add %i1,%l1,%i1
  210. bne .Lmovedwordwise_loop
  211. nop
  212. subcc %i2,%l7,%i2
  213. be .Lmoveexit
  214. nop
  215. .Lmovewordwise_shift:
  216. sra %l1,1,%l1
  217. .Lmovewordwise:
  218. srl %i2,1,%l6
  219. cmp %g0,%l6
  220. sll %l6,1,%l7
  221. be .Lmovebytewise_shift
  222. nop
  223. .Lmovewordwise_loop:
  224. lduh [%i0],%l0
  225. subcc %l6,1,%l6
  226. add %i0,%l1,%i0
  227. sth %l0,[%i1]
  228. add %i1,%l1,%i1
  229. bne .Lmovewordwise_loop
  230. nop
  231. subcc %i2,%l7,%i2
  232. be .Lmoveexit
  233. nop
  234. .Lmovebytewise_shift:
  235. sra %l1,1,%l1
  236. .Lmovebytewise:
  237. cmp %g0,%i2
  238. be .Lmoveexit
  239. nop
  240. ldub [%i0],%l0
  241. subcc %i2,1,%i2
  242. add %i0,%l1,%i0
  243. stb %l0,[%i1]
  244. add %i1,%l1,%i1
  245. bne .Lmovebytewise
  246. nop
  247. .Lmoveexit:
  248. end;
  249. {$endif FPC_SYSTEM_HAS_MOVE}
  250. {****************************************************************************
  251. Integer math
  252. ****************************************************************************}
  253. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  254. function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}nostackframe;{$ifndef INTERNCONSTINTF}[internconst:fpc_in_const_abs];{$endif}
  255. asm
  256. sra %o0,31,%g1
  257. add %o0,%g1,%o0
  258. xor %o0,%g1,%o0
  259. end;
  260. var
  261. fpc_system_lock : byte;export name 'fpc_system_lock';
  262. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  263. function declocked(var l : longint) : boolean;assembler;nostackframe;
  264. asm
  265. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  266. worse the effort, especially while waiting :)
  267. }
  268. .Ldeclocked1:
  269. sethi %hi(fpc_system_lock), %g1
  270. or %g1,%lo(fpc_system_lock), %g1
  271. ldstub [%g1],%g1
  272. cmp %g1,0
  273. bne .Ldeclocked1
  274. nop
  275. ld [%o0],%g1
  276. sub %g1,1,%g1
  277. st %g1,[%o0]
  278. subcc %g1,1,%g0
  279. addx %g0,%g0,%o0
  280. { unlock }
  281. sethi %hi(fpc_system_lock), %g1
  282. or %g1,%lo(fpc_system_lock), %g1
  283. stb %g0,[%g1]
  284. end;
  285. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  286. procedure inclocked(var l : longint);assembler;nostackframe;
  287. asm
  288. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  289. worse the effort, especially while waiting :)
  290. }
  291. .Linclocked1:
  292. sethi %hi(fpc_system_lock), %g1
  293. or %g1,%lo(fpc_system_lock), %g1
  294. ldstub [%g1],%g1
  295. cmp %g1,0
  296. bne .Linclocked1
  297. nop
  298. ld [%o0],%g1
  299. add %g1,1,%g1
  300. st %g1,[%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. {
  307. $Log$
  308. Revision 1.19 2005-02-07 22:17:48 peter
  309. * add $ifdef for move
  310. Revision 1.18 2005/01/27 21:26:39 florian
  311. + getgot function added
  312. Revision 1.17 2005/01/18 20:37:26 florian
  313. * set floating point precision and ieee compliance
  314. Revision 1.16 2004/11/21 19:11:33 peter
  315. * fix bootstrapping
  316. Revision 1.15 2004/11/21 15:35:23 peter
  317. * float routines all use internproc and compilerproc helpers
  318. Revision 1.14 2004/11/03 20:53:58 florian
  319. * get_frame fixed
  320. Revision 1.13 2004/10/14 19:45:39 florian
  321. + added and implemented functions for locked operations
  322. Revision 1.12 2004/10/03 12:41:30 florian
  323. * made sqrt, sqr and abs internal for the sparc
  324. Revision 1.11 2004/10/02 20:46:20 florian
  325. * made assembler implementation of move
  326. Revision 1.10 2004/09/23 11:30:41 florian
  327. * fixed indention
  328. Revision 1.9 2004/09/12 12:04:23 peter
  329. * restore traps when returning with longjmp
  330. Revision 1.8 2004/08/04 19:27:10 florian
  331. * fixed floating point and integer exception handling on sparc/linux
  332. Revision 1.7 2004/05/30 20:03:05 florian
  333. * ?
  334. Revision 1.6 2004/05/27 23:34:37 peter
  335. * backtrace support
  336. Revision 1.5 2004/01/02 17:22:14 jonas
  337. + fpc_cpuinit procedure to allow cpu/fpu initialisation before any unit
  338. initialises
  339. + fpu exceptions for invalid operations and division by zero enabled for
  340. ppc
  341. Revision 1.4 2003/12/04 21:42:07 peter
  342. * register calling updates
  343. Revision 1.3 2003/03/17 14:30:11 peter
  344. * changed address parameter/return values to pointer instead
  345. of longint
  346. Revision 1.2 2003/02/05 21:48:34 mazen
  347. * fixing run time errors related to unimplemented abstract methods in CG
  348. + giving empty emplementations for some RTL functions
  349. Revision 1.1 2002/11/16 20:10:31 florian
  350. + sparc specific rtl skeleton added
  351. }