0
|
1 /*
|
|
2
|
|
3 Package: dyncall
|
|
4 Library: dyncall
|
|
5 File: dyncall/dyncall_call_arm32_thumb_gas.s
|
|
6 Description: ARM Thumb call kernel implementation for GNU assembler.
|
|
7 License:
|
|
8
|
|
9 Copyright (c) 2007-2011 Daniel Adler <dadler@uni-goettingen.de>,
|
|
10 Tassilo Philipp <tphilipp@potion-studios.com>
|
|
11
|
|
12 Permission to use, copy, modify, and distribute this software for any
|
|
13 purpose with or without fee is hereby granted, provided that the above
|
|
14 copyright notice and this permission notice appear in all copies.
|
|
15
|
|
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
23
|
|
24 */
|
|
25
|
|
26
|
|
27 .text
|
|
28 #if !defined(__thumb2__)
|
|
29 .code 16 /* THUMB mode */
|
|
30 #endif
|
|
31
|
|
32 .globl dcCall_arm32_thumb
|
|
33
|
|
34 /* Main dyncall call. */
|
|
35 .thumb_func
|
|
36 dcCall_arm32_thumb:
|
|
37
|
|
38 /* Prolog. This function never needs to spill inside its prolog, so just store the permanent registers. */
|
|
39 push {%r4-%r7, %r14} /* Frame ptr, permanent registers, link register -> save area on stack. */
|
|
40 mov %r7, %r13 /* Set frame ptr. */
|
|
41
|
|
42 /* Call. */
|
|
43 mov %r4, %r0 /* Move 'fptr' to r4 (1st argument is passed in r0). */
|
|
44
|
|
45 /* Disable 'thumb' address forcing... */
|
|
46
|
|
47 /* mov %r0, #1 */ /* Assure that LSB is set to 1 (THUMB call). - Not Required and not useful for interworking calls */
|
|
48 /* orr %r4, %r0 */
|
|
49
|
|
50 mov %r5, %r1 /* Move 'args' to r5 (2nd argument is passed in r1). */
|
|
51 mov %r6, %r2 /* Move 'size' to r6 (3rd argument is passed in r2). */
|
|
52
|
|
53 cmp %r6, #16 /* Jump to call if no more than 4 arguments. */
|
|
54 ble call
|
|
55
|
|
56 sub %r6, #16 /* Size of remaining arguments. */
|
|
57 mov %r0, %r13 /* Set stack pointer to top of stack. */
|
|
58 sub %r0, %r0, %r6
|
|
59 lsr %r0, #3 /* Align stack on 8 byte boundaries. */
|
|
60 lsl %r0, #3
|
|
61 mov %r13, %r0
|
|
62
|
|
63 add %r1, #16 /* Let r1 point to remaining arguments. */
|
|
64 mov %r2, #0 /* Init byte counter to 0. */
|
|
65 .thumb_func
|
|
66 pushArgs:
|
|
67 ldrb %r3, [%r1, %r2] /* Load a byte into r3. */
|
|
68 strb %r3, [%r0, %r2] /* Push byte onto stack. */
|
|
69 add %r2, %r2, #1 /* Increment byte counter. */
|
|
70 cmp %r2, %r6
|
|
71 bne pushArgs
|
|
72 .thumb_func
|
|
73 call:
|
|
74 ldmia %r5!, {%r0-%r3} /* Load first 4 arguments for new call into r0-r3. */
|
|
75
|
|
76 /* 'blx %r4' workaround for ARMv4t in THUMB: */
|
|
77 mov %r6, %r15 /* Load PC+2 instructions from here */
|
|
78 add %r6, #5 /* Increment by 2 instructions (Address of 'Epilog') and set bit 0 (THUMB) */
|
|
79 mov %r14, %r6 /* Store in link register. */
|
|
80 bx %r4 /* Branch and force THUMB-mode return (LR bit 0 set). */
|
|
81
|
|
82 /* Epilog. */
|
|
83 mov %r13, %r7 /* Reset stack ptr. */
|
|
84 pop {%r4-%r7, %r15} /* Restore permanent registers and program counter. (Force a stay in THUMB in ARMv4, whether ARMv5 can return in ARM or THUMB depending on the bit 0. */
|
|
85
|
|
86
|
|
87
|
|
88 /* Internally used to avoid compiler overwriting r0 and r1 in call stub */
|
|
89 .globl dcCall_arm32_thumb_word
|
|
90
|
|
91 .thumb_func
|
|
92 dcCall_arm32_thumb_word:
|
|
93 b dcCall_arm32_thumb
|
|
94
|
|
95
|
|
96 .globl dcCall_arm32_thumb_dword
|
|
97
|
|
98 .thumb_func
|
|
99 dcCall_arm32_thumb_dword:
|
|
100 b dcCall_arm32_thumb
|
|
101
|