comparison dyncall/dyncall_callvm_arm32_arm_armhf.c @ 0:3e629dc19168

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:24:28 +0100
parents
children f01895437921
comparison
equal deleted inserted replaced
-1:000000000000 0:3e629dc19168
1 /*
2
3 Package: dyncall
4 Library: dyncall
5 File: dyncall/dyncall_callvm_arm32_arm_armhf.c
6 Description: ARM 'armhf' ABI implementation
7 License:
8
9 Copyright (c) 2007-2015 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 #include "dyncall_callvm_arm32_arm_armhf.h"
28 #include "dyncall_alloc.h"
29
30
31 static DCCallVM* dc_callvm_new_arm32_armhf(DCCallVM_vt* vt, DCsize size)
32 {
33 /* Store at least 16 bytes (4 words) for internal spill area. Assembly code depends on it. */
34 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)dcAllocMem(sizeof(DCCallVM_arm32_armhf)+size+16);
35 dc_callvm_base_init(&p->mInterface, vt);
36 dcVecInit(&p->mVecHead, size);
37 p->i = 0;
38 p->s = 0;
39 p->d = 0;
40 return (DCCallVM*)p;
41 }
42
43 static void mode(DCCallVM* in_self,DCint mode);
44
45 static void deinit(DCCallVM* in_self)
46 {
47 dcFreeMem(in_self);
48 }
49
50
51 static void reset(DCCallVM* in_p)
52 {
53 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p;
54 p->i = 0;
55 p->s = 0;
56 p->d = 0;
57 dcVecResize(&p->mVecHead, 16);
58 }
59
60 static void a_int(DCCallVM* in_self, DCint x)
61 {
62 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_self;
63 if (p->i < 16) {
64 * (DCint*) dcVecAt(&p->mVecHead, p->i) = x;
65 p->i += 4;
66 } else {
67 dcVecAppend(&p->mVecHead, &x, sizeof(DCint));
68 }
69 }
70
71 static void a_bool (DCCallVM* in_self, DCbool x) { a_int(in_self, (DCint)x); }
72 static void a_char (DCCallVM* in_self, DCchar x) { a_int(in_self, x); }
73 static void a_short (DCCallVM* in_self, DCshort x) { a_int(in_self, x); }
74 static void a_long (DCCallVM* in_self, DClong x) { a_int(in_self, x); }
75 static void a_longlong(DCCallVM* in_self, DClonglong x)
76 {
77 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_self;
78
79 p->i = (p->i+4) & -8;
80 if (p->i < 16) {
81 * (DClonglong*) dcVecAt(&p->mVecHead, p->i) = x;
82 p->i += 8;
83 } else {
84 /* 64 bit values need to be aligned on 8 byte boundaries */
85 dcVecSkip(&p->mVecHead, dcVecSize(&p->mVecHead) & 4);
86 dcVecAppend(&p->mVecHead, &x, sizeof(DClonglong));
87 }
88 }
89 static void a_pointer(DCCallVM* in_p, DCpointer x) { a_int(in_p, (DCint) x ); }
90
91 static void a_float(DCCallVM* in_p, DCfloat x)
92 {
93 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p;
94 if (p->s < 16) {
95 p->S[p->s++] = x;
96 if (p->d < p->s) {
97 p->d = (p->s+1) & ~(1U);
98 } else {
99 p->s = p->d;
100 }
101 } else {
102 dcVecAppend(&p->mVecHead, &x, sizeof(DCfloat));
103 }
104 }
105
106 static void a_double(DCCallVM* in_p, DCdouble x)
107 {
108 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p;
109 if (p->d < 16) {
110 * (double*) &p->S[p->d] = x;
111 p->d += 2;
112 if (!(p->s & 1)) {
113 /* if s is even it always equals d.
114 otherwise, s points to an odd float register.
115 */
116 p->s = p->d;
117 }
118 } else {
119 p->s = 16;
120 union {
121 DCdouble d;
122 DCchar b[8];
123 } v; // ,w;
124 v.d = x;
125 #if 0
126 w.b[0] = v.b[7];
127 w.b[1] = v.b[6];
128 w.b[2] = v.b[5];
129 w.b[3] = v.b[4];
130 w.b[4] = v.b[3];
131 w.b[5] = v.b[2];
132 w.b[6] = v.b[1];
133 w.b[7] = v.b[0];
134 #endif
135 /* 64 bit values need to be aligned on 8 byte boundaries */
136 dcVecSkip(&p->mVecHead, dcVecSize(&p->mVecHead) & 4);
137 dcVecAppend(&p->mVecHead, &v.b[0], sizeof(DCdouble));
138 }
139 }
140
141 void call(DCCallVM* in_p, DCpointer target)
142 {
143 DCCallVM_arm32_armhf* p = (DCCallVM_arm32_armhf*)in_p;
144 dcCall_arm32_armhf(target, dcVecData(&p->mVecHead), dcVecSize(&p->mVecHead), &p->S[0]);
145 }
146
147 DCCallVM_vt vt_armhf =
148 {
149 &deinit
150 , &reset
151 , &mode
152 , &a_bool
153 , &a_char
154 , &a_short
155 , &a_int
156 , &a_long
157 , &a_longlong
158 , &a_float
159 , &a_double
160 , &a_pointer
161 , NULL /* argStruct */
162 , (DCvoidvmfunc*) &call
163 , (DCboolvmfunc*) &call
164 , (DCcharvmfunc*) &call
165 , (DCshortvmfunc*) &call
166 , (DCintvmfunc*) &call
167 , (DClongvmfunc*) &call
168 , (DClonglongvmfunc*) &call
169 , (DCfloatvmfunc*) &call
170 , (DCdoublevmfunc*) &call
171 , (DCpointervmfunc*) &call
172 , NULL /* callStruct */
173 };
174
175 DCCallVM* dcNewCallVM(DCsize size)
176 {
177 #if defined(DC__ABI_ARM_EABI)
178 return dc_callvm_new_arm32_arm(&eabi, size);
179 #elif defined(DC__ABI_ARM_HF)
180 return dc_callvm_new_arm32_armhf(&vt_armhf, size);
181 #elif defined(DC__ABI_ARM_OABI)
182 return dc_callvm_new_arm32_arm(&oabi, size);
183 #else
184 #error unknown ARM abi
185 #endif
186 }
187
188 static void mode(DCCallVM* in_self,DCint mode)
189 {
190 DCCallVM_arm32_armhf* self = (DCCallVM_arm32_armhf*) in_self;
191 DCCallVM_vt* vt;
192 switch(mode) {
193 case DC_CALL_C_DEFAULT:
194 case DC_CALL_C_ELLIPSIS:
195 case DC_CALL_C_ELLIPSIS_VARARGS:
196 case DC_CALL_C_ARM_ARMHF:
197 vt = &vt_armhf;
198 break;
199 default:
200 in_self->mError = DC_ERROR_UNSUPPORTED_MODE;
201 return;
202 }
203 self->mInterface.mVTpointer = vt;
204 }
205