as_callfunc_arm_vita.S 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2015 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. andreas@angelcode.com
  22. */
  23. /*
  24. Assembly routines for the Playstation Vita SNC call convention.
  25. This code was adapted from as_callfunc_arm_gcc (ARM, Linux hard float) by Brandon Bare on October 2014.
  26. */
  27. #if !defined(AS_MAX_PORTABILITY)
  28. #ifdef __psp2__
  29. .syntax unified
  30. .cpu cortex-a9
  31. .fpu neon
  32. .section .text.armCallFunc
  33. .balign 2
  34. .thumb
  35. .thumb_func
  36. .align 2
  37. .global armFunc
  38. .global armFuncR0
  39. .global armFuncR0R1
  40. .global armFuncObjLast
  41. .global armFuncR0ObjLast
  42. .type armFunc, %function
  43. .type armFuncR0, %function
  44. .type armFuncR0R1, %function
  45. .type armFuncObjLast, %function
  46. .type armFuncR0ObjLast, %function
  47. /* --------------------------------------------------------------------------------------------*/
  48. armFunc:
  49. .fnstart
  50. push {r4-r8, r10, r11, lr} /* sp must be 8-byte alignment for ABI compliance, so the pushed registers must be even */
  51. mov r6, r0 /* arg table */
  52. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  53. mov r4, r2 /* function address */
  54. /* Load float and double args into d0-d7 and s0-s15 */
  55. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  56. mov r8, #0
  57. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  58. /* If there are no arguments to set into r0-r3 */
  59. /* go check if there are arguments for the stack */
  60. beq stackargs
  61. /* Load the first 4 arguments into r0-r3 */
  62. cmp r7, #4
  63. it ge
  64. ldrge r0, [r6]
  65. cmp r7, #8
  66. it ge
  67. ldrge r1, [r6, #4]
  68. cmp r7, #12
  69. it ge
  70. ldrge r2, [r6, #8]
  71. cmp r7, #16
  72. it ge
  73. ldrge r3, [r6, #12]
  74. stackargs:
  75. ldr r5, [r6, #268] /* Load stack size into r5 */
  76. movs r7, r5 /* Load stack size into r7, checking for 0 args */
  77. /* If there are no args for the stack, branch */
  78. beq nomoreargs
  79. /* Load the rest of the arguments onto the stack */
  80. /* Ensure 8-byte stack alignment */
  81. mov r8, sp
  82. sub sp, sp, r7
  83. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  84. sub r12, sp, #8
  85. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  86. sub r8, r8, r12
  87. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  88. stackargsloop:
  89. ldr r5, [r6], #4
  90. subs r7, r7, #4
  91. str r5, [sp], #4
  92. bne stackargsloop
  93. mov sp, r12
  94. nomoreargs:
  95. blx r4
  96. add sp, sp, r8
  97. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d7 to the address stored in r10 */
  98. pop {r4-r8, r10, r11, pc}
  99. .fnend
  100. /* --------------------------------------------------------------------------------------------*/
  101. armFuncObjLast:
  102. .fnstart
  103. push {r4-r8, r10, r11, lr} /* We´re storing r11 just to keep the stack aligned to an 8 byte boundary */
  104. mov r6, r0 /* arg table */
  105. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  106. mov r4, r2 /* function address */
  107. mov r0, r3 /* objlast. might get overwritten */
  108. mov r5, #0 /* This will hold an offset of #4 only if objlast couldn´t be placed into an "r" register */
  109. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  110. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  111. mov r8, #0
  112. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  113. /* If there are no arguments to set into r0-r3 */
  114. /* go check if there are arguments for the stack */
  115. beq stackargsFuncObjLast
  116. mov r5, r3 /* store objlast in r5 temporarily */
  117. /* Load the first 4 arguments into r0-r3 */
  118. cmp r7, #4
  119. it ge
  120. ldrge r0, [r6]
  121. cmp r7, #8
  122. it ge
  123. ldrge r1, [r6,#4]
  124. it lt
  125. movlt r1, r5
  126. cmp r7, #12
  127. it ge
  128. ldrge r2, [r6,#8]
  129. it lt
  130. movlt r2, r5
  131. cmp r7, #16
  132. it ge
  133. ldrge r3, [r6,#12]
  134. ittt lt
  135. movlt r3, r5
  136. movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
  137. blt stackargsFuncObjLast /* If objlast got placed into a register, go to stackargsFuncObjLast */
  138. str r5, [r6, #12] /* Put objlast in r6 + 12 */
  139. mov r5, #4 /* Set r5 with an offset of #4, so objlast can be loaded into the stack */
  140. stackargsFuncObjLast:
  141. ldr r7, [r6, #268] /* Load stack size into r7 */
  142. add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
  143. cmp r7, #0 /* Check for 0 args */
  144. /* If there are no args for the stack, branch */
  145. beq nomoreargsarmFuncObjLast
  146. /* Load the rest of the arguments onto the stack */
  147. /* Ensure 8-byte stack alignment */
  148. mov r8, sp
  149. sub sp, sp, r7
  150. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  151. sub r12, sp, #8
  152. sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
  153. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  154. sub r8, r8, r12
  155. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  156. stackargslooparmFuncObjLast:
  157. ldr r5, [r6], #4
  158. subs r7, r7, #4
  159. str r5, [sp], #4
  160. bne stackargslooparmFuncObjLast
  161. mov sp, r12
  162. nomoreargsarmFuncObjLast:
  163. blx r4
  164. add sp, sp, r8
  165. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  166. pop {r4-r8, r10,r11, pc}
  167. .fnend
  168. /* --------------------------------------------------------------------------------------------*/
  169. armFuncR0ObjLast:
  170. .fnstart
  171. push {r4-r8, r10, r11, lr}
  172. ldr r5, [sp,#32] /* objlast to temp reg */
  173. mov r6, r0 /* arg table */
  174. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  175. mov r4, r2 /* function address */
  176. mov r0, r3 /* r0 explicitly set */
  177. mov r1, r5 /* objlast. might get overwritten */
  178. mov r5, #0 /* This will hold an offset of #4 or #8 if objlast or one arg couldn´t be placed into an "r" register */
  179. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  180. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  181. mov r8, #0
  182. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  183. /* If there are no arguments to set into r0-r3 */
  184. /* go check if there are arguments for the stack */
  185. beq stackargsFuncR0ObjLast
  186. mov r5, r1 /* store objlast in r5 temporarily */
  187. /* Load the first 3 arguments into r1-r3 */
  188. cmp r7, #4
  189. it ge
  190. ldrge r1, [r6]
  191. cmp r7, #8
  192. it ge
  193. ldrge r2, [r6,#4]
  194. it lt
  195. movlt r2, r5
  196. cmp r7, #12
  197. it ge
  198. ldrge r3, [r6,#8]
  199. ittt lt
  200. movlt r3, r5
  201. movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
  202. blt stackargsFuncR0ObjLast /* If objlast got placed into a register, go to stackargsFuncR0ObjLast */
  203. cmp r7, #16 /* Else if we have one last arg set the offset accordingly and store the arg in the array */
  204. itt ge
  205. ldrge r7, [r6, #12]
  206. strge r7, [r6, #8]
  207. str r5, [r6, #12] /* Put objlast in r6 + 12 */
  208. mov r5, #0
  209. it ge
  210. movge r5, #4 /* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
  211. add r5, r5, #4 /* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
  212. stackargsFuncR0ObjLast:
  213. ldr r7, [r6, #268] /* Load stack size into r7 */
  214. add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
  215. cmp r7, #0 /* Check for 0 args */
  216. /* If there are no args for the stack, branch */
  217. beq nomoreargsarmFuncR0ObjLast
  218. /* Load the rest of the arguments onto the stack */
  219. /* Ensure 8-byte stack alignment */
  220. mov r8, sp
  221. sub sp, sp, r7
  222. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  223. sub r12, sp, #8
  224. sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
  225. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  226. sub r8, r8, r12
  227. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  228. stackargslooparmFuncR0ObjLast:
  229. ldr r5, [r6], #4
  230. subs r7, r7, #4
  231. str r5, [sp], #4
  232. bne stackargslooparmFuncR0ObjLast
  233. mov sp, r12
  234. nomoreargsarmFuncR0ObjLast:
  235. blx r4
  236. add sp, sp, r8
  237. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  238. pop {r4-r8, r10, r11, pc}
  239. .fnend
  240. /* --------------------------------------------------------------------------------------------*/
  241. armFuncR0:
  242. .fnstart
  243. push {r4-r8, r10, r11, lr}
  244. mov r6, r0 /* arg table */
  245. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  246. mov r4, r2 /* function address */
  247. mov r11, #0 /* This will hold an offset of #4 only if the last arg that should have been placed into an "r" reg needs to go to the stack */
  248. mov r0, r3 /* r0 explicitly set */
  249. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  250. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  251. mov r8, #0
  252. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  253. /* If there are no arguments to set into r0-r3 */
  254. /* go check if there are arguments for the stack */
  255. beq stackargsarmFuncR0
  256. /* Load the first 3 arguments into r1-r3 */
  257. cmp r7, #4
  258. it ge
  259. ldrge r1, [r6]
  260. cmp r7, #8
  261. it ge
  262. ldrge r2, [r6, #4]
  263. cmp r7, #12
  264. it ge
  265. ldrge r3, [r6, #8]
  266. cmp r7, #16
  267. it ge
  268. movge r11, #4 /* If there is still one arg to be placed, set the offset in r11 to #4 */
  269. stackargsarmFuncR0:
  270. ldr r5, [r6, #268] /* Load stack size into r5 */
  271. add r5, r11 /* Add the offset placed in r11 (could be #0 or #4) */
  272. movs r7, r5 /* Load stack size into r7, checking for 0 args */
  273. /* If there are no args for the stack, branch */
  274. beq nomoreargsarmFuncR0
  275. /* Load the rest of the arguments onto the stack */
  276. /* Ensure 8-byte stack alignment */
  277. mov r8, sp
  278. sub sp, sp, r7
  279. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  280. sub r12, sp, #8
  281. sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4) */
  282. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  283. sub r8, r8, r12
  284. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  285. stackargslooparmFuncR0:
  286. ldr r5, [r6], #4
  287. subs r7, r7, #4
  288. str r5, [sp], #4
  289. bne stackargslooparmFuncR0
  290. mov sp, r12
  291. nomoreargsarmFuncR0:
  292. blx r4
  293. add sp, sp, r8
  294. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  295. pop {r4-r8, r10, r11, pc}
  296. .fnend
  297. /* --------------------------------------------------------------------------------------------*/
  298. armFuncR0R1:
  299. .fnstart
  300. push {r4-r8, r10, r11, lr}
  301. mov r6, r0 /* arg table */
  302. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  303. mov r4, r2 /* function address */
  304. mov r11, #0 /* This will hold an offset of #4 or #8 only if the last arg (or last 2 args) that should have been placed into "r" regs need to go to the stack */
  305. mov r0, r3 /* r0 explicitly set */
  306. ldr r1, [sp, #32] /* r1 explicitly set too */
  307. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  308. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  309. mov r8, #0
  310. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  311. /* If there are no arguments to set into r2-r3 */
  312. /* go check if there are arguments for the stack */
  313. beq stackargsarmFuncR0R1
  314. /* Load the first 2 arguments into r2-r3 */
  315. cmp r7, #4
  316. it ge
  317. ldrge r2, [r6]
  318. cmp r7, #8
  319. it ge
  320. ldrge r3, [r6, #4]
  321. cmp r7, #12
  322. it ge
  323. movge r11, #4 /* If there is a third arg to be placed, set the offset in r11 to #4 */
  324. cmp r7, #16
  325. it ge
  326. movge r11, #8 /* If there is a fourth arg to be placed, set the offset in r11 to #8 */
  327. itt lt
  328. ldrlt r7, [r6, #8] /* Else copy the third arg to the correct place in the array */
  329. strlt r7, [r6, #12]
  330. stackargsarmFuncR0R1:
  331. ldr r5, [r6, #268] /* Load stack size into r5 */
  332. add r5, r11 /* Add the offset placed in r11 (could be #0 or #4 or #8) */
  333. movs r7, r5 /* Load stack size into r7, checking for 0 args */
  334. /* If there are no args for the stack, branch */
  335. beq nomoreargsarmFuncR0R1
  336. /* Load the rest of the arguments onto the stack */
  337. /* Ensure 8-byte stack alignment */
  338. mov r8, sp
  339. sub sp, sp, r7
  340. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  341. sub r12, sp, #8
  342. sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4 or #8) */
  343. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  344. sub r8, r8, r12
  345. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  346. stackargslooparmFuncR0R1:
  347. ldr r5, [r6], #4
  348. subs r7, r7, #4
  349. str r5, [sp], #4
  350. bne stackargslooparmFuncR0R1
  351. mov sp, r12
  352. nomoreargsarmFuncR0R1:
  353. blx r4
  354. add sp, sp, r8
  355. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  356. pop {r4-r8, r10, r11, pc}
  357. .fnend
  358. #endif
  359. #endif /* !AS_MAX_PORTABILITY */