summaryrefslogtreecommitdiff
path: root/src/common/abi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/abi.cpp')
-rw-r--r--src/common/abi.cpp680
1 files changed, 680 insertions, 0 deletions
diff --git a/src/common/abi.cpp b/src/common/abi.cpp
new file mode 100644
index 000000000..d1892ad48
--- /dev/null
+++ b/src/common/abi.cpp
@@ -0,0 +1,680 @@
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 "x64_emitter.h"
19#include "abi.h"
20
21using namespace Gen;
22
23// Shared code between Win64 and Unix64
24
25// Sets up a __cdecl function.
26void XEmitter::ABI_EmitPrologue(int maxCallParams)
27{
28#ifdef _M_IX86
29 // Don't really need to do anything
30#elif defined(_M_X86_64)
31#if _WIN32
32 int stacksize = ((maxCallParams + 1) & ~1) * 8 + 8;
33 // Set up a stack frame so that we can call functions
34 // TODO: use maxCallParams
35 SUB(64, R(RSP), Imm8(stacksize));
36#endif
37#else
38#error Arch not supported
39#endif
40}
41
42void XEmitter::ABI_EmitEpilogue(int maxCallParams)
43{
44#ifdef _M_IX86
45 RET();
46#elif defined(_M_X86_64)
47#ifdef _WIN32
48 int stacksize = ((maxCallParams+1)&~1)*8 + 8;
49 ADD(64, R(RSP), Imm8(stacksize));
50#endif
51 RET();
52#else
53#error Arch not supported
54
55
56#endif
57}
58
59#ifdef _M_IX86 // All32
60
61// Shared code between Win32 and Unix32
62void XEmitter::ABI_CallFunction(const void *func) {
63 ABI_AlignStack(0);
64 CALL(func);
65 ABI_RestoreStack(0);
66}
67
68void XEmitter::ABI_CallFunctionC16(const void *func, u16 param1) {
69 ABI_AlignStack(1 * 2);
70 PUSH(16, Imm16(param1));
71 CALL(func);
72 ABI_RestoreStack(1 * 2);
73}
74
75void XEmitter::ABI_CallFunctionCC16(const void *func, u32 param1, u16 param2) {
76 ABI_AlignStack(1 * 2 + 1 * 4);
77 PUSH(16, Imm16(param2));
78 PUSH(32, Imm32(param1));
79 CALL(func);
80 ABI_RestoreStack(1 * 2 + 1 * 4);
81}
82
83void XEmitter::ABI_CallFunctionC(const void *func, u32 param1) {
84 ABI_AlignStack(1 * 4);
85 PUSH(32, Imm32(param1));
86 CALL(func);
87 ABI_RestoreStack(1 * 4);
88}
89
90void XEmitter::ABI_CallFunctionCC(const void *func, u32 param1, u32 param2) {
91 ABI_AlignStack(2 * 4);
92 PUSH(32, Imm32(param2));
93 PUSH(32, Imm32(param1));
94 CALL(func);
95 ABI_RestoreStack(2 * 4);
96}
97
98void XEmitter::ABI_CallFunctionCCC(const void *func, u32 param1, u32 param2, u32 param3) {
99 ABI_AlignStack(3 * 4);
100 PUSH(32, Imm32(param3));
101 PUSH(32, Imm32(param2));
102 PUSH(32, Imm32(param1));
103 CALL(func);
104 ABI_RestoreStack(3 * 4);
105}
106
107void XEmitter::ABI_CallFunctionCCP(const void *func, u32 param1, u32 param2, void *param3) {
108 ABI_AlignStack(3 * 4);
109 PUSH(32, ImmPtr(param3));
110 PUSH(32, Imm32(param2));
111 PUSH(32, Imm32(param1));
112 CALL(func);
113 ABI_RestoreStack(3 * 4);
114}
115
116void XEmitter::ABI_CallFunctionCCCP(const void *func, u32 param1, u32 param2,u32 param3, void *param4) {
117 ABI_AlignStack(4 * 4);
118 PUSH(32, ImmPtr(param4));
119 PUSH(32, Imm32(param3));
120 PUSH(32, Imm32(param2));
121 PUSH(32, Imm32(param1));
122 CALL(func);
123 ABI_RestoreStack(4 * 4);
124}
125
126void XEmitter::ABI_CallFunctionP(const void *func, void *param1) {
127 ABI_AlignStack(1 * 4);
128 PUSH(32, ImmPtr(param1));
129 CALL(func);
130 ABI_RestoreStack(1 * 4);
131}
132
133void XEmitter::ABI_CallFunctionPA(const void *func, void *param1, const Gen::OpArg &arg2) {
134 ABI_AlignStack(2 * 4);
135 PUSH(32, arg2);
136 PUSH(32, ImmPtr(param1));
137 CALL(func);
138 ABI_RestoreStack(2 * 4);
139}
140
141void XEmitter::ABI_CallFunctionPAA(const void *func, void *param1, const Gen::OpArg &arg2, const Gen::OpArg &arg3) {
142 ABI_AlignStack(3 * 4);
143 PUSH(32, arg3);
144 PUSH(32, arg2);
145 PUSH(32, ImmPtr(param1));
146 CALL(func);
147 ABI_RestoreStack(3 * 4);
148}
149
150void XEmitter::ABI_CallFunctionPPC(const void *func, void *param1, void *param2, u32 param3) {
151 ABI_AlignStack(3 * 4);
152 PUSH(32, Imm32(param3));
153 PUSH(32, ImmPtr(param2));
154 PUSH(32, ImmPtr(param1));
155 CALL(func);
156 ABI_RestoreStack(3 * 4);
157}
158
159// Pass a register as a parameter.
160void XEmitter::ABI_CallFunctionR(const void *func, X64Reg reg1) {
161 ABI_AlignStack(1 * 4);
162 PUSH(32, R(reg1));
163 CALL(func);
164 ABI_RestoreStack(1 * 4);
165}
166
167// Pass two registers as parameters.
168void XEmitter::ABI_CallFunctionRR(const void *func, Gen::X64Reg reg1, Gen::X64Reg reg2)
169{
170 ABI_AlignStack(2 * 4);
171 PUSH(32, R(reg2));
172 PUSH(32, R(reg1));
173 CALL(func);
174 ABI_RestoreStack(2 * 4);
175}
176
177void XEmitter::ABI_CallFunctionAC(const void *func, const Gen::OpArg &arg1, u32 param2)
178{
179 ABI_AlignStack(2 * 4);
180 PUSH(32, Imm32(param2));
181 PUSH(32, arg1);
182 CALL(func);
183 ABI_RestoreStack(2 * 4);
184}
185
186void XEmitter::ABI_CallFunctionACC(const void *func, const Gen::OpArg &arg1, u32 param2, u32 param3)
187{
188 ABI_AlignStack(3 * 4);
189 PUSH(32, Imm32(param3));
190 PUSH(32, Imm32(param2));
191 PUSH(32, arg1);
192 CALL(func);
193 ABI_RestoreStack(3 * 4);
194}
195
196void XEmitter::ABI_CallFunctionA(const void *func, const Gen::OpArg &arg1)
197{
198 ABI_AlignStack(1 * 4);
199 PUSH(32, arg1);
200 CALL(func);
201 ABI_RestoreStack(1 * 4);
202}
203
204void XEmitter::ABI_CallFunctionAA(const void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2)
205{
206 ABI_AlignStack(2 * 4);
207 PUSH(32, arg2);
208 PUSH(32, arg1);
209 CALL(func);
210 ABI_RestoreStack(2 * 4);
211}
212
213void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() {
214 // Note: 4 * 4 = 16 bytes, so alignment is preserved.
215 PUSH(EBP);
216 PUSH(EBX);
217 PUSH(ESI);
218 PUSH(EDI);
219}
220
221void XEmitter::ABI_PopAllCalleeSavedRegsAndAdjustStack() {
222 POP(EDI);
223 POP(ESI);
224 POP(EBX);
225 POP(EBP);
226}
227
228unsigned int XEmitter::ABI_GetAlignedFrameSize(unsigned int frameSize) {
229 frameSize += 4; // reserve space for return address
230 unsigned int alignedSize =
231#ifdef __GNUC__
232 (frameSize + 15) & -16;
233#else
234 (frameSize + 3) & -4;
235#endif
236 return alignedSize;
237}
238
239
240void XEmitter::ABI_AlignStack(unsigned int frameSize) {
241// Mac OS X requires the stack to be 16-byte aligned before every call.
242// Linux requires the stack to be 16-byte aligned before calls that put SSE
243// vectors on the stack, but since we do not keep track of which calls do that,
244// it is effectively every call as well.
245// Windows binaries compiled with MSVC do not have such a restriction*, but I
246// expect that GCC on Windows acts the same as GCC on Linux in this respect.
247// It would be nice if someone could verify this.
248// *However, the MSVC optimizing compiler assumes a 4-byte-aligned stack at times.
249 unsigned int fillSize =
250 ABI_GetAlignedFrameSize(frameSize) - (frameSize + 4);
251 if (fillSize != 0) {
252 SUB(32, R(ESP), Imm8(fillSize));
253 }
254}
255
256void XEmitter::ABI_RestoreStack(unsigned int frameSize) {
257 unsigned int alignedSize = ABI_GetAlignedFrameSize(frameSize);
258 alignedSize -= 4; // return address is POPped at end of call
259 if (alignedSize != 0) {
260 ADD(32, R(ESP), Imm8(alignedSize));
261 }
262}
263
264#else //64bit
265
266// Common functions
267void XEmitter::ABI_CallFunction(const void *func) {
268 u64 distance = u64(func) - (u64(code) + 5);
269 if (distance >= 0x0000000080000000ULL
270 && distance < 0xFFFFFFFF80000000ULL) {
271 // Far call
272 MOV(64, R(RAX), ImmPtr(func));
273 CALLptr(R(RAX));
274 } else {
275 CALL(func);
276 }
277}
278
279void XEmitter::ABI_CallFunctionC16(const void *func, u16 param1) {
280 MOV(32, R(ABI_PARAM1), Imm32((u32)param1));
281 u64 distance = u64(func) - (u64(code) + 5);
282 if (distance >= 0x0000000080000000ULL
283 && distance < 0xFFFFFFFF80000000ULL) {
284 // Far call
285 MOV(64, R(RAX), ImmPtr(func));
286 CALLptr(R(RAX));
287 } else {
288 CALL(func);
289 }
290}
291
292void XEmitter::ABI_CallFunctionCC16(const void *func, u32 param1, u16 param2) {
293 MOV(32, R(ABI_PARAM1), Imm32(param1));
294 MOV(32, R(ABI_PARAM2), Imm32((u32)param2));
295 u64 distance = u64(func) - (u64(code) + 5);
296 if (distance >= 0x0000000080000000ULL
297 && distance < 0xFFFFFFFF80000000ULL) {
298 // Far call
299 MOV(64, R(RAX), ImmPtr(func));
300 CALLptr(R(RAX));
301 } else {
302 CALL(func);
303 }
304}
305
306void XEmitter::ABI_CallFunctionC(const void *func, u32 param1) {
307 MOV(32, R(ABI_PARAM1), Imm32(param1));
308 u64 distance = u64(func) - (u64(code) + 5);
309 if (distance >= 0x0000000080000000ULL
310 && distance < 0xFFFFFFFF80000000ULL) {
311 // Far call
312 MOV(64, R(RAX), ImmPtr(func));
313 CALLptr(R(RAX));
314 } else {
315 CALL(func);
316 }
317}
318
319void XEmitter::ABI_CallFunctionCC(const void *func, u32 param1, u32 param2) {
320 MOV(32, R(ABI_PARAM1), Imm32(param1));
321 MOV(32, R(ABI_PARAM2), Imm32(param2));
322 u64 distance = u64(func) - (u64(code) + 5);
323 if (distance >= 0x0000000080000000ULL
324 && distance < 0xFFFFFFFF80000000ULL) {
325 // Far call
326 MOV(64, R(RAX), ImmPtr(func));
327 CALLptr(R(RAX));
328 } else {
329 CALL(func);
330 }
331}
332
333void XEmitter::ABI_CallFunctionCCC(const void *func, u32 param1, u32 param2, u32 param3) {
334 MOV(32, R(ABI_PARAM1), Imm32(param1));
335 MOV(32, R(ABI_PARAM2), Imm32(param2));
336 MOV(32, R(ABI_PARAM3), Imm32(param3));
337 u64 distance = u64(func) - (u64(code) + 5);
338 if (distance >= 0x0000000080000000ULL
339 && distance < 0xFFFFFFFF80000000ULL) {
340 // Far call
341 MOV(64, R(RAX), ImmPtr(func));
342 CALLptr(R(RAX));
343 } else {
344 CALL(func);
345 }
346}
347
348void XEmitter::ABI_CallFunctionCCP(const void *func, u32 param1, u32 param2, void *param3) {
349 MOV(32, R(ABI_PARAM1), Imm32(param1));
350 MOV(32, R(ABI_PARAM2), Imm32(param2));
351 MOV(64, R(ABI_PARAM3), ImmPtr(param3));
352 u64 distance = u64(func) - (u64(code) + 5);
353 if (distance >= 0x0000000080000000ULL
354 && distance < 0xFFFFFFFF80000000ULL) {
355 // Far call
356 MOV(64, R(RAX), ImmPtr(func));
357 CALLptr(R(RAX));
358 } else {
359 CALL(func);
360 }
361}
362
363void XEmitter::ABI_CallFunctionCCCP(const void *func, u32 param1, u32 param2, u32 param3, void *param4) {
364 MOV(32, R(ABI_PARAM1), Imm32(param1));
365 MOV(32, R(ABI_PARAM2), Imm32(param2));
366 MOV(32, R(ABI_PARAM3), Imm32(param3));
367 MOV(64, R(ABI_PARAM4), ImmPtr(param4));
368 u64 distance = u64(func) - (u64(code) + 5);
369 if (distance >= 0x0000000080000000ULL
370 && distance < 0xFFFFFFFF80000000ULL) {
371 // Far call
372 MOV(64, R(RAX), ImmPtr(func));
373 CALLptr(R(RAX));
374 } else {
375 CALL(func);
376 }
377}
378
379void XEmitter::ABI_CallFunctionP(const void *func, void *param1) {
380 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
381 u64 distance = u64(func) - (u64(code) + 5);
382 if (distance >= 0x0000000080000000ULL
383 && distance < 0xFFFFFFFF80000000ULL) {
384 // Far call
385 MOV(64, R(RAX), ImmPtr(func));
386 CALLptr(R(RAX));
387 } else {
388 CALL(func);
389 }
390}
391
392void XEmitter::ABI_CallFunctionPA(const void *func, void *param1, const Gen::OpArg &arg2) {
393 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
394 if (!arg2.IsSimpleReg(ABI_PARAM2))
395 MOV(32, R(ABI_PARAM2), arg2);
396 u64 distance = u64(func) - (u64(code) + 5);
397 if (distance >= 0x0000000080000000ULL
398 && distance < 0xFFFFFFFF80000000ULL) {
399 // Far call
400 MOV(64, R(RAX), ImmPtr(func));
401 CALLptr(R(RAX));
402 } else {
403 CALL(func);
404 }
405}
406
407void XEmitter::ABI_CallFunctionPAA(const void *func, void *param1, const Gen::OpArg &arg2, const Gen::OpArg &arg3) {
408 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
409 if (!arg2.IsSimpleReg(ABI_PARAM2))
410 MOV(32, R(ABI_PARAM2), arg2);
411 if (!arg3.IsSimpleReg(ABI_PARAM3))
412 MOV(32, R(ABI_PARAM3), arg3);
413 u64 distance = u64(func) - (u64(code) + 5);
414 if (distance >= 0x0000000080000000ULL
415 && distance < 0xFFFFFFFF80000000ULL) {
416 // Far call
417 MOV(64, R(RAX), ImmPtr(func));
418 CALLptr(R(RAX));
419 } else {
420 CALL(func);
421 }
422}
423
424void XEmitter::ABI_CallFunctionPPC(const void *func, void *param1, void *param2, u32 param3) {
425 MOV(64, R(ABI_PARAM1), ImmPtr(param1));
426 MOV(64, R(ABI_PARAM2), ImmPtr(param2));
427 MOV(32, R(ABI_PARAM3), Imm32(param3));
428 u64 distance = u64(func) - (u64(code) + 5);
429 if (distance >= 0x0000000080000000ULL
430 && distance < 0xFFFFFFFF80000000ULL) {
431 // Far call
432 MOV(64, R(RAX), ImmPtr(func));
433 CALLptr(R(RAX));
434 } else {
435 CALL(func);
436 }
437}
438
439// Pass a register as a parameter.
440void XEmitter::ABI_CallFunctionR(const void *func, X64Reg reg1) {
441 if (reg1 != ABI_PARAM1)
442 MOV(32, R(ABI_PARAM1), R(reg1));
443 u64 distance = u64(func) - (u64(code) + 5);
444 if (distance >= 0x0000000080000000ULL
445 && distance < 0xFFFFFFFF80000000ULL) {
446 // Far call
447 MOV(64, R(RAX), ImmPtr(func));
448 CALLptr(R(RAX));
449 } else {
450 CALL(func);
451 }
452}
453
454// Pass two registers as parameters.
455void XEmitter::ABI_CallFunctionRR(const void *func, X64Reg reg1, X64Reg reg2) {
456 if (reg2 != ABI_PARAM1) {
457 if (reg1 != ABI_PARAM1)
458 MOV(64, R(ABI_PARAM1), R(reg1));
459 if (reg2 != ABI_PARAM2)
460 MOV(64, R(ABI_PARAM2), R(reg2));
461 } else {
462 if (reg2 != ABI_PARAM2)
463 MOV(64, R(ABI_PARAM2), R(reg2));
464 if (reg1 != ABI_PARAM1)
465 MOV(64, R(ABI_PARAM1), R(reg1));
466 }
467 u64 distance = u64(func) - (u64(code) + 5);
468 if (distance >= 0x0000000080000000ULL
469 && distance < 0xFFFFFFFF80000000ULL) {
470 // Far call
471 MOV(64, R(RAX), ImmPtr(func));
472 CALLptr(R(RAX));
473 } else {
474 CALL(func);
475 }
476}
477
478void XEmitter::ABI_CallFunctionAC(const void *func, const Gen::OpArg &arg1, u32 param2)
479{
480 if (!arg1.IsSimpleReg(ABI_PARAM1))
481 MOV(32, R(ABI_PARAM1), arg1);
482 MOV(32, R(ABI_PARAM2), Imm32(param2));
483 u64 distance = u64(func) - (u64(code) + 5);
484 if (distance >= 0x0000000080000000ULL
485 && distance < 0xFFFFFFFF80000000ULL) {
486 // Far call
487 MOV(64, R(RAX), ImmPtr(func));
488 CALLptr(R(RAX));
489 } else {
490 CALL(func);
491 }
492}
493
494void XEmitter::ABI_CallFunctionACC(const void *func, const Gen::OpArg &arg1, u32 param2, u32 param3)
495{
496 if (!arg1.IsSimpleReg(ABI_PARAM1))
497 MOV(32, R(ABI_PARAM1), arg1);
498 MOV(32, R(ABI_PARAM2), Imm32(param2));
499 MOV(64, R(ABI_PARAM3), Imm64(param3));
500 u64 distance = u64(func) - (u64(code) + 5);
501 if (distance >= 0x0000000080000000ULL
502 && distance < 0xFFFFFFFF80000000ULL) {
503 // Far call
504 MOV(64, R(RAX), ImmPtr(func));
505 CALLptr(R(RAX));
506 } else {
507 CALL(func);
508 }
509}
510
511void XEmitter::ABI_CallFunctionA(const void *func, const Gen::OpArg &arg1)
512{
513 if (!arg1.IsSimpleReg(ABI_PARAM1))
514 MOV(32, R(ABI_PARAM1), arg1);
515 u64 distance = u64(func) - (u64(code) + 5);
516 if (distance >= 0x0000000080000000ULL
517 && distance < 0xFFFFFFFF80000000ULL) {
518 // Far call
519 MOV(64, R(RAX), ImmPtr(func));
520 CALLptr(R(RAX));
521 } else {
522 CALL(func);
523 }
524}
525
526void XEmitter::ABI_CallFunctionAA(const void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2)
527{
528 if (!arg1.IsSimpleReg(ABI_PARAM1))
529 MOV(32, R(ABI_PARAM1), arg1);
530 if (!arg2.IsSimpleReg(ABI_PARAM2))
531 MOV(32, R(ABI_PARAM2), arg2);
532 u64 distance = u64(func) - (u64(code) + 5);
533 if (distance >= 0x0000000080000000ULL
534 && distance < 0xFFFFFFFF80000000ULL) {
535 // Far call
536 MOV(64, R(RAX), ImmPtr(func));
537 CALLptr(R(RAX));
538 } else {
539 CALL(func);
540 }
541}
542
543unsigned int XEmitter::ABI_GetAlignedFrameSize(unsigned int frameSize) {
544 return frameSize;
545}
546
547#ifdef _WIN32
548
549// The Windows x64 ABI requires XMM6 - XMM15 to be callee saved. 10 regs.
550// But, not saving XMM4 and XMM5 breaks things in VS 2010, even though they are volatile regs.
551// Let's just save all 16.
552const int XMM_STACK_SPACE = 16 * 16;
553
554// Win64 Specific Code
555void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() {
556 //we only want to do this once
557 PUSH(RBX);
558 PUSH(RSI);
559 PUSH(RDI);
560 PUSH(RBP);
561 PUSH(R12);
562 PUSH(R13);
563 PUSH(R14);
564 PUSH(R15);
565 ABI_AlignStack(0);
566
567 // Do this after aligning, because before it's offset by 8.
568 SUB(64, R(RSP), Imm32(XMM_STACK_SPACE));
569 for (int i = 0; i < 16; ++i)
570 MOVAPS(MDisp(RSP, i * 16), (X64Reg)(XMM0 + i));
571}
572
573void XEmitter::ABI_PopAllCalleeSavedRegsAndAdjustStack() {
574 for (int i = 0; i < 16; ++i)
575 MOVAPS((X64Reg)(XMM0 + i), MDisp(RSP, i * 16));
576 ADD(64, R(RSP), Imm32(XMM_STACK_SPACE));
577
578 ABI_RestoreStack(0);
579 POP(R15);
580 POP(R14);
581 POP(R13);
582 POP(R12);
583 POP(RBP);
584 POP(RDI);
585 POP(RSI);
586 POP(RBX);
587}
588
589// Win64 Specific Code
590void XEmitter::ABI_PushAllCallerSavedRegsAndAdjustStack() {
591 PUSH(RCX);
592 PUSH(RDX);
593 PUSH(RSI);
594 PUSH(RDI);
595 PUSH(R8);
596 PUSH(R9);
597 PUSH(R10);
598 PUSH(R11);
599 // TODO: Callers preserve XMM4-5 (XMM0-3 are args.)
600 ABI_AlignStack(0);
601}
602
603void XEmitter::ABI_PopAllCallerSavedRegsAndAdjustStack() {
604 ABI_RestoreStack(0);
605 POP(R11);
606 POP(R10);
607 POP(R9);
608 POP(R8);
609 POP(RDI);
610 POP(RSI);
611 POP(RDX);
612 POP(RCX);
613}
614
615void XEmitter::ABI_AlignStack(unsigned int /*frameSize*/) {
616 SUB(64, R(RSP), Imm8(0x28));
617}
618
619void XEmitter::ABI_RestoreStack(unsigned int /*frameSize*/) {
620 ADD(64, R(RSP), Imm8(0x28));
621}
622
623#else
624// Unix64 Specific Code
625void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() {
626 PUSH(RBX);
627 PUSH(RBP);
628 PUSH(R12);
629 PUSH(R13);
630 PUSH(R14);
631 PUSH(R15);
632 PUSH(R15); //just to align stack. duped push/pop doesn't hurt.
633 // TODO: XMM?
634}
635
636void XEmitter::ABI_PopAllCalleeSavedRegsAndAdjustStack() {
637 POP(R15);
638 POP(R15);
639 POP(R14);
640 POP(R13);
641 POP(R12);
642 POP(RBP);
643 POP(RBX);
644}
645
646void XEmitter::ABI_PushAllCallerSavedRegsAndAdjustStack() {
647 PUSH(RCX);
648 PUSH(RDX);
649 PUSH(RSI);
650 PUSH(RDI);
651 PUSH(R8);
652 PUSH(R9);
653 PUSH(R10);
654 PUSH(R11);
655 PUSH(R11);
656}
657
658void XEmitter::ABI_PopAllCallerSavedRegsAndAdjustStack() {
659 POP(R11);
660 POP(R11);
661 POP(R10);
662 POP(R9);
663 POP(R8);
664 POP(RDI);
665 POP(RSI);
666 POP(RDX);
667 POP(RCX);
668}
669
670void XEmitter::ABI_AlignStack(unsigned int /*frameSize*/) {
671 SUB(64, R(RSP), Imm8(0x08));
672}
673
674void XEmitter::ABI_RestoreStack(unsigned int /*frameSize*/) {
675 ADD(64, R(RSP), Imm8(0x08));
676}
677
678#endif // WIN32
679
680#endif // 32bit