as_callfunc_arm_gcc.S 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2020 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 ARM call convention
  25. Written by Fredrik Ehnbom in June 2009
  26. Adapted to GNUC by darktemplar216 in September 2009
  27. Modified by Lasse Oorni for 8-byte stack alignment in May 2012
  28. The assembler routines for Linux were written by Carlos Luna in December 2012
  29. */
  30. #if !defined(AS_MAX_PORTABILITY)
  31. #if defined(__arm__) || defined(__ARM__) || defined(I3D_ARCH_ARM)
  32. #if !defined(__linux__) || defined(__ANDROID__) || defined(ANDROID) || defined(__SOFTFP__) || defined(__ARM_PCS)
  33. /* iOS, Android, Marmalade, and Linux with soft-float ABI goes here */
  34. .global armFunc
  35. .global armFuncR0
  36. .global armFuncR0R1
  37. .global armFuncObjLast
  38. .global armFuncR0ObjLast
  39. /* --------------------------------------------------------------------------------------------*/
  40. armFunc:
  41. stmdb sp!, {r4-r8, lr}
  42. mov r6, r0 /* arg table */
  43. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  44. mov r4, r2 /* function address */
  45. mov r8, #0
  46. beq nomoreargs
  47. /* Load the first 4 arguments into r0-r3 */
  48. cmp r7, #4
  49. ldrge r0, [r6],#4
  50. cmp r7, #2*4
  51. ldrge r1, [r6],#4
  52. cmp r7, #3*4
  53. ldrge r2, [r6],#4
  54. cmp r7, #4*4
  55. ldrge r3, [r6],#4
  56. ble nomoreargs
  57. /* Load the rest of the arguments onto the stack */
  58. sub r7, r7, #4*4 /* skip the 4 registers already loaded into r0-r3 */
  59. add r8, r7, #4 /* ensure 8-byte stack alignment */
  60. bic r8, r8, #4
  61. sub sp, sp, r8
  62. mov r12, sp /* copy size != frame size, so store frame start sp */
  63. stackargsloop:
  64. ldr r5, [r6], #4
  65. str r5, [sp], #4
  66. subs r7, r7, #4
  67. bne stackargsloop
  68. mov sp, r12
  69. nomoreargs:
  70. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  71. mov lr, pc /* older ARM didn't support blx */
  72. mov pc, r4
  73. #else
  74. blx r4
  75. #endif
  76. add sp, sp, r8
  77. ldmia sp!, {r4-r8, pc}
  78. /* --------------------------------------------------------------------------------------------*/
  79. armFuncObjLast:
  80. stmdb sp!, {r4-r8, lr}
  81. mov r6, r0 /* arg table */
  82. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  83. mov r4, r2 /* function address */
  84. mov r8, #0
  85. mov r0, r3 /* objlast. might get overwritten */
  86. mov r5, r3 /* objlast to temp reg */
  87. beq nomoreargsarmFuncObjLast
  88. /* Load the first 4 arguments into r0-r3 */
  89. cmp r7, #4
  90. ldrge r0, [r6],#4
  91. cmp r7, #2*4
  92. ldrge r1, [r6],#4
  93. movlt r1, r5
  94. cmp r7, #3*4
  95. ldrge r2, [r6],#4
  96. movlt r2, r5
  97. cmp r7, #4*4
  98. ldrge r3, [r6],#4
  99. movlt r3, r5
  100. blt nomoreargsarmFuncObjLast
  101. /* Load the rest of the arguments onto the stack */
  102. sub r7, r7, #4*4 /* skip the 4 registers already loaded into r0-r3 */
  103. add r8, r7, #8 /* account for the objlast pointer, ensure 8-byte stack alignment */
  104. bic r8, r8, #4
  105. str r5, [sp,#-4] /* store the objlast on stack, twice in case we adjusted alignment */
  106. str r5, [sp,#-8]
  107. sub sp, sp, r8 /* adjust frame */
  108. cmp r7, #0 /* we may also have come here with no extra params */
  109. beq nomoreargsarmFuncObjLast
  110. mov r12, sp /* copy size != frame size, so store frame start sp */
  111. stackargslooparmFuncObjLast:
  112. ldr r5, [r6], #4
  113. str r5, [sp], #4
  114. subs r7, r7, #4
  115. bne stackargslooparmFuncObjLast
  116. mov sp, r12
  117. nomoreargsarmFuncObjLast:
  118. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  119. mov lr, pc /* older ARM didn't support blx */
  120. mov pc, r4
  121. #else
  122. blx r4
  123. #endif
  124. add sp, sp, r8
  125. ldmia sp!, {r4-r8, pc}
  126. /* --------------------------------------------------------------------------------------------*/
  127. armFuncR0ObjLast:
  128. stmdb sp!, {r4-r8, lr}
  129. ldr r5, [sp,#6*4] /* objlast to temp reg */
  130. mov r6, r0 /* arg table */
  131. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  132. mov r4, r2 /* function address */
  133. mov r8, #0
  134. mov r0, r3 /* r0 explicitly set */
  135. mov r1, r5 /* objlast. might get overwritten */
  136. beq nomoreargsarmFuncR0ObjLast
  137. /* Load the first 3 arguments into r1-r3 */
  138. cmp r7, #1*4
  139. ldrge r1, [r6],#4
  140. cmp r7, #2*4
  141. ldrge r2, [r6],#4
  142. movlt r2, r5
  143. cmp r7, #3*4
  144. ldrge r3, [r6],#4
  145. movlt r3, r5
  146. blt nomoreargsarmFuncR0ObjLast
  147. /* Load the rest of the arguments onto the stack */
  148. sub r7, r7, #3*4 /* skip the 3 registers already loaded into r1-r3 */
  149. add r8, r7, #8 /* account for the objlast pointer, ensure 8-byte stack alignment */
  150. bic r8, r8, #4
  151. str r5, [sp,#-4] /* store the objlast on stack, twice in case we adjusted alignment */
  152. str r5, [sp,#-8]
  153. sub sp, sp, r8 /* adjust frame */
  154. cmp r7, #0 /* we may also have come here with no extra params */
  155. beq nomoreargsarmFuncR0ObjLast
  156. mov r12, sp /* copy size != frame size, so store frame start sp */
  157. stackargslooparmFuncR0ObjLast:
  158. ldr r5, [r6], #4
  159. str r5, [sp], #4
  160. subs r7, r7, #4
  161. bne stackargslooparmFuncR0ObjLast
  162. mov sp, r12
  163. nomoreargsarmFuncR0ObjLast:
  164. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  165. mov lr, pc /* older ARM didn't support blx */
  166. mov pc, r4
  167. #else
  168. blx r4
  169. #endif
  170. add sp, sp, r8
  171. ldmia sp!, {r4-r8, pc}
  172. /* --------------------------------------------------------------------------------------------*/
  173. armFuncR0:
  174. stmdb sp!, {r4-r8, lr}
  175. mov r6, r0 /* arg table */
  176. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  177. mov r4, r2 /* function address */
  178. mov r8, #0
  179. mov r0, r3 /* r0 explicitly set */
  180. beq nomoreargsarmFuncR0
  181. /* Load the first 3 arguments into r1-r3 */
  182. cmp r7, #1*4
  183. ldrge r1, [r6],#4
  184. cmp r7, #2*4
  185. ldrge r2, [r6],#4
  186. cmp r7, #3*4
  187. ldrge r3, [r6],#4
  188. ble nomoreargsarmFuncR0
  189. /* Load the rest of the arguments onto the stack */
  190. sub r7, r7, #3*4 /* skip the 3 registers already loaded into r1-r3 */
  191. add r8, r7, #4 /* ensure 8-byte stack alignment */
  192. bic r8, r8, #4
  193. sub sp, sp, r8
  194. mov r12, sp /* copy size != frame size, so store frame start sp */
  195. stackargslooparmFuncR0:
  196. ldr r5, [r6], #4
  197. str r5, [sp], #4
  198. subs r7, r7, #4
  199. bne stackargslooparmFuncR0
  200. mov sp, r12
  201. nomoreargsarmFuncR0:
  202. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  203. mov lr, pc /* older ARM didn't support blx */
  204. mov pc, r4
  205. #else
  206. blx r4
  207. #endif
  208. add sp, sp, r8
  209. ldmia sp!, {r4-r8, pc}
  210. /* --------------------------------------------------------------------------------------------*/
  211. armFuncR0R1:
  212. stmdb sp!, {r4-r8, lr}
  213. mov r6, r0 /* arg table */
  214. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  215. mov r4, r2 /* function address */
  216. mov r8, #0
  217. mov r0, r3 /* r0 explicitly set */
  218. ldr r1, [sp, #6*4] /* r1 explicitly set too */
  219. beq nomoreargsarmFuncR0R1
  220. /* Load the first 2 arguments into r2-r3 */
  221. cmp r7, #1*4
  222. ldrge r2, [r6],#4
  223. cmp r7, #2*4
  224. ldrge r3, [r6],#4
  225. ble nomoreargsarmFuncR0R1
  226. /* Load the rest of the arguments onto the stack */
  227. sub r7, r7, #2*4 /* skip the 2 registers already loaded into r2-r3 */
  228. add r8, r7, #4 /* ensure 8-byte stack alignment */
  229. bic r8, r8, #4
  230. sub sp, sp, r8
  231. mov r12, sp /* copy size != frame size, so store frame start sp */
  232. stackargslooparmFuncR0R1:
  233. ldr r5, [r6], #4
  234. str r5, [sp], #4
  235. subs r7, r7, #4
  236. bne stackargslooparmFuncR0R1
  237. mov sp, r12
  238. nomoreargsarmFuncR0R1:
  239. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  240. mov lr, pc /* older ARM didn't support blx */
  241. mov pc, r4
  242. #else
  243. blx r4
  244. #endif
  245. add sp, sp, r8
  246. ldmia sp!, {r4-r8, pc}
  247. /* --------------------------------------------------------------------------------------------*/
  248. #elif defined(__linux__) && !defined(__SOFTFP__) && !defined(__ARM_PCS)
  249. /* The Linux with hard-float ABI code goes here */
  250. /* These codes are suitable for armeabi + vfp / armeabihf */
  251. /* when using armeabi + vfp, please set C_FLAGS -mfloat-abi=softfp -mfpu=vfp */
  252. /* using armeabihf, please set C_FLAGS -mfloat-abi=hard -mfpu=vfpv3-d16 */
  253. /* if you prefer to run in ARM mode, please add -marm to C_FLAGS */
  254. /* while using thumb mode, please add -mthumb -Wa,-mimplicit-it=thumb */
  255. /* SP is a multiple of 8 when control first enters a program.*/
  256. /* This places an obligation on authors of low level OS, RTOS, and runtime library code to align SP at all points */
  257. /* at which control first enters a body of (AAPCS-conforming) code. (please read "ARM IHI 0046B" document)*/
  258. .section .text
  259. .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
  260. #if defined(__thumb__) || defined(__thumb2__)
  261. .thumb
  262. .syntax unified
  263. #else
  264. .arm /* Use ARM instructions instead of Thumb.*/
  265. #endif
  266. .globl armFunc /* Make the function globally accessible.*/
  267. armFunc:
  268. push {r4-r8, r10, r11, lr} /* sp must be 8-byte alignment for ABI compliance, so the pushed registers must be even */
  269. mov r6, r0 /* arg table */
  270. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  271. mov r4, r2 /* function address */
  272. /* Load float and double args into d0-d7 and s0-s15 */
  273. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  274. mov r8, #0
  275. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  276. /* If there are no arguments to set into r0-r3 */
  277. /* go check if there are arguments for the stack */
  278. beq stackargs
  279. /* Load the first 4 arguments into r0-r3 */
  280. cmp r7, #4
  281. ldrge r0, [r6]
  282. cmp r7, #8
  283. ldrge r1, [r6, #4]
  284. cmp r7, #12
  285. ldrge r2, [r6, #8]
  286. cmp r7, #16
  287. ldrge r3, [r6, #12]
  288. stackargs:
  289. ldr r5, [r6, #268] /* Load stack size into r5 */
  290. movs r7, r5 /* Load stack size into r7, checking for 0 args */
  291. /* If there are no args for the stack, branch */
  292. beq nomoreargs
  293. /* Load the rest of the arguments onto the stack */
  294. /* Ensure 8-byte stack alignment */
  295. mov r8, sp
  296. sub sp, sp, r7
  297. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  298. sub r12, sp, #8
  299. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  300. sub r8, r8, r12
  301. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  302. stackargsloop:
  303. ldr r5, [r6], #4
  304. subs r7, r7, #4
  305. str r5, [sp], #4
  306. bne stackargsloop
  307. mov sp, r12
  308. nomoreargs:
  309. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  310. mov lr, pc /* older ARM didn't support blx */
  311. mov pc, r4
  312. #else
  313. blx r4
  314. #endif
  315. add sp, sp, r8
  316. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d7 to the address stored in r10 */
  317. pop {r4-r8, r10, r11, pc}
  318. /* --------------------------------------------------------------------------------------------*/
  319. .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
  320. #if defined(__thumb__) || defined(__thumb2__)
  321. .thumb
  322. .syntax unified
  323. #else
  324. .arm /* Use ARM instructions instead of Thumb.*/
  325. #endif
  326. .globl armFuncObjLast /* Make the function globally accessible.*/
  327. armFuncObjLast:
  328. push {r4-r8, r10, r11, lr} /* We´re storing r11 just to keep the stack aligned to an 8 byte boundary */
  329. mov r6, r0 /* arg table */
  330. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  331. mov r4, r2 /* function address */
  332. mov r0, r3 /* objlast. might get overwritten */
  333. mov r5, #0 /* This will hold an offset of #4 only if objlast couldn´t be placed into an "r" register */
  334. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  335. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  336. mov r8, #0
  337. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  338. /* If there are no arguments to set into r0-r3 */
  339. /* go check if there are arguments for the stack */
  340. beq stackargsFuncObjLast
  341. mov r5, r3 /* store objlast in r5 temporarily */
  342. /* Load the first 4 arguments into r0-r3 */
  343. cmp r7, #4
  344. ldrge r0, [r6]
  345. cmp r7, #8
  346. ldrge r1, [r6,#4]
  347. movlt r1, r5
  348. cmp r7, #12
  349. ldrge r2, [r6,#8]
  350. movlt r2, r5
  351. cmp r7, #16
  352. ldrge r3, [r6,#12]
  353. movlt r3, r5
  354. movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
  355. blt stackargsFuncObjLast /* If objlast got placed into a register, go to stackargsFuncObjLast */
  356. str r5, [r6, #12] /* Put objlast in r6 + 12 */
  357. mov r5, #4 /* Set r5 with an offset of #4, so objlast can be loaded into the stack */
  358. stackargsFuncObjLast:
  359. ldr r7, [r6, #268] /* Load stack size into r7 */
  360. add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
  361. cmp r7, #0 /* Check for 0 args */
  362. /* If there are no args for the stack, branch */
  363. beq nomoreargsarmFuncObjLast
  364. /* Load the rest of the arguments onto the stack */
  365. /* Ensure 8-byte stack alignment */
  366. mov r8, sp
  367. sub sp, sp, r7
  368. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  369. sub r12, sp, #8
  370. sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
  371. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  372. sub r8, r8, r12
  373. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  374. stackargslooparmFuncObjLast:
  375. ldr r5, [r6], #4
  376. subs r7, r7, #4
  377. str r5, [sp], #4
  378. bne stackargslooparmFuncObjLast
  379. mov sp, r12
  380. nomoreargsarmFuncObjLast:
  381. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  382. mov lr, pc /* older ARM didn't support blx */
  383. mov pc, r4
  384. #else
  385. blx r4
  386. #endif
  387. add sp, sp, r8
  388. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  389. pop {r4-r8, r10,r11, pc}
  390. /* ------------------------------------------------------------------------------------------- */
  391. .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
  392. #if defined(__thumb__) || defined(__thumb2__)
  393. .thumb
  394. .syntax unified
  395. #else
  396. .arm /* Use ARM instructions instead of Thumb.*/
  397. #endif
  398. .globl armFuncR0ObjLast /* Make the function globally accessible.*/
  399. armFuncR0ObjLast:
  400. push {r4-r8, r10, r11, lr}
  401. ldr r5, [sp,#32] /* objlast to temp reg */
  402. mov r6, r0 /* arg table */
  403. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  404. mov r4, r2 /* function address */
  405. mov r0, r3 /* r0 explicitly set */
  406. mov r1, r5 /* objlast. might get overwritten */
  407. 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 */
  408. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  409. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  410. mov r8, #0
  411. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  412. /* If there are no arguments to set into r0-r3 */
  413. /* go check if there are arguments for the stack */
  414. beq stackargsFuncR0ObjLast
  415. mov r5, r1 /* store objlast in r5 temporarily */
  416. /* Load the first 3 arguments into r1-r3 */
  417. cmp r7, #4
  418. ldrge r1, [r6]
  419. cmp r7, #8
  420. ldrge r2, [r6,#4]
  421. movlt r2, r5
  422. cmp r7, #12
  423. ldrge r3, [r6,#8]
  424. movlt r3, r5
  425. movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
  426. blt stackargsFuncR0ObjLast /* If objlast got placed into a register, go to stackargsFuncR0ObjLast */
  427. cmp r7, #16 /* Else if we have one last arg set the offset accordingly and store the arg in the array */
  428. ldrge r7, [r6, #12]
  429. strge r7, [r6, #8]
  430. str r5, [r6, #12] /* Put objlast in r6 + 12 */
  431. mov r5, #0
  432. movge r5, #4 /* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
  433. add r5, r5, #4 /* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
  434. stackargsFuncR0ObjLast:
  435. ldr r7, [r6, #268] /* Load stack size into r7 */
  436. add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
  437. cmp r7, #0 /* Check for 0 args */
  438. /* If there are no args for the stack, branch */
  439. beq nomoreargsarmFuncR0ObjLast
  440. /* Load the rest of the arguments onto the stack */
  441. /* Ensure 8-byte stack alignment */
  442. mov r8, sp
  443. sub sp, sp, r7
  444. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  445. sub r12, sp, #8
  446. sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
  447. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  448. sub r8, r8, r12
  449. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  450. stackargslooparmFuncR0ObjLast:
  451. ldr r5, [r6], #4
  452. subs r7, r7, #4
  453. str r5, [sp], #4
  454. bne stackargslooparmFuncR0ObjLast
  455. mov sp, r12
  456. nomoreargsarmFuncR0ObjLast:
  457. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  458. mov lr, pc /* older ARM didn't support blx */
  459. mov pc, r4
  460. #else
  461. blx r4
  462. #endif
  463. add sp, sp, r8
  464. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  465. pop {r4-r8, r10, r11, pc}
  466. /* ------------------------------------------------------------------------------------------- */
  467. .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
  468. #if defined(__thumb__) || defined(__thumb2__)
  469. .thumb
  470. .syntax unified
  471. #else
  472. .arm /* Use ARM instructions instead of Thumb.*/
  473. #endif
  474. .globl armFuncR0 /* Make the function globally accessible.*/
  475. armFuncR0:
  476. push {r4-r8, r10, r11, lr}
  477. mov r6, r0 /* arg table */
  478. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  479. mov r4, r2 /* function address */
  480. 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 */
  481. mov r0, r3 /* r0 explicitly set */
  482. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  483. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  484. mov r8, #0
  485. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  486. /* If there are no arguments to set into r0-r3 */
  487. /* go check if there are arguments for the stack */
  488. beq stackargsarmFuncR0
  489. /* Load the first 3 arguments into r1-r3 */
  490. cmp r7, #4
  491. ldrge r1, [r6]
  492. cmp r7, #8
  493. ldrge r2, [r6, #4]
  494. cmp r7, #12
  495. ldrge r3, [r6, #8]
  496. cmp r7, #16
  497. movge r11, #4 /* If there is still one arg to be placed, set the offset in r11 to #4 */
  498. stackargsarmFuncR0:
  499. ldr r5, [r6, #268] /* Load stack size into r5 */
  500. add r5, r11 /* Add the offset placed in r11 (could be #0 or #4) */
  501. movs r7, r5 /* Load stack size into r7, checking for 0 args */
  502. /* If there are no args for the stack, branch */
  503. beq nomoreargsarmFuncR0
  504. /* Load the rest of the arguments onto the stack */
  505. /* Ensure 8-byte stack alignment */
  506. mov r8, sp
  507. sub sp, sp, r7
  508. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  509. sub r12, sp, #8
  510. sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4) */
  511. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  512. sub r8, r8, r12
  513. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  514. stackargslooparmFuncR0:
  515. ldr r5, [r6], #4
  516. subs r7, r7, #4
  517. str r5, [sp], #4
  518. bne stackargslooparmFuncR0
  519. mov sp, r12
  520. nomoreargsarmFuncR0:
  521. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  522. mov lr, pc /* older ARM didn't support blx */
  523. mov pc, r4
  524. #else
  525. blx r4
  526. #endif
  527. add sp, sp, r8
  528. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  529. pop {r4-r8, r10, r11, pc}
  530. /* ------------------------------------------------------------------------------------------- */
  531. .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
  532. #if defined(__thumb__) || defined(__thumb2__)
  533. .thumb
  534. .syntax unified
  535. #else
  536. .arm /* Use ARM instructions instead of Thumb.*/
  537. #endif
  538. .globl armFuncR0R1 /* Make the function globally accessible.*/
  539. armFuncR0R1:
  540. push {r4-r8, r10, r11, lr}
  541. mov r6, r0 /* arg table */
  542. movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
  543. mov r4, r2 /* function address */
  544. 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 */
  545. mov r0, r3 /* r0 explicitly set */
  546. ldr r1, [sp, #32] /* r1 explicitly set too */
  547. /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
  548. add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
  549. mov r8, #0
  550. vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
  551. /* If there are no arguments to set into r2-r3 */
  552. /* go check if there are arguments for the stack */
  553. beq stackargsarmFuncR0R1
  554. /* Load the first 2 arguments into r2-r3 */
  555. cmp r7, #4
  556. ldrge r2, [r6]
  557. cmp r7, #8
  558. ldrge r3, [r6, #4]
  559. cmp r7, #12
  560. movge r11, #4 /* If there is a third arg to be placed, set the offset in r11 to #4 */
  561. cmp r7, #16
  562. movge r11, #8 /* If there is a fourth arg to be placed, set the offset in r11 to #8 */
  563. ldrlt r7, [r6, #8] /* Else copy the third arg to the correct place in the array */
  564. strlt r7, [r6, #12]
  565. stackargsarmFuncR0R1:
  566. ldr r5, [r6, #268] /* Load stack size into r5 */
  567. add r5, r11 /* Add the offset placed in r11 (could be #0 or #4 or #8) */
  568. movs r7, r5 /* Load stack size into r7, checking for 0 args */
  569. /* If there are no args for the stack, branch */
  570. beq nomoreargsarmFuncR0R1
  571. /* Load the rest of the arguments onto the stack */
  572. /* Ensure 8-byte stack alignment */
  573. mov r8, sp
  574. sub sp, sp, r7
  575. add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
  576. sub r12, sp, #8
  577. sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4 or #8) */
  578. bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
  579. sub r8, r8, r12
  580. mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
  581. stackargslooparmFuncR0R1:
  582. ldr r5, [r6], #4
  583. subs r7, r7, #4
  584. str r5, [sp], #4
  585. bne stackargslooparmFuncR0R1
  586. mov sp, r12
  587. nomoreargsarmFuncR0R1:
  588. #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
  589. mov lr, pc /* older ARM didn't support blx */
  590. mov pc, r4
  591. #else
  592. blx r4
  593. #endif
  594. add sp, sp, r8
  595. vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
  596. pop {r4-r8, r10, r11, pc}
  597. #endif /* hard float abi */
  598. #endif /* arm */
  599. #if defined(__linux__) && defined(__ELF__)
  600. /* ref: http://hardened.gentoo.org/gnu-stack.xml
  601. ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart */
  602. .section .note.GNU-stack,"",%progbits
  603. #endif
  604. #endif /* !AS_MAX_PORTABILITY */