CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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