comparison dyncall/dyncall_callvm_mips_eabi.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_mips_eabi.c
6 Description: Implementation of Call VM for mips "eabi" abi.
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
28 #include "dyncall_callvm_mips_eabi.h"
29 #include "dyncall_alloc.h"
30
31 static void dc_callvm_reset_mips_eabi(DCCallVM* in_self)
32 {
33 DCCallVM_mips_eabi* self = (DCCallVM_mips_eabi*)in_self;
34 dcVecReset(&self->mVecHead);
35 self->mIntRegs = 0;
36 self->mSingleRegs = 0;
37 }
38
39 static DCCallVM* dc_callvm_new_mips_eabi(DCCallVM_vt* vt, DCsize size)
40 {
41 /* Store at least 16 bytes (4 words) for internal spill area. Assembly code depends on it. */
42 DCCallVM_mips_eabi* self = (DCCallVM_mips_eabi*)dcAllocMem(sizeof(DCCallVM_mips_eabi)+size+16);
43 dc_callvm_base_init(&self->mInterface, vt);
44 dcVecInit(&self->mVecHead, size);
45 dc_callvm_reset_mips_eabi( (DCCallVM*) self );
46 return (DCCallVM*)self;
47 }
48
49
50 static void dc_callvm_free_mips_eabi(DCCallVM* in_self)
51 {
52 dcFreeMem(in_self);
53 }
54
55 static void dc_callvm_mode_mips_eabi(DCCallVM* in_self,DCint mode)
56 {
57 switch(mode) {
58 case DC_CALL_C_DEFAULT:
59 case DC_CALL_C_ELLIPSIS:
60 case DC_CALL_C_MIPS32_EABI:
61 break;
62 default:
63 in_self->mError = DC_ERROR_UNSUPPORTED_MODE; return;
64 }
65 }
66
67 /* arg int -- fillup integer register file OR push on stack */
68
69 static void dc_callvm_argInt_mips_eabi(DCCallVM* in_self, DCint i)
70 {
71 DCCallVM_mips_eabi* self = (DCCallVM_mips_eabi*)in_self;
72 /* fillup integer register file */
73 if (self->mIntRegs < 8)
74 self->mRegData.mIntData[self->mIntRegs++] = i;
75 else
76 dcVecAppend(&self->mVecHead, &i, sizeof(DCint));
77 }
78
79 static void dc_callvm_argPointer_mips_eabi(DCCallVM* in_self, DCpointer x)
80 {
81 dc_callvm_argInt_mips_eabi(in_self, * (DCint*) &x );
82 }
83
84 static void dc_callvm_argBool_mips_eabi(DCCallVM* in_self, DCbool x)
85 {
86 dc_callvm_argInt_mips_eabi(in_self, (DCint)x);
87 }
88
89 static void dc_callvm_argChar_mips_eabi(DCCallVM* in_self, DCchar x)
90 {
91 dc_callvm_argInt_mips_eabi(in_self, (DCint)x);
92 }
93
94 static void dc_callvm_argShort_mips_eabi(DCCallVM* in_self, DCshort x)
95 {
96 dc_callvm_argInt_mips_eabi(in_self, (DCint)x);
97 }
98
99 static void dc_callvm_argLong_mips_eabi(DCCallVM* in_self, DClong x)
100 {
101 dc_callvm_argInt_mips_eabi(in_self, (DCint)x);
102 }
103
104 static void dc_callvm_argLongLong_mips_eabi(DCCallVM* in_self, DClonglong Lv)
105 {
106 DCCallVM_mips_eabi* self = (DCCallVM_mips_eabi*)in_self;
107
108 if (self->mIntRegs < 7) {
109 DCint* p = (DCint*) &Lv;
110 /* skip odd register (align 64 bit) */
111 self->mIntRegs += self->mIntRegs & 1;
112 self->mRegData.mIntData[self->mIntRegs++] = p[0];
113 self->mRegData.mIntData[self->mIntRegs++] = p[1];
114 } else {
115 self->mIntRegs = 8;
116 /* 64 bit values need to be aligned on 8 byte boundaries */
117 dcVecSkip(&self->mVecHead, dcVecSize(&self->mVecHead) & 4);
118 dcVecAppend(&self->mVecHead, &Lv, sizeof(DClonglong));
119 }
120 }
121
122 static void dc_callvm_argFloat_mips_eabi(DCCallVM* in_self, DCfloat x)
123 {
124 DCCallVM_mips_eabi* self = (DCCallVM_mips_eabi*)in_self;
125 if (self->mSingleRegs < 8) {
126 self->mRegData.mSingleData[self->mSingleRegs++] = x;
127 } else {
128 dcVecAppend(&self->mVecHead, &x, sizeof(DCfloat) );
129 }
130 }
131
132 static void dc_callvm_argDouble_mips_eabi(DCCallVM* in_self, DCdouble x)
133 {
134 DClonglong* p = (DClonglong*) &x;
135 dc_callvm_argLongLong_mips_eabi(in_self, *p);
136 }
137
138 /* Call. */
139 void dc_callvm_call_mips_eabi(DCCallVM* in_self, DCpointer target)
140 {
141 DCCallVM_mips_eabi* self = (DCCallVM_mips_eabi*)in_self;
142 dcCall_mips_eabi(target, &self->mRegData, dcVecSize(&self->mVecHead), dcVecData(&self->mVecHead));
143 }
144
145 DCCallVM_vt gVT_mips_eabi =
146 {
147 &dc_callvm_free_mips_eabi
148 , &dc_callvm_reset_mips_eabi
149 , &dc_callvm_mode_mips_eabi
150 , &dc_callvm_argBool_mips_eabi
151 , &dc_callvm_argChar_mips_eabi
152 , &dc_callvm_argShort_mips_eabi
153 , &dc_callvm_argInt_mips_eabi
154 , &dc_callvm_argLong_mips_eabi
155 , &dc_callvm_argLongLong_mips_eabi
156 , &dc_callvm_argFloat_mips_eabi
157 , &dc_callvm_argDouble_mips_eabi
158 , &dc_callvm_argPointer_mips_eabi
159 , NULL /* argStruct */
160 , (DCvoidvmfunc*) &dc_callvm_call_mips_eabi
161 , (DCboolvmfunc*) &dc_callvm_call_mips_eabi
162 , (DCcharvmfunc*) &dc_callvm_call_mips_eabi
163 , (DCshortvmfunc*) &dc_callvm_call_mips_eabi
164 , (DCintvmfunc*) &dc_callvm_call_mips_eabi
165 , (DClongvmfunc*) &dc_callvm_call_mips_eabi
166 , (DClonglongvmfunc*) &dc_callvm_call_mips_eabi
167 , (DCfloatvmfunc*) &dc_callvm_call_mips_eabi
168 , (DCdoublevmfunc*) &dc_callvm_call_mips_eabi
169 , (DCpointervmfunc*) &dc_callvm_call_mips_eabi
170 , NULL /* callStruct */
171 };
172
173 DCCallVM* dcNewCallVM_mips_eabi(DCsize size)
174 {
175 return dc_callvm_new_mips_eabi(&gVT_mips_eabi, size);
176 }
177
178 DCCallVM* dcNewCallVM(DCsize size)
179 {
180 return dcNewCallVM_mips_eabi(size);
181 }
182