summaryrefslogtreecommitdiff
path: root/src/common/x64/abi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/x64/abi.cpp')
-rw-r--r--src/common/x64/abi.cpp350
1 files changed, 0 insertions, 350 deletions
diff --git a/src/common/x64/abi.cpp b/src/common/x64/abi.cpp
deleted file mode 100644
index 504b9c940..000000000
--- a/src/common/x64/abi.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
1// Copyright (C) 2003 Dolphin Project.
2
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, version 2.0 or later versions.
6
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10// GNU General Public License 2.0 for more details.
11
12// A copy of the GPL 2.0 should have been included with the program.
13// If not, see http://www.gnu.org/licenses/
14
15// Official SVN repository and contact information can be found at
16// http://code.google.com/p/dolphin-emu/
17
18#include "abi.h"
19#include "emitter.h"
20
21using namespace Gen;
22
23// Shared code between Win64 and Unix64
24
25void XEmitter::ABI_CalculateFrameSize(BitSet32 mask, size_t rsp_alignment, size_t needed_frame_size,
26 size_t* shadowp, size_t* subtractionp, size_t* xmm_offsetp) {
27 size_t shadow = 0;
28#if defined(_WIN32)
29 shadow = 0x20;
30#endif
31
32 int count = (mask & ABI_ALL_GPRS).Count();
33 rsp_alignment -= count * 8;
34 size_t subtraction = 0;
35 int fpr_count = (mask & ABI_ALL_FPRS).Count();
36 if (fpr_count) {
37 // If we have any XMMs to save, we must align the stack here.
38 subtraction = rsp_alignment & 0xf;
39 }
40 subtraction += 16 * fpr_count;
41 size_t xmm_base_subtraction = subtraction;
42 subtraction += needed_frame_size;
43 subtraction += shadow;
44 // Final alignment.
45 rsp_alignment -= subtraction;
46 subtraction += rsp_alignment & 0xf;
47
48 *shadowp = shadow;
49 *subtractionp = subtraction;
50 *xmm_offsetp = subtraction - xmm_base_subtraction;
51}
52
53size_t XEmitter::ABI_PushRegistersAndAdjustStack(BitSet32 mask, size_t rsp_alignment,
54 size_t needed_frame_size) {
55 size_t shadow, subtraction, xmm_offset;
56 ABI_CalculateFrameSize(mask, rsp_alignment, needed_frame_size, &shadow, &subtraction,
57 &xmm_offset);
58
59 for (int r : mask& ABI_ALL_GPRS)
60 PUSH((X64Reg)r);
61
62 if (subtraction)
63 SUB(64, R(RSP), subtraction >= 0x80 ? Imm32((u32)subtraction) : Imm8((u8)subtraction));
64
65 for (int x : mask& ABI_ALL_FPRS) {
66 MOVAPD(MDisp(RSP, (int)xmm_offset), (X64Reg)(x - 16));
67 xmm_offset += 16;
68 }
69
70 return shadow;
71}
72
73void XEmitter::ABI_PopRegistersAndAdjustStack(BitSet32 mask, size_t rsp_alignment,
74 size_t needed_frame_size) {
75 size_t shadow, subtraction, xmm_offset;
76 ABI_CalculateFrameSize(mask, rsp_alignment, needed_frame_size, &shadow, &subtraction,
77 &xmm_offset);
78
79 for (int x : mask& ABI_ALL_FPRS) {
80 MOVAPD((X64Reg)(x - 16), MDisp(RSP, (int)xmm_offset));
81 xmm_offset += 16;
82 }
83
84 if (subtraction)
85 ADD(64, R(RSP), subtraction >= 0x80 ? Imm32((u32)subtraction) : Imm8((u8)subtraction));
86
87 for (int r = 15; r >= 0; r--) {
88 if (mask[r])
89 POP((X64Reg)r);
90 }
91}
92
93// Common functions
94void XEmitter::ABI_CallFunction(const void* func) {
95 u64 distance = u64(func) - (u64(code) + 5);
96 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
97 // Far call
98 MOV(64, R(RAX), ImmPtr(func));
99 CALLptr(R(RAX));
100 } else {
101 CALL(func);
102 }
103}
104
105void XEmitter::ABI_CallFunctionC16(const void* func, u16 param1) {
106 MOV(32, R(ABI_PARAM1), Imm32((u32)param1));
107 u64 distance = u64(func) - (u64(code) + 5);
108 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
109 // Far call
110 MOV(64, R(RAX), ImmPtr(func));
111 CALLptr(R(RAX));
112 } else {
113 CALL(func);
114 }
115}
116
117void XEmitter::ABI_CallFunctionCC16(const void* func, u32 param1, u16 param2) {
118 MOV(32, R(ABI_PARAM1), Imm32(param1));
119 MOV(32, R(ABI_PARAM2), Imm32((u32)param2));
120 u64 distance = u64(func) - (u64(code) + 5);
121 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
122 // Far call
123 MOV(64, R(RAX), ImmPtr(func));
124 CALLptr(R(RAX));
125 } else {
126 CALL(func);
127 }
128}
129
130void XEmitter::ABI_CallFunctionC(const void* func, u32 param1) {
131 MOV(32, R(ABI_PARAM1), Imm32(param1));
132 u64 distance = u64(func) - (u64(code) + 5);
133 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
134 // Far call
135 MOV(64, R(RAX), ImmPtr(func));
136 CALLptr(R(RAX));
137 } else {
138 CALL(func);
139 }
140}
141
142void XEmitter::ABI_CallFunctionCC(const void* func, u32 param1, u32 param2) {
143 MOV(32, R(ABI_PARAM1), Imm32(param1));
144 MOV(32, R(ABI_PARAM2), Imm32(param2));
145 u64 distance = u64(func) - (u64(code) + 5);
146 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
147 // Far call
148 MOV(64, R(RAX), ImmPtr(func));
149 CALLptr(R(RAX));
150 } else {
151 CALL(func);
152 }
153}
154
155void XEmitter::ABI_CallFunctionCCC(const void* func, u32 param1, u32 param2, u32 param3) {
156 MOV(32, R(ABI_PARAM1), Imm32(param1));
157 MOV(32, R(ABI_PARAM2), Imm32(param2));
158 MOV(32, R(ABI_PARAM3), Imm32(param3));
159 u64 distance = u64(func) - (u64(code) + 5);
160 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
161 // Far call
162 MOV(64, R(RAX), ImmPtr(func));
163 CALLptr(R(RAX));
164 } else {
165 CALL(func);
166 }
167}
168
169void XEmitter::ABI_CallFunctionCCP(const void* func, u32 param1, u32 param2, void* param3) {
170 MOV(32, R(ABI_PARAM1), Imm32(param1));
171 MOV(32, R(ABI_PARAM2), Imm32(param2));
172 MOV(64, R(ABI_PARAM3), ImmPtr(param3));
173 u64 distance = u64(func) - (u64(code) + 5);
174 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
175 // Far call
176 MOV(64, R(RAX), ImmPtr(func));
177 CALLptr(R(RAX));
178 } else {
179 CALL(func);
180 }
181}
182
183void XEmitter::ABI_CallFunctionCCCP(const void* func, u32 param1, u32 param2, u32 param3,
184 void* param4) {
185 MOV(32, R(ABI_PARAM1), Imm32(param1));
186 MOV(32, R(ABI_PARAM2), Imm32(param2));
187 MOV(32, R(ABI_PARAM3), Imm32(param3));
188 MOV(64, R(ABI_PARAM4), ImmPtr(param4));
189 u64 distance = u64(func) - (u64(code) + 5);
190 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
191 // Far call
192 MOV(64, R(RAX), ImmPtr(func));
193 CALLptr(R(RAX));
194 } else {
195 CALL(func);
196 }
197}
198
199void XEmitter::ABI_CallFunctionP(const void* func, void* param1) {
200 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
201 u64 distance = u64(func) - (u64(code) + 5);
202 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
203 // Far call
204 MOV(64, R(RAX), ImmPtr(func));
205 CALLptr(R(RAX));
206 } else {
207 CALL(func);
208 }
209}
210
211void XEmitter::ABI_CallFunctionPA(const void* func, void* param1, const Gen::OpArg& arg2) {
212 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
213 if (!arg2.IsSimpleReg(ABI_PARAM2))
214 MOV(32, R(ABI_PARAM2), arg2);
215 u64 distance = u64(func) - (u64(code) + 5);
216 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
217 // Far call
218 MOV(64, R(RAX), ImmPtr(func));
219 CALLptr(R(RAX));
220 } else {
221 CALL(func);
222 }
223}
224
225void XEmitter::ABI_CallFunctionPAA(const void* func, void* param1, const Gen::OpArg& arg2,
226 const Gen::OpArg& arg3) {
227 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
228 if (!arg2.IsSimpleReg(ABI_PARAM2))
229 MOV(32, R(ABI_PARAM2), arg2);
230 if (!arg3.IsSimpleReg(ABI_PARAM3))
231 MOV(32, R(ABI_PARAM3), arg3);
232 u64 distance = u64(func) - (u64(code) + 5);
233 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
234 // Far call
235 MOV(64, R(RAX), ImmPtr(func));
236 CALLptr(R(RAX));
237 } else {
238 CALL(func);
239 }
240}
241
242void XEmitter::ABI_CallFunctionPPC(const void* func, void* param1, void* param2, u32 param3) {
243 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
244 MOV(64, R(ABI_PARAM2), ImmPtr(param2));
245 MOV(32, R(ABI_PARAM3), Imm32(param3));
246 u64 distance = u64(func) - (u64(code) + 5);
247 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
248 // Far call
249 MOV(64, R(RAX), ImmPtr(func));
250 CALLptr(R(RAX));
251 } else {
252 CALL(func);
253 }
254}
255
256// Pass a register as a parameter.
257void XEmitter::ABI_CallFunctionR(const void* func, X64Reg reg1) {
258 if (reg1 != ABI_PARAM1)
259 MOV(32, R(ABI_PARAM1), R(reg1));
260 u64 distance = u64(func) - (u64(code) + 5);
261 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
262 // Far call
263 MOV(64, R(RAX), ImmPtr(func));
264 CALLptr(R(RAX));
265 } else {
266 CALL(func);
267 }
268}
269
270// Pass two registers as parameters.
271void XEmitter::ABI_CallFunctionRR(const void* func, X64Reg reg1, X64Reg reg2) {
272 if (reg2 != ABI_PARAM1) {
273 if (reg1 != ABI_PARAM1)
274 MOV(64, R(ABI_PARAM1), R(reg1));
275 if (reg2 != ABI_PARAM2)
276 MOV(64, R(ABI_PARAM2), R(reg2));
277 } else {
278 if (reg2 != ABI_PARAM2)
279 MOV(64, R(ABI_PARAM2), R(reg2));
280 if (reg1 != ABI_PARAM1)
281 MOV(64, R(ABI_PARAM1), R(reg1));
282 }
283 u64 distance = u64(func) - (u64(code) + 5);
284 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
285 // Far call
286 MOV(64, R(RAX), ImmPtr(func));
287 CALLptr(R(RAX));
288 } else {
289 CALL(func);
290 }
291}
292
293void XEmitter::ABI_CallFunctionAC(const void* func, const Gen::OpArg& arg1, u32 param2) {
294 if (!arg1.IsSimpleReg(ABI_PARAM1))
295 MOV(32, R(ABI_PARAM1), arg1);
296 MOV(32, R(ABI_PARAM2), Imm32(param2));
297 u64 distance = u64(func) - (u64(code) + 5);
298 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
299 // Far call
300 MOV(64, R(RAX), ImmPtr(func));
301 CALLptr(R(RAX));
302 } else {
303 CALL(func);
304 }
305}
306
307void XEmitter::ABI_CallFunctionACC(const void* func, const Gen::OpArg& arg1, u32 param2,
308 u32 param3) {
309 if (!arg1.IsSimpleReg(ABI_PARAM1))
310 MOV(32, R(ABI_PARAM1), arg1);
311 MOV(32, R(ABI_PARAM2), Imm32(param2));
312 MOV(64, R(ABI_PARAM3), Imm64(param3));
313 u64 distance = u64(func) - (u64(code) + 5);
314 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
315 // Far call
316 MOV(64, R(RAX), ImmPtr(func));
317 CALLptr(R(RAX));
318 } else {
319 CALL(func);
320 }
321}
322
323void XEmitter::ABI_CallFunctionA(const void* func, const Gen::OpArg& arg1) {
324 if (!arg1.IsSimpleReg(ABI_PARAM1))
325 MOV(32, R(ABI_PARAM1), arg1);
326 u64 distance = u64(func) - (u64(code) + 5);
327 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
328 // Far call
329 MOV(64, R(RAX), ImmPtr(func));
330 CALLptr(R(RAX));
331 } else {
332 CALL(func);
333 }
334}
335
336void XEmitter::ABI_CallFunctionAA(const void* func, const Gen::OpArg& arg1,
337 const Gen::OpArg& arg2) {
338 if (!arg1.IsSimpleReg(ABI_PARAM1))
339 MOV(32, R(ABI_PARAM1), arg1);
340 if (!arg2.IsSimpleReg(ABI_PARAM2))
341 MOV(32, R(ABI_PARAM2), arg2);
342 u64 distance = u64(func) - (u64(code) + 5);
343 if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
344 // Far call
345 MOV(64, R(RAX), ImmPtr(func));
346 CALLptr(R(RAX));
347 } else {
348 CALL(func);
349 }
350} \ No newline at end of file