123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731 |
- /*
- AngelCode Scripting Library
- Copyright (c) 2003-2020 Andreas Jonsson
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any
- damages arising from the use of this software.
- Permission is granted to anyone to use this software for any
- purpose, including commercial applications, and to alter it and
- redistribute it freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you
- must not claim that you wrote the original software. If you use
- this software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and
- must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source
- distribution.
- The original version of this library can be located at:
- http://www.angelcode.com/angelscript/
- Andreas Jonsson
- andreas@angelcode.com
- */
- /*
- Assembly routines for the ARM call convention
- Written by Fredrik Ehnbom in June 2009
- Adapted to GNUC by darktemplar216 in September 2009
- Modified by Lasse Oorni for 8-byte stack alignment in May 2012
- The assembler routines for Linux were written by Carlos Luna in December 2012
- */
- #if !defined(AS_MAX_PORTABILITY)
- #if defined(__arm__) || defined(__ARM__) || defined(I3D_ARCH_ARM)
- #if !defined(__linux__) || defined(__ANDROID__) || defined(ANDROID) || defined(__SOFTFP__) || defined(__ARM_PCS)
- /* iOS, Android, Marmalade, and Linux with soft-float ABI goes here */
- .global armFunc
- .global armFuncR0
- .global armFuncR0R1
- .global armFuncObjLast
- .global armFuncR0ObjLast
- /* --------------------------------------------------------------------------------------------*/
- armFunc:
- stmdb sp!, {r4-r8, lr}
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- mov r8, #0
- beq nomoreargs
- /* Load the first 4 arguments into r0-r3 */
- cmp r7, #4
- ldrge r0, [r6],#4
- cmp r7, #2*4
- ldrge r1, [r6],#4
- cmp r7, #3*4
- ldrge r2, [r6],#4
- cmp r7, #4*4
- ldrge r3, [r6],#4
- ble nomoreargs
- /* Load the rest of the arguments onto the stack */
- sub r7, r7, #4*4 /* skip the 4 registers already loaded into r0-r3 */
- add r8, r7, #4 /* ensure 8-byte stack alignment */
- bic r8, r8, #4
- sub sp, sp, r8
- mov r12, sp /* copy size != frame size, so store frame start sp */
- stackargsloop:
- ldr r5, [r6], #4
- str r5, [sp], #4
- subs r7, r7, #4
- bne stackargsloop
- mov sp, r12
- nomoreargs:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- ldmia sp!, {r4-r8, pc}
- /* --------------------------------------------------------------------------------------------*/
- armFuncObjLast:
- stmdb sp!, {r4-r8, lr}
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- mov r8, #0
- mov r0, r3 /* objlast. might get overwritten */
- mov r5, r3 /* objlast to temp reg */
- beq nomoreargsarmFuncObjLast
- /* Load the first 4 arguments into r0-r3 */
- cmp r7, #4
- ldrge r0, [r6],#4
- cmp r7, #2*4
- ldrge r1, [r6],#4
- movlt r1, r5
- cmp r7, #3*4
- ldrge r2, [r6],#4
- movlt r2, r5
- cmp r7, #4*4
- ldrge r3, [r6],#4
- movlt r3, r5
- blt nomoreargsarmFuncObjLast
- /* Load the rest of the arguments onto the stack */
- sub r7, r7, #4*4 /* skip the 4 registers already loaded into r0-r3 */
- add r8, r7, #8 /* account for the objlast pointer, ensure 8-byte stack alignment */
- bic r8, r8, #4
- str r5, [sp,#-4] /* store the objlast on stack, twice in case we adjusted alignment */
- str r5, [sp,#-8]
- sub sp, sp, r8 /* adjust frame */
- cmp r7, #0 /* we may also have come here with no extra params */
- beq nomoreargsarmFuncObjLast
- mov r12, sp /* copy size != frame size, so store frame start sp */
- stackargslooparmFuncObjLast:
- ldr r5, [r6], #4
- str r5, [sp], #4
- subs r7, r7, #4
- bne stackargslooparmFuncObjLast
- mov sp, r12
- nomoreargsarmFuncObjLast:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- ldmia sp!, {r4-r8, pc}
- /* --------------------------------------------------------------------------------------------*/
- armFuncR0ObjLast:
- stmdb sp!, {r4-r8, lr}
- ldr r5, [sp,#6*4] /* objlast to temp reg */
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- mov r8, #0
- mov r0, r3 /* r0 explicitly set */
- mov r1, r5 /* objlast. might get overwritten */
- beq nomoreargsarmFuncR0ObjLast
- /* Load the first 3 arguments into r1-r3 */
- cmp r7, #1*4
- ldrge r1, [r6],#4
- cmp r7, #2*4
- ldrge r2, [r6],#4
- movlt r2, r5
- cmp r7, #3*4
- ldrge r3, [r6],#4
- movlt r3, r5
- blt nomoreargsarmFuncR0ObjLast
- /* Load the rest of the arguments onto the stack */
- sub r7, r7, #3*4 /* skip the 3 registers already loaded into r1-r3 */
- add r8, r7, #8 /* account for the objlast pointer, ensure 8-byte stack alignment */
- bic r8, r8, #4
- str r5, [sp,#-4] /* store the objlast on stack, twice in case we adjusted alignment */
- str r5, [sp,#-8]
- sub sp, sp, r8 /* adjust frame */
- cmp r7, #0 /* we may also have come here with no extra params */
- beq nomoreargsarmFuncR0ObjLast
- mov r12, sp /* copy size != frame size, so store frame start sp */
- stackargslooparmFuncR0ObjLast:
- ldr r5, [r6], #4
- str r5, [sp], #4
- subs r7, r7, #4
- bne stackargslooparmFuncR0ObjLast
- mov sp, r12
- nomoreargsarmFuncR0ObjLast:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- ldmia sp!, {r4-r8, pc}
- /* --------------------------------------------------------------------------------------------*/
- armFuncR0:
- stmdb sp!, {r4-r8, lr}
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- mov r8, #0
- mov r0, r3 /* r0 explicitly set */
- beq nomoreargsarmFuncR0
- /* Load the first 3 arguments into r1-r3 */
- cmp r7, #1*4
- ldrge r1, [r6],#4
- cmp r7, #2*4
- ldrge r2, [r6],#4
- cmp r7, #3*4
- ldrge r3, [r6],#4
- ble nomoreargsarmFuncR0
- /* Load the rest of the arguments onto the stack */
- sub r7, r7, #3*4 /* skip the 3 registers already loaded into r1-r3 */
- add r8, r7, #4 /* ensure 8-byte stack alignment */
- bic r8, r8, #4
- sub sp, sp, r8
- mov r12, sp /* copy size != frame size, so store frame start sp */
- stackargslooparmFuncR0:
- ldr r5, [r6], #4
- str r5, [sp], #4
- subs r7, r7, #4
- bne stackargslooparmFuncR0
- mov sp, r12
- nomoreargsarmFuncR0:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- ldmia sp!, {r4-r8, pc}
- /* --------------------------------------------------------------------------------------------*/
- armFuncR0R1:
- stmdb sp!, {r4-r8, lr}
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- mov r8, #0
- mov r0, r3 /* r0 explicitly set */
- ldr r1, [sp, #6*4] /* r1 explicitly set too */
- beq nomoreargsarmFuncR0R1
- /* Load the first 2 arguments into r2-r3 */
- cmp r7, #1*4
- ldrge r2, [r6],#4
- cmp r7, #2*4
- ldrge r3, [r6],#4
- ble nomoreargsarmFuncR0R1
- /* Load the rest of the arguments onto the stack */
- sub r7, r7, #2*4 /* skip the 2 registers already loaded into r2-r3 */
- add r8, r7, #4 /* ensure 8-byte stack alignment */
- bic r8, r8, #4
- sub sp, sp, r8
- mov r12, sp /* copy size != frame size, so store frame start sp */
- stackargslooparmFuncR0R1:
- ldr r5, [r6], #4
- str r5, [sp], #4
- subs r7, r7, #4
- bne stackargslooparmFuncR0R1
- mov sp, r12
- nomoreargsarmFuncR0R1:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- ldmia sp!, {r4-r8, pc}
- /* --------------------------------------------------------------------------------------------*/
- #elif defined(__linux__) && !defined(__SOFTFP__) && !defined(__ARM_PCS)
- /* The Linux with hard-float ABI code goes here */
- /* These codes are suitable for armeabi + vfp / armeabihf */
- /* when using armeabi + vfp, please set C_FLAGS -mfloat-abi=softfp -mfpu=vfp */
- /* using armeabihf, please set C_FLAGS -mfloat-abi=hard -mfpu=vfpv3-d16 */
- /* if you prefer to run in ARM mode, please add -marm to C_FLAGS */
- /* while using thumb mode, please add -mthumb -Wa,-mimplicit-it=thumb */
- /* SP is a multiple of 8 when control first enters a program.*/
- /* This places an obligation on authors of low level OS, RTOS, and runtime library code to align SP at all points */
- /* at which control first enters a body of (AAPCS-conforming) code. (please read "ARM IHI 0046B" document)*/
- .section .text
- .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
- #if defined(__thumb__) || defined(__thumb2__)
- .thumb
- .syntax unified
- #else
- .arm /* Use ARM instructions instead of Thumb.*/
- #endif
- .globl armFunc /* Make the function globally accessible.*/
- armFunc:
- push {r4-r8, r10, r11, lr} /* sp must be 8-byte alignment for ABI compliance, so the pushed registers must be even */
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- /* Load float and double args into d0-d7 and s0-s15 */
- add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
- mov r8, #0
- vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
- /* If there are no arguments to set into r0-r3 */
- /* go check if there are arguments for the stack */
- beq stackargs
- /* Load the first 4 arguments into r0-r3 */
- cmp r7, #4
- ldrge r0, [r6]
- cmp r7, #8
- ldrge r1, [r6, #4]
- cmp r7, #12
- ldrge r2, [r6, #8]
- cmp r7, #16
- ldrge r3, [r6, #12]
- stackargs:
- ldr r5, [r6, #268] /* Load stack size into r5 */
- movs r7, r5 /* Load stack size into r7, checking for 0 args */
- /* If there are no args for the stack, branch */
- beq nomoreargs
- /* Load the rest of the arguments onto the stack */
- /* Ensure 8-byte stack alignment */
- mov r8, sp
- sub sp, sp, r7
- add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
- sub r12, sp, #8
- bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
- sub r8, r8, r12
- mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
- stackargsloop:
- ldr r5, [r6], #4
- subs r7, r7, #4
- str r5, [sp], #4
- bne stackargsloop
- mov sp, r12
- nomoreargs:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d7 to the address stored in r10 */
- pop {r4-r8, r10, r11, pc}
- /* --------------------------------------------------------------------------------------------*/
- .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
- #if defined(__thumb__) || defined(__thumb2__)
- .thumb
- .syntax unified
- #else
- .arm /* Use ARM instructions instead of Thumb.*/
- #endif
- .globl armFuncObjLast /* Make the function globally accessible.*/
- armFuncObjLast:
- push {r4-r8, r10, r11, lr} /* We´re storing r11 just to keep the stack aligned to an 8 byte boundary */
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- mov r0, r3 /* objlast. might get overwritten */
- mov r5, #0 /* This will hold an offset of #4 only if objlast couldn´t be placed into an "r" register */
- /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
- add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
- mov r8, #0
- vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
- /* If there are no arguments to set into r0-r3 */
- /* go check if there are arguments for the stack */
- beq stackargsFuncObjLast
- mov r5, r3 /* store objlast in r5 temporarily */
- /* Load the first 4 arguments into r0-r3 */
- cmp r7, #4
- ldrge r0, [r6]
- cmp r7, #8
- ldrge r1, [r6,#4]
- movlt r1, r5
- cmp r7, #12
- ldrge r2, [r6,#8]
- movlt r2, r5
- cmp r7, #16
- ldrge r3, [r6,#12]
- movlt r3, r5
- movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
- blt stackargsFuncObjLast /* If objlast got placed into a register, go to stackargsFuncObjLast */
- str r5, [r6, #12] /* Put objlast in r6 + 12 */
- mov r5, #4 /* Set r5 with an offset of #4, so objlast can be loaded into the stack */
- stackargsFuncObjLast:
- ldr r7, [r6, #268] /* Load stack size into r7 */
- add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
- cmp r7, #0 /* Check for 0 args */
- /* If there are no args for the stack, branch */
- beq nomoreargsarmFuncObjLast
- /* Load the rest of the arguments onto the stack */
- /* Ensure 8-byte stack alignment */
- mov r8, sp
- sub sp, sp, r7
- add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
- sub r12, sp, #8
- sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
- bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
- sub r8, r8, r12
- mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
- stackargslooparmFuncObjLast:
- ldr r5, [r6], #4
- subs r7, r7, #4
- str r5, [sp], #4
- bne stackargslooparmFuncObjLast
- mov sp, r12
- nomoreargsarmFuncObjLast:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
- pop {r4-r8, r10,r11, pc}
- /* ------------------------------------------------------------------------------------------- */
- .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
- #if defined(__thumb__) || defined(__thumb2__)
- .thumb
- .syntax unified
- #else
- .arm /* Use ARM instructions instead of Thumb.*/
- #endif
- .globl armFuncR0ObjLast /* Make the function globally accessible.*/
- armFuncR0ObjLast:
- push {r4-r8, r10, r11, lr}
- ldr r5, [sp,#32] /* objlast to temp reg */
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- mov r0, r3 /* r0 explicitly set */
- mov r1, r5 /* objlast. might get overwritten */
- 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 */
- /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
- add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
- mov r8, #0
- vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
- /* If there are no arguments to set into r0-r3 */
- /* go check if there are arguments for the stack */
- beq stackargsFuncR0ObjLast
- mov r5, r1 /* store objlast in r5 temporarily */
- /* Load the first 3 arguments into r1-r3 */
- cmp r7, #4
- ldrge r1, [r6]
- cmp r7, #8
- ldrge r2, [r6,#4]
- movlt r2, r5
- cmp r7, #12
- ldrge r3, [r6,#8]
- movlt r3, r5
- movlt r5, #0 /* If objlast got placed into a register, r5 = 0 */
- blt stackargsFuncR0ObjLast /* If objlast got placed into a register, go to stackargsFuncR0ObjLast */
- cmp r7, #16 /* Else if we have one last arg set the offset accordingly and store the arg in the array */
- ldrge r7, [r6, #12]
- strge r7, [r6, #8]
- str r5, [r6, #12] /* Put objlast in r6 + 12 */
- mov r5, #0
- movge r5, #4 /* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
- add r5, r5, #4 /* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
- stackargsFuncR0ObjLast:
- ldr r7, [r6, #268] /* Load stack size into r7 */
- add r7, r7, r5 /* Add the offset placed in r5 (could be #0 or #4) */
- cmp r7, #0 /* Check for 0 args */
- /* If there are no args for the stack, branch */
- beq nomoreargsarmFuncR0ObjLast
- /* Load the rest of the arguments onto the stack */
- /* Ensure 8-byte stack alignment */
- mov r8, sp
- sub sp, sp, r7
- add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
- sub r12, sp, #8
- sub r6, r6, r5 /* r6 = r6 - r5 (r5 can be #0 or #4) */
- bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
- sub r8, r8, r12
- mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
- stackargslooparmFuncR0ObjLast:
- ldr r5, [r6], #4
- subs r7, r7, #4
- str r5, [sp], #4
- bne stackargslooparmFuncR0ObjLast
- mov sp, r12
- nomoreargsarmFuncR0ObjLast:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
- pop {r4-r8, r10, r11, pc}
- /* ------------------------------------------------------------------------------------------- */
- .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
- #if defined(__thumb__) || defined(__thumb2__)
- .thumb
- .syntax unified
- #else
- .arm /* Use ARM instructions instead of Thumb.*/
- #endif
- .globl armFuncR0 /* Make the function globally accessible.*/
- armFuncR0:
- push {r4-r8, r10, r11, lr}
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- 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 */
- mov r0, r3 /* r0 explicitly set */
- /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
- add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
- mov r8, #0
- vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
- /* If there are no arguments to set into r0-r3 */
- /* go check if there are arguments for the stack */
- beq stackargsarmFuncR0
- /* Load the first 3 arguments into r1-r3 */
- cmp r7, #4
- ldrge r1, [r6]
- cmp r7, #8
- ldrge r2, [r6, #4]
- cmp r7, #12
- ldrge r3, [r6, #8]
- cmp r7, #16
- movge r11, #4 /* If there is still one arg to be placed, set the offset in r11 to #4 */
- stackargsarmFuncR0:
- ldr r5, [r6, #268] /* Load stack size into r5 */
- add r5, r11 /* Add the offset placed in r11 (could be #0 or #4) */
- movs r7, r5 /* Load stack size into r7, checking for 0 args */
- /* If there are no args for the stack, branch */
- beq nomoreargsarmFuncR0
- /* Load the rest of the arguments onto the stack */
- /* Ensure 8-byte stack alignment */
- mov r8, sp
- sub sp, sp, r7
- add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
- sub r12, sp, #8
- sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4) */
- bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
- sub r8, r8, r12
- mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
- stackargslooparmFuncR0:
- ldr r5, [r6], #4
- subs r7, r7, #4
- str r5, [sp], #4
- bne stackargslooparmFuncR0
- mov sp, r12
- nomoreargsarmFuncR0:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
- pop {r4-r8, r10, r11, pc}
- /* ------------------------------------------------------------------------------------------- */
- .align 2 /* Align the function code to a 4-byte (2^n) word boundary. */
- #if defined(__thumb__) || defined(__thumb2__)
- .thumb
- .syntax unified
- #else
- .arm /* Use ARM instructions instead of Thumb.*/
- #endif
- .globl armFuncR0R1 /* Make the function globally accessible.*/
- armFuncR0R1:
- push {r4-r8, r10, r11, lr}
- mov r6, r0 /* arg table */
- movs r7, r1 /* arg size (also set the condition code flags so that we detect if there are no arguments) */
- mov r4, r2 /* function address */
- 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 */
- mov r0, r3 /* r0 explicitly set */
- ldr r1, [sp, #32] /* r1 explicitly set too */
- /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
- add r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
- mov r8, #0
- vldmia.64 r10, {d0-d7} /* Load contents starting at r10 into registers d0-d7 */
- /* If there are no arguments to set into r2-r3 */
- /* go check if there are arguments for the stack */
- beq stackargsarmFuncR0R1
- /* Load the first 2 arguments into r2-r3 */
- cmp r7, #4
- ldrge r2, [r6]
- cmp r7, #8
- ldrge r3, [r6, #4]
- cmp r7, #12
- movge r11, #4 /* If there is a third arg to be placed, set the offset in r11 to #4 */
- cmp r7, #16
- movge r11, #8 /* If there is a fourth arg to be placed, set the offset in r11 to #8 */
- ldrlt r7, [r6, #8] /* Else copy the third arg to the correct place in the array */
- strlt r7, [r6, #12]
- stackargsarmFuncR0R1:
- ldr r5, [r6, #268] /* Load stack size into r5 */
- add r5, r11 /* Add the offset placed in r11 (could be #0 or #4 or #8) */
- movs r7, r5 /* Load stack size into r7, checking for 0 args */
- /* If there are no args for the stack, branch */
- beq nomoreargsarmFuncR0R1
- /* Load the rest of the arguments onto the stack */
- /* Ensure 8-byte stack alignment */
- mov r8, sp
- sub sp, sp, r7
- add r6, r6, #16 /* Set r6 to point to the first arg to be placed on the stack */
- sub r12, sp, #8
- sub r6, r6, r11 /* r6 = r6 - r11 (r11 can be #0 or #4 or #8) */
- bic r12, r12, #7 /* thumb mode couldn't support "bic sp, sp, #7" instruction */
- sub r8, r8, r12
- mov sp, r12 /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
- stackargslooparmFuncR0R1:
- ldr r5, [r6], #4
- subs r7, r7, #4
- str r5, [sp], #4
- bne stackargslooparmFuncR0R1
- mov sp, r12
- nomoreargsarmFuncR0R1:
- #if defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
- mov lr, pc /* older ARM didn't support blx */
- mov pc, r4
- #else
- blx r4
- #endif
- add sp, sp, r8
- vstmia.64 r10, {d0-d7} /* Copy contents of registers d0-d10 to the address stored in r10 */
- pop {r4-r8, r10, r11, pc}
- #endif /* hard float abi */
- #endif /* arm */
- #if defined(__linux__) && defined(__ELF__)
- /* ref: http://hardened.gentoo.org/gnu-stack.xml
- ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart */
- .section .note.GNU-stack,"",%progbits
- #endif
- #endif /* !AS_MAX_PORTABILITY */
|