0
|
1 /*
|
|
2
|
|
3 Package: dyncall
|
|
4 Library: dyncallback
|
|
5 File: dyncallback/dyncall_callback_ppc64.S
|
|
6 Description: Callback Thunk - Implementation for PowerPC 64-bit
|
|
7 License:
|
|
8
|
|
9 Copyright (c) 2014-2015 Masanori Mitsugi <mitsugi@linux.vnet.ibm.com>
|
|
10
|
|
11 Permission to use, copy, modify, and distribute this software for any
|
|
12 purpose with or without fee is hereby granted, provided that the above
|
|
13 copyright notice and this permission notice appear in all copies.
|
|
14
|
|
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
22
|
|
23 */
|
|
24
|
7
|
25 #include "../portasm/portasm-ppc64.S"
|
0
|
26
|
7
|
27 .text
|
|
28 .align 2
|
0
|
29
|
|
30 /* struct DCCallback */
|
7
|
31
|
|
32 #if DC__ABI_PPC64_ELF_V != 2
|
|
33 DCB_THUNK = 0 /* v1 */
|
|
34 DCB_HANDLER = 64
|
|
35 DCB_STACKCLEAN = 72
|
|
36 DCB_USERDATA = 80
|
|
37 #else
|
|
38 DCB_THUNK = 0 /* v2 */
|
0
|
39 DCB_HANDLER = 48
|
|
40 DCB_STACKCLEAN = 56
|
|
41 DCB_USERDATA = 64
|
|
42 #endif
|
|
43
|
|
44 /* struct DCArgs */
|
7
|
45
|
|
46 ARGS_IREGS = 0
|
|
47 ARGS_FREGS = ARGS_IREGS + 8*8
|
|
48 ARGS_SP = ARGS_FREGS + 8*13
|
|
49 ARGS_ICNT = ARGS_SP + 8
|
|
50 ARGS_FCNT = ARGS_ICNT + 4
|
|
51 ARGS_SIZE = ARGS_FCNT + 4
|
0
|
52
|
|
53 /* struct DCValue */
|
7
|
54
|
|
55 RESULT_SIZE = 8
|
|
56
|
|
57 /* Stack Offsets */
|
0
|
58
|
7
|
59 SP_PREV = 0
|
|
60 SP_CR = SP_PREV + 8
|
|
61 SP_LR = SP_CR + 8
|
|
62 #if DC__ABI_PPC64_ELF_V != 2
|
|
63 SP_TOC = 40
|
|
64 SP_PAR = 48
|
|
65 PAR_SZ = 64
|
|
66 #else
|
|
67 SP_TOC = 24
|
|
68 SP_PAR = 32
|
|
69 PAR_SZ = 0
|
|
70 #endif
|
|
71 SP_ARGS = SP_PAR + PAR_SZ
|
|
72 SP_IREGS = SP_ARGS + ARGS_IREGS
|
|
73 SP_FREGS = SP_ARGS + ARGS_FREGS
|
|
74 SP_SP = SP_ARGS + ARGS_SP
|
|
75 SP_ICNT = SP_ARGS + ARGS_ICNT
|
|
76 SP_FCNT = SP_ARGS + ARGS_FCNT
|
|
77 SP_RESULT = SP_ARGS + ARGS_SIZE
|
|
78 SP_LOCAL = SP_RESULT + RESULT_SIZE /* additional locals (reg 30/31) */
|
|
79 SP_SIZE = SP_LOCAL + 2*8
|
0
|
80
|
7
|
81 #define ALIGN(M,X) ( M+(X-1) & (-X) )
|
|
82
|
|
83 FRAMESIZE = ALIGN(SP_SIZE,16)
|
|
84
|
|
85 GLOBAL_C(dcCallbackThunkEntry)
|
|
86 ENTRY_C(dcCallbackThunkEntry)
|
|
87
|
|
88 /* --------------------------------------------------------------------------
|
|
89
|
|
90 Input:
|
|
91 r1 Stack Pointer
|
|
92 r3-r10 Integer Arguments
|
|
93 f1-f8 Floating-point Arguments
|
|
94 r11 Thunk Pointer
|
|
95
|
0
|
96 */
|
|
97
|
|
98 mflr r0
|
7
|
99 std r0, SP_LR(r1) /* store return address */
|
|
100 std r31, -8(r1) /* store preserved registers (r31) */
|
|
101 addi r12, r1, SP_PAR /* temporary r12 = parameter area on callers stack frame */
|
|
102 stdu r1, -FRAMESIZE(r1) /* save callers stack pointer and make new stack frame. */
|
0
|
103
|
7
|
104 std r3, SP_IREGS + 0*8(r1) /* spill 8 integer parameter registers */
|
|
105 std r4, SP_IREGS + 1*8(r1)
|
|
106 std r5, SP_IREGS + 2*8(r1)
|
|
107 std r6, SP_IREGS + 3*8(r1)
|
|
108 std r7, SP_IREGS + 4*8(r1)
|
|
109 std r8, SP_IREGS + 5*8(r1)
|
|
110 std r9, SP_IREGS + 6*8(r1)
|
|
111 std r10,SP_IREGS + 7*8(r1)
|
|
112 stfd f1, SP_FREGS + 0*8(r1) /* spill 13 float parameter registers */
|
|
113 stfd f2, SP_FREGS + 1*8(r1)
|
|
114 stfd f3, SP_FREGS + 2*8(r1)
|
|
115 stfd f4, SP_FREGS + 3*8(r1)
|
|
116 stfd f5, SP_FREGS + 4*8(r1)
|
|
117 stfd f6, SP_FREGS + 5*8(r1)
|
|
118 stfd f7, SP_FREGS + 6*8(r1)
|
|
119 stfd f8, SP_FREGS + 7*8(r1)
|
|
120 stfd f9, SP_FREGS + 8*8(r1)
|
|
121 stfd f10,SP_FREGS + 9*8(r1)
|
|
122 stfd f11,SP_FREGS +10*8(r1)
|
|
123 stfd f12,SP_FREGS +11*8(r1)
|
|
124 stfd f13,SP_FREGS +12*8(r1)
|
0
|
125 /* initialize struct DCCallback */
|
7
|
126 std r12,SP_SP(r1) /* init stack pointer */
|
0
|
127 xor r0, r0, r0 /* init register counters */
|
7
|
128 std r0, SP_ICNT(r1)
|
|
129 std r0, SP_FCNT(r1)
|
|
130 std r0, SP_RESULT(r1) /* init result object */
|
0
|
131 /* invoke callback handler */
|
7
|
132 mr r3, r11 /* arg 1: DCCallback* pcb (r11 is thunk pointer) */
|
|
133 addi r4, r1, SP_ARGS /* arg 2: DCArgs* args */
|
|
134 addi r5, r1, SP_RESULT /* arg 3: DCValue* result */
|
0
|
135 ld r6, DCB_USERDATA(r11) /* arg 4: void* userdata */
|
|
136
|
|
137 /* branch-and-link to DCCallback.handler */
|
|
138 ld r12, DCB_HANDLER(r11)
|
7
|
139 std r2, SP_TOC(r1)
|
0
|
140 #if DC__ABI_PPC64_ELF_V != 2
|
|
141 ld r2, 8(r12)
|
|
142 ld r0, 0(r12)
|
|
143 mtctr r0
|
|
144 #else
|
|
145 mtctr r12
|
|
146 #endif
|
|
147 bctrl
|
|
148
|
7
|
149 /* check result type */
|
0
|
150 cmpi cr0, r3, 'f
|
|
151 beq .f32
|
|
152 cmpi cr0, r3, 'd
|
|
153 beq .f64
|
7
|
154 .i64:
|
|
155 ld r3, SP_RESULT(r1)
|
0
|
156 b .end
|
|
157 .end:
|
|
158
|
7
|
159 ld r2, SP_TOC(r1)
|
|
160 ld r1, SP_PREV(r1) /* restore stack pointer */
|
|
161 ld r31, -8(r1) /* restore preserved registers */
|
|
162 ld r0, SP_LR(r1) /* load link register with return address */
|
0
|
163 mtlr r0
|
7
|
164 blr /* branch back to link register */
|
|
165 .f32:
|
|
166 lfs f1, SP_RESULT(r1)
|
|
167 b .end
|
|
168 .f64:
|
|
169 lfd f1, SP_RESULT(r1)
|
|
170 b .end
|