mips.inc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2006-2007 by David Zhang
  4. Processor dependent implementation for the system unit for MIPS
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************
  12. MIPS specific stuff
  13. ****************************************************************************}
  14. function get_fsr : dword;assembler;nostackframe;[public, alias: 'FPC_GETFSR'];
  15. var
  16. fsr : dword;
  17. asm
  18. cfc1 $2,$31
  19. end;
  20. procedure set_fsr(fsr : dword);assembler;[public, alias: 'FPC_SETFSR'];
  21. var
  22. _fsr : dword;
  23. asm
  24. ctc1 $4,$31
  25. end;
  26. function get_got_z : pointer;assembler;nostackframe;[public, alias: 'FPC_GETGOT_Z'];
  27. asm
  28. move $2,$28
  29. end;
  30. procedure fpc_cpuinit;
  31. var
  32. tmp32: longint;
  33. begin
  34. { don't let libraries influence the FPU cw set by the host program }
  35. if not IsLibrary then
  36. begin
  37. { enable div by 0 and invalid operation fpu exceptions }
  38. { round towards nearest; ieee compliant arithmetics }
  39. tmp32 := get_fsr();
  40. set_fsr(tmp32 and $fffffffc);
  41. end;
  42. end;
  43. {$define FPC_SYSTEM_HAS_GET_FRAME}
  44. function get_frame:pointer;assembler;nostackframe;
  45. asm
  46. { we need to use the information of the .pdr section to do this properly:
  47. 0 proc. start adress
  48. 4 regmask
  49. 8 reg. offset
  50. 12 fmask
  51. 16 foffset
  52. 20 frame size
  53. 24 stack reg
  54. 28 link reg
  55. Further, we need to know the pc
  56. }
  57. // lw $2,0($sp)
  58. move $2,$30
  59. end;
  60. {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
  61. function get_caller_addr(framebp:pointer):pointer;assembler;nostackframe;
  62. asm
  63. // lw $2,4($4) // #movl 4(%eax),%eax
  64. lui $2,0
  65. end;
  66. {$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
  67. function get_caller_frame(framebp:pointer):pointer;assembler;nostackframe;
  68. asm
  69. // lw $2,0($4) // #movl (%eax),%eax
  70. lui $2,0
  71. end;
  72. {$define FPC_SYSTEM_HAS_SPTR}
  73. function Sptr:Pointer;assembler;nostackframe;
  74. asm
  75. move $2,$sp
  76. end;
  77. {$ifdef USE_MIPS_STK2_ASM}
  78. {$ifndef FPC_SYSTEM_HAS_MOVE}
  79. (* Disabled for now
  80. {$define FPC_SYSTEM_HAS_MOVE}
  81. procedure Move(const source;var dest;count:longint);[public, alias: 'FPC_MOVE'];assembler;
  82. asm
  83. {
  84. Registers:
  85. $7 temp. to do copying
  86. $8 inc/decrement
  87. $9/l0/l1/l2 qword move
  88. }
  89. sw $4,0($23)
  90. sw $5,-4($23)
  91. sw $6,-8($23)
  92. sw $7,-12($23)
  93. sw $8,-16($23)
  94. sw $9,-20($23)
  95. sw $10,-24($23)
  96. sw $11,-28($23)
  97. sw $12,-32($23)
  98. sw $13,-36($23)
  99. sw $14,-40($23)
  100. addiu $23,$23,-44
  101. // count <= 0 ?
  102. ble $6,$0,.Lmoveexit
  103. nop
  104. // source = dest ?
  105. beq $4,$5,.Lmoveexit
  106. nop
  107. // possible overlap?
  108. bgt $4,$5,.Lnopossibleoverlap
  109. nop
  110. // source < dest ....
  111. addu $7,$6,$4
  112. // overlap?
  113. // source+count < dest ?
  114. blt $7,$5,.Lnopossibleoverlap
  115. nop
  116. .Lcopybackward:
  117. // check alignment of source and dest
  118. or $2,$4,$5
  119. // move src and dest to the end of the blocks
  120. // assuming 16 byte block size
  121. addiu $3,$6,-1
  122. addu $4,$4,$3
  123. addu $5,$5,$3
  124. b .Lmovebytewise
  125. li $3,-1
  126. .Lnopossibleoverlap:
  127. // check alignment of source and dest
  128. or $2,$4,$5
  129. // everything 16 byte aligned ?
  130. andi $13,$2,15
  131. beq $13,$0,.Lmovetwordwise
  132. // load direction in delay slot
  133. li $3,16
  134. andi $13,$2,7
  135. beq $13,$0,.Lmoveqwordwise
  136. li $3,8
  137. andi $13,$2,3
  138. beq $13,$0,.Lmovedwordwise
  139. li $3,4
  140. andi $13,$2,1
  141. beq $13,$0,.Lmovewordwise
  142. li $3,2
  143. b .Lmovebytewise
  144. li $3,1
  145. .Lmovetwordwise:
  146. srl $13,$6,4
  147. sll $14,$13,4
  148. beq $14,$0,.Lmoveqwordwise_shift
  149. nop
  150. .Lmovetwordwise_loop:
  151. lw $9,0($4)
  152. lw $10,4($4)
  153. addiu $13,$13,-1
  154. lw $11,8($4)
  155. lw $12,12($4)
  156. addu $4,$4,$3
  157. sw $9,0($5)
  158. sw $10,4($5)
  159. sw $11,8($5)
  160. sw $12,12($5)
  161. addu $5,$5,$3
  162. bne $13,$0,.Lmovetwordwise_loop
  163. nop
  164. subu $6,$6,$14
  165. beq $6,$0,.Lmoveexit
  166. nop
  167. .Lmoveqwordwise_shift:
  168. sra $3,$3,1
  169. .Lmoveqwordwise:
  170. srl $13,$6,3
  171. sll $14,$13,3
  172. beq $14,$0,.Lmovedwordwise_shift
  173. nop
  174. .Lmoveqwordwise_loop:
  175. lw $9,0($4)
  176. lw $10,4($4)
  177. addiu $13,$13,-1
  178. addu $4,$3,$4
  179. sw $9,0($5)
  180. sw $10,4($5)
  181. addu $5,$3,$5
  182. bne $13,$0,.Lmoveqwordwise_loop
  183. nop
  184. subu $6,$6,$14
  185. beq $6,$0,.Lmoveexit
  186. nop
  187. .Lmovedwordwise_shift:
  188. sra $3,$3,1
  189. .Lmovedwordwise:
  190. srl $13,$6,2
  191. sll $14,$13,2
  192. beq $14,$0,.Lmovewordwise_shift
  193. nop
  194. .Lmovedwordwise_loop:
  195. lw $9,0($4)
  196. addiu $13,$13,-1
  197. addu $4,$4,$3
  198. sw $9,0($5)
  199. addu $5,$5,$3
  200. bne $13,$0,.Lmovedwordwise_loop
  201. nop
  202. subu $6,$6,$14
  203. beq $6,$0,.Lmoveexit
  204. nop
  205. .Lmovewordwise_shift:
  206. sra $3,$3,1
  207. .Lmovewordwise:
  208. srl $13,$6,1
  209. sll $14,$13,1
  210. beq $14,$0, .Lmovebytewise_shift
  211. nop
  212. .Lmovewordwise_loop:
  213. lhu $9,0($4)
  214. addiu $13,$13,-1
  215. addu $4,$4,$3
  216. sh $9,0($5)
  217. addu $5,$5,$3
  218. bne $13,$0,.Lmovewordwise_loop
  219. nop
  220. subu $6,$6,$14
  221. beq $6,$0, .Lmoveexit
  222. nop
  223. .Lmovebytewise_shift:
  224. sra $3,$3,1
  225. .Lmovebytewise:
  226. beq $6,$0, .Lmoveexit
  227. nop
  228. lbu $9,0($4)
  229. addiu $6,$6,-1
  230. addu $4,$4,$3
  231. sb $9,0($5)
  232. addu $5,$5,$3
  233. bne $6,$0,.Lmovebytewise
  234. nop
  235. .Lmoveexit:
  236. addiu $23,$23,44
  237. lw $4,0($23)
  238. lw $5,-4($23)
  239. lw $6,-8($23)
  240. lw $7,-12($23)
  241. lw $8,-16($23)
  242. lw $9,-20($23)
  243. lw $10,-24($23)
  244. lw $11,-28($23)
  245. lw $12,-32($23)
  246. lw $13,-36($23)
  247. lw $14,-40($23)
  248. end;
  249. *)
  250. {$endif FPC_SYSTEM_HAS_MOVE}
  251. {****************************************************************************
  252. Integer math
  253. ****************************************************************************}
  254. {$define FPC_SYSTEM_HAS_ABS_LONGINT}
  255. function abs(l:longint):longint; assembler;{$ifdef SYSTEMINLINE}inline;{$endif}nostackframe;
  256. asm
  257. sra $1,$4,31 // $at,$4,31
  258. xor $2,$4,$1 // $2,$4,$at
  259. sub $2,$2,$1 // $2,$2,$at
  260. end;
  261. var
  262. fpc_system_lock : longint; export name 'fpc_system_lock';
  263. {$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
  264. function declocked(var l : longint) : boolean;assembler;nostackframe;
  265. { input: address of l in $4 }
  266. { output: boolean indicating whether l is zero after decrementing }
  267. asm
  268. sw $4,0($23)
  269. sw $5,-4($23)
  270. sw $6,-8($23)
  271. sw $7,-12($23)
  272. sw $8,-16($23)
  273. sw $9,-20($23)
  274. sw $10,-24($23)
  275. sw $11,-28($23)
  276. sw $12,-32($23)
  277. sw $13,-36($23)
  278. sw $14,-40($23)
  279. addiu $23,$23,-44
  280. .Ldeclocked1:
  281. lui $5,%hi(fpc_system_lock)
  282. addiu $5,$5,%lo(fpc_system_lock)
  283. ll $6,0($5)
  284. ori $7,$6,1
  285. beq $7,$6,.Ldeclocked1
  286. nop
  287. sc $7,0($5)
  288. beq $7,$0,.Ldeclocked1
  289. nop
  290. lw $5,0($4)
  291. addiu $5,$5,-1
  292. sw $5,0($4)
  293. seq $2,$5,$0
  294. { unlock }
  295. lui $5,%hi(fpc_system_lock)
  296. addiu $5,$5,%lo(fpc_system_lock)
  297. sw $0,0($5)
  298. addiu $23,$23,44
  299. lw $4,0($23)
  300. lw $5,-4($23)
  301. lw $6,-8($23)
  302. lw $7,-12($23)
  303. lw $8,-16($23)
  304. lw $9,-20($23)
  305. lw $10,-24($23)
  306. lw $11,-28($23)
  307. lw $12,-32($23)
  308. lw $13,-36($23)
  309. lw $14,-40($23)
  310. end;
  311. {$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
  312. procedure inclocked(var l : 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. { unlock }
  318. sw $4,0($23)
  319. sw $5,-4($23)
  320. sw $6,-8($23)
  321. sw $7,-12($23)
  322. sw $8,-16($23)
  323. sw $9,-20($23)
  324. sw $10,-24($23)
  325. sw $11,-28($23)
  326. sw $12,-32($23)
  327. sw $13,-36($23)
  328. sw $14,-40($23)
  329. addiu $23,$23,-44
  330. .Ldeclocked1:
  331. lui $5,%hi(fpc_system_lock)
  332. addiu $5,$5,%lo(fpc_system_lock)
  333. ll $6,0($5)
  334. ori $7,$6,1
  335. beq $7,$6,.Ldeclocked1
  336. nop
  337. sc $7,0($5)
  338. beq $7,$0,.Ldeclocked1
  339. nop
  340. lw $5,0($4)
  341. addiu $5,$5,1
  342. sw $5,0($4)
  343. { unlock }
  344. lui $5,%hi(fpc_system_lock)
  345. addiu $5,$5,%lo(fpc_system_lock)
  346. sw $0,0($5)
  347. addiu $23,$23,44
  348. lw $4,0($23)
  349. lw $5,-4($23)
  350. lw $6,-8($23)
  351. lw $7,-12($23)
  352. lw $8,-16($23)
  353. lw $9,-20($23)
  354. lw $10,-24($23)
  355. lw $11,-28($23)
  356. lw $12,-32($23)
  357. lw $13,-36($23)
  358. lw $14,-40($23)
  359. end;
  360. {$endif def USE_MIPS_STK2_ASM}
  361. function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
  362. asm
  363. {$warning FIXME: This implementation of InterLockedDecrement in not yet ThreadSafe }
  364. lw $v0,($a0)
  365. addi $v1,$v0,-1
  366. sw $v1,($a0)
  367. end;
  368. function InterLockedIncrement (var Target: longint) : longint; assembler; nostackframe;
  369. asm
  370. {$warning FIXME: This implementation of InterLockedIncrement in not yet ThreadSafe }
  371. lw $v0,($a0)
  372. addi $v1,$v0,1
  373. sw $v1,($a0)
  374. end;
  375. function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler; nostackframe;
  376. asm
  377. {$warning FIXME: This implementation of InterLockedExchange in not yet ThreadSafe }
  378. lw $v0,($a0)
  379. sw $a1,($a0)
  380. end;
  381. function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler; nostackframe;
  382. asm
  383. {$warning FIXME: This implementation of InterLockedExchangeAdd in not yet ThreadSafe }
  384. lw $v0,($a0)
  385. add $a1,$v0,$a1
  386. sw $a1,($a0)
  387. end;
  388. function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler; nostackframe;
  389. asm
  390. {$warning FIXME: This implementation of InterLockedCompareAdd in not yet ThreadSafe }
  391. { put old value of Target into $v0, result register }
  392. lw $v0,($a0)
  393. { copy to t0 register }
  394. move $t0,$v0
  395. move $v1,$a2
  396. xor $t0,$t0,$v1
  397. beq $t0,$zero,.L1
  398. b .L2
  399. .L1:
  400. {store NewValue (in $a1) into Target in ($(a0)) }
  401. sw $a1,($a0)
  402. .L2:
  403. end;