sparc.inc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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. procedure fpc_cpuinit;
  36. begin
  37. { enable div by 0 and invalid operation fpu exceptions }
  38. { round towards zero; ieee compliant arithmetics }
  39. set_fsr((get_fsr and $3fbfffff) or $09000000);
  40. end;
  41. {$define FPC_SYSTEM_HAS_GET_FRAME}
  42. function get_frame:pointer;assembler;nostackframe;
  43. asm
  44. mov %fp,%o0
  45. end;
  46. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  47. function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
  48. asm
  49. { framebp = %o0 }
  50. { flush register windows, so they are stored in the stack }
  51. ta 3
  52. ld [%o0+60],%o0
  53. { add 8 to skip jmpl and delay slot }
  54. add %o0,8,%o0
  55. end;
  56. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  57. function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
  58. asm
  59. { flush register windows, so they are stored in the stack }
  60. ta 3
  61. { framebp = %o0 }
  62. ld [%o0+56],%o0
  63. end;
  64. {$define FPC_SYSTEM_HAS_SPTR}
  65. function Sptr:Pointer;assembler;nostackframe;
  66. asm
  67. mov %sp,%o0
  68. end;
  69. {$ifndef FPC_SYSTEM_HAS_MOVE}
  70. {$define FPC_SYSTEM_HAS_MOVE}
  71. procedure Move(const source;var dest;count:longint);[public, alias: 'FPC_MOVE'];assembler;
  72. {
  73. Registers:
  74. %l0 temp. to do copying
  75. %l1 inc/decrement
  76. %l2/l3/l4/l5 qword move
  77. }
  78. asm
  79. // count < 0 ?
  80. cmp %g0,%i2
  81. bge .Lmoveexit
  82. nop
  83. // possible overlap?
  84. cmp %i0,%i1
  85. bcc .Lnopossibleoverlap
  86. nop
  87. // source < dest ....
  88. add %i0,%i2,%l0
  89. // overlap?
  90. cmp %l0,%i1
  91. // source+count < dest ?
  92. bcs .Lnopossibleoverlap
  93. nop
  94. .Lcopybackward:
  95. // check alignment of source and dest
  96. or %i0,%i1,%l0
  97. // move src and dest to the end of the blocks
  98. // assuming 16 byte block size
  99. sub %i2,1,%l1
  100. add %i0,%l1,%i0
  101. add %i1,%l1,%i1
  102. {
  103. // everything 16 byte aligned ?
  104. andcc %l0,15,%l0
  105. be .Lmovetwordwise
  106. // load direction in delay slot
  107. mov -16,%l1
  108. // adjust according to block size
  109. add %i0,8,%i0
  110. add %i1,8,%i1
  111. andcc %l0,7,%l0
  112. be .Lmoveqwordwise
  113. mov -8,%l1
  114. // adjust according to block size
  115. add %i0,4,%i0
  116. add %i1,4,%i1
  117. andcc %l0,3,%l0
  118. be .Lmovedwordwise
  119. mov -4,%l1
  120. // adjust according to block size
  121. add %i0,2,%i0
  122. add %i1,2,%i1
  123. andcc %l0,1,%l0
  124. be .Lmovewordwise
  125. mov -2,%l1
  126. // adjust according to block size
  127. add %i0,1,%i0
  128. add %i1,1,%i1
  129. }
  130. ba .Lmovebytewise
  131. mov -1,%l1
  132. .Lnopossibleoverlap:
  133. // check alignment of source and dest
  134. or %i0,%i1,%l0
  135. // everything 16 byte aligned ?
  136. andcc %l0,15,%l0
  137. be .Lmovetwordwise
  138. // load direction in delay slot
  139. mov 16,%l1
  140. andcc %l0,7,%l0
  141. be .Lmoveqwordwise
  142. mov 8,%l1
  143. andcc %l0,3,%l0
  144. be .Lmovedwordwise
  145. mov 4,%l1
  146. andcc %l0,1,%l0
  147. be .Lmovewordwise
  148. mov 2,%l1
  149. ba .Lmovebytewise
  150. mov 1,%l1
  151. .Lmovetwordwise:
  152. srl %i2,4,%l6
  153. cmp %g0,%l6
  154. sll %l6,4,%l7
  155. be .Lmoveqwordwise_shift
  156. nop
  157. .Lmovetwordwise_loop:
  158. ld [%i0],%l2
  159. ld [%i0+4],%l3
  160. subcc %l6,1,%l6
  161. ld [%i0+8],%l4
  162. ld [%i0+12],%l5
  163. add %i0,%l1,%i0
  164. st %l2,[%i1]
  165. st %l3,[%i1+4]
  166. st %l4,[%i1+8]
  167. st %l5,[%i1+12]
  168. add %i1,%l1,%i1
  169. bne .Lmovetwordwise_loop
  170. nop
  171. subcc %i2,%l7,%i2
  172. be .Lmoveexit
  173. nop
  174. .Lmoveqwordwise_shift:
  175. sra %l1,1,%l1
  176. .Lmoveqwordwise:
  177. srl %i2,3,%l6
  178. cmp %g0,%l6
  179. sll %l6,3,%l7
  180. be .Lmovedwordwise_shift
  181. nop
  182. .Lmoveqwordwise_loop:
  183. ld [%i0],%l2
  184. ld [%i0+4],%l3
  185. subcc %l6,1,%l6
  186. add %i0,%l1,%i0
  187. st %l2,[%i1]
  188. st %l3,[%i1+4]
  189. add %i1,%l1,%i1
  190. bne .Lmoveqwordwise_loop
  191. nop
  192. subcc %i2,%l7,%i2
  193. be .Lmoveexit
  194. nop
  195. .Lmovedwordwise_shift:
  196. sra %l1,1,%l1
  197. .Lmovedwordwise:
  198. srl %i2,2,%l6
  199. cmp %g0,%l6
  200. sll %l6,2,%l7
  201. be .Lmovewordwise_shift
  202. nop
  203. .Lmovedwordwise_loop:
  204. ld [%i0],%l0
  205. subcc %l6,1,%l6
  206. add %i0,%l1,%i0
  207. st %l0,[%i1]
  208. add %i1,%l1,%i1
  209. bne .Lmovedwordwise_loop
  210. nop
  211. subcc %i2,%l7,%i2
  212. be .Lmoveexit
  213. nop
  214. .Lmovewordwise_shift:
  215. sra %l1,1,%l1
  216. .Lmovewordwise:
  217. srl %i2,1,%l6
  218. cmp %g0,%l6
  219. sll %l6,1,%l7
  220. be .Lmovebytewise_shift
  221. nop
  222. .Lmovewordwise_loop:
  223. lduh [%i0],%l0
  224. subcc %l6,1,%l6
  225. add %i0,%l1,%i0
  226. sth %l0,[%i1]
  227. add %i1,%l1,%i1
  228. bne .Lmovewordwise_loop
  229. nop
  230. subcc %i2,%l7,%i2
  231. be .Lmoveexit
  232. nop
  233. .Lmovebytewise_shift:
  234. sra %l1,1,%l1
  235. .Lmovebytewise:
  236. cmp %g0,%i2
  237. be .Lmoveexit
  238. nop
  239. ldub [%i0],%l0
  240. subcc %i2,1,%i2
  241. add %i0,%l1,%i0
  242. stb %l0,[%i1]
  243. add %i1,%l1,%i1
  244. bne .Lmovebytewise
  245. nop
  246. .Lmoveexit:
  247. end;
  248. {$endif FPC_SYSTEM_HAS_MOVE}
  249. {****************************************************************************
  250. Integer math
  251. ****************************************************************************}
  252. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  253. function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}nostackframe;
  254. asm
  255. sra %o0,31,%g1
  256. add %o0,%g1,%o0
  257. xor %o0,%g1,%o0
  258. end;
  259. var
  260. fpc_system_lock : byte;export name 'fpc_system_lock';
  261. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  262. function declocked(var l : longint) : boolean;assembler;nostackframe;
  263. asm
  264. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  265. worse the effort, especially while waiting :)
  266. }
  267. .Ldeclocked1:
  268. sethi %hi(fpc_system_lock), %g1
  269. or %g1,%lo(fpc_system_lock), %g1
  270. ldstub [%g1],%g1
  271. cmp %g1,0
  272. bne .Ldeclocked1
  273. nop
  274. ld [%o0],%g1
  275. sub %g1,1,%g1
  276. st %g1,[%o0]
  277. subcc %g1,1,%g0
  278. addx %g0,%g0,%o0
  279. { unlock }
  280. sethi %hi(fpc_system_lock), %g1
  281. or %g1,%lo(fpc_system_lock), %g1
  282. stb %g0,[%g1]
  283. end;
  284. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  285. procedure inclocked(var l : longint);assembler;nostackframe;
  286. asm
  287. { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
  288. worse the effort, especially while waiting :)
  289. }
  290. .Linclocked1:
  291. sethi %hi(fpc_system_lock), %g1
  292. or %g1,%lo(fpc_system_lock), %g1
  293. ldstub [%g1],%g1
  294. cmp %g1,0
  295. bne .Linclocked1
  296. nop
  297. ld [%o0],%g1
  298. add %g1,1,%g1
  299. st %g1,[%o0]
  300. { unlock }
  301. sethi %hi(fpc_system_lock), %g1
  302. or %g1,%lo(fpc_system_lock), %g1
  303. stb %g0,[%g1]
  304. end;