comparison dyncall/dyncall_callvm_arm64.c @ 0:3e629dc19168

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:24:28 +0100
parents
children 67961454902b
comparison
equal deleted inserted replaced
-1:000000000000 0:3e629dc19168
1 /*
2
3 Package: dyncall
4 Library: dyncall
5 File: dyncall/dyncall_callvm_arm64.c
6 Description: ARM 64-bit ABI implementation
7 License:
8
9 Copyright (c) 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_arm64.h"
28 #include "dyncall_alloc.h"
29
30 static DCCallVM* dc_callvm_new_arm64(DCCallVM_vt* vt, DCsize size)
31 {
32 DCCallVM_arm64* p = (DCCallVM_arm64*) dcAllocMem(size);
33
34 dc_callvm_base_init(&p->mInterface, vt);
35
36 dcVecInit(&p->mVecHead, size);
37
38 p->i = 0;
39 p->f = 0;
40
41 return (DCCallVM*)p;
42 }
43
44 static void reset(DCCallVM* in_p)
45 {
46 DCCallVM_arm64* p = (DCCallVM_arm64*)in_p;
47 p->i = 0;
48 p->f = 0;
49 dcVecReset(&p->mVecHead);
50 }
51
52
53 static void mode(DCCallVM* in_self,DCint mode);
54
55 static void deinit(DCCallVM* in_self)
56 {
57 dcFreeMem(in_self);
58 }
59
60
61
62 static void a_i64(DCCallVM* in_self, DClonglong x)
63 {
64 DCCallVM_arm64* p = (DCCallVM_arm64*)in_self;
65 if (p->i < 8) {
66 p->I[p->i] = x;
67 p->i++;
68 } else {
69 dcVecAppend(&p->mVecHead, &x, sizeof(DClonglong));
70 }
71 }
72
73 static void a_bool (DCCallVM* self, DCbool x) { a_i64(self, (DClonglong)x); }
74 static void a_char (DCCallVM* self, DCchar x) { a_i64(self, x); }
75 static void a_short (DCCallVM* self, DCshort x) { a_i64(self, x); }
76 static void a_int (DCCallVM* self, DCint x) { a_i64(self, x); }
77 static void a_long (DCCallVM* self, DClong x) { a_i64(self, x); }
78 static void a_pointer (DCCallVM* self, DCpointer x) { a_i64(self, (DClonglong) x ); }
79
80 static void a_float(DCCallVM* in_p, DCfloat x)
81 {
82 DCCallVM_arm64* p = (DCCallVM_arm64*)in_p;
83
84 if (p->f < 8) {
85 p->u.S[ p->f << 1 ] = x;
86 p->f++;
87 } else {
88 dcVecAppend(&p->mVecHead, &x, sizeof(DCfloat));
89 dcVecSkip(&p->mVecHead, 4); /* align to 8-bytes */
90 }
91 }
92
93 static void a_double(DCCallVM* in_p, DCdouble x)
94 {
95 DCCallVM_arm64* p = (DCCallVM_arm64*)in_p;
96 if (p->f < 8) {
97 p->u.D[ p->f ] = x;
98 p->f++;
99 } else {
100 dcVecAppend(&p->mVecHead, &x, sizeof(DCdouble));
101 }
102 }
103
104 void call(DCCallVM* in_p, DCpointer target)
105 {
106 DCCallVM_arm64* p = (DCCallVM_arm64*)in_p;
107
108 /*
109 ** copy 'size' argument is given in number of 16-byte 'pair' blocks.
110 */
111
112 dcCall_arm64(target, dcVecData(&p->mVecHead), ( dcVecSize(&p->mVecHead) + 15 ) & -16, &p->u.S[0]);
113 }
114
115 DCCallVM_vt vt_arm64 =
116 {
117 &deinit
118 , &reset
119 , &mode
120 , &a_bool
121 , &a_char
122 , &a_short
123 , &a_int
124 , &a_long
125 , &a_i64
126 , &a_float
127 , &a_double
128 , &a_pointer
129 , NULL /* argStruct */
130 , (DCvoidvmfunc*) &call
131 , (DCboolvmfunc*) &call
132 , (DCcharvmfunc*) &call
133 , (DCshortvmfunc*) &call
134 , (DCintvmfunc*) &call
135 , (DClongvmfunc*) &call
136 , (DClonglongvmfunc*) &call
137 , (DCfloatvmfunc*) &call
138 , (DCdoublevmfunc*) &call
139 , (DCpointervmfunc*) &call
140 , NULL /* callStruct */
141 };
142
143 DCCallVM* dcNewCallVM(DCsize size)
144 {
145 return dc_callvm_new_arm64(&vt_arm64, size);
146 }
147
148 static void mode(DCCallVM* in_self,DCint mode)
149 {
150 DCCallVM_arm64* self = (DCCallVM_arm64*) in_self;
151 DCCallVM_vt* vt;
152 switch(mode) {
153 case DC_CALL_C_DEFAULT:
154 case DC_CALL_C_ELLIPSIS:
155 case DC_CALL_C_ELLIPSIS_VARARGS:
156 case DC_CALL_C_ARM64:
157 vt = &vt_arm64;
158 break;
159 default:
160 in_self->mError = DC_ERROR_UNSUPPORTED_MODE;
161 return;
162 }
163 self->mInterface.mVTpointer = vt;
164 }
165