improve ARM feature detection
[pcsx_rearmed.git] / libpcsxcore / ix86_64 / iR3000A-64.c
CommitLineData
ef79bbde
P
1/***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
18 ***************************************************************************/
19
20/*
21* i386 assembly functions for R3000A core.
22*/
23
24#include "ix86-64.h"
25#include "../r3000a.h"
26#include "../psxhle.h"
27
28#include <sys/mman.h>
29
30#ifndef MAP_ANONYMOUS
31#define MAP_ANONYMOUS MAP_ANON
32#endif
33
34uptr* psxRecLUT;
35
36#define PTRMULT (sizeof(uptr) / sizeof(u32))
37
38#undef PC_REC
39#undef PC_REC8
40#undef PC_REC16
41#undef PC_REC32
42#define PC_REC(x) (psxRecLUT[(x) >> 16] + PTRMULT * ((x) & 0xffff))
43#define PC_RECP(x) (*(uptr *)PC_REC(x))
44
45#define RECMEM_SIZE (PTRMULT * 8 * 1024 * 1024)
46
47static char *recMem; /* the recompiled blocks will be here */
48static char *recRAM; /* and the ptr to the blocks here */
49static char *recROM; /* and here */
50
51static u32 pc; /* recompiler pc */
52static u32 pcold; /* recompiler oldpc */
53static int count; /* recompiler intruction count */
54static int branch; /* set for branch */
55static u32 target; /* branch target */
56static u32 resp;
57
58typedef struct {
59 int state;
60 u32 k;
61 int reg;
62} iRegisters;
63
64static iRegisters iRegs[32];
65static iRegisters iRegsS[32];
66
67#define ST_UNK 0
68#define ST_CONST 1
69#define ST_MAPPED 2
70
71#define IsConst(reg) (iRegs[reg].state == ST_CONST)
72#define IsMapped(reg) (iRegs[reg].state == ST_MAPPED)
73
74static void (*recBSC[64])();
75static void (*recSPC[64])();
76static void (*recREG[32])();
77static void (*recCP0[32])();
78static void (*recCP2[64])();
79static void (*recCP2BSC[32])();
80
81#define STACKSIZE 0x18
82static void StackRes()
83{
84#ifdef __x86_64__
85 ADD64ItoR(RSP, STACKSIZE);
86#else
87 if (resp) ADD32ItoR(ESP, resp);
88#endif
89}
90
91static void MapConst(int reg, u32 _const) {
92 iRegs[reg].k = _const;
93 iRegs[reg].state = ST_CONST;
94}
95
96static void iFlushReg(int reg) {
97 if (IsConst(reg)) {
98 MOV32ItoM((uptr)&psxRegs.GPR.r[reg], iRegs[reg].k);
99 }
100 iRegs[reg].state = ST_UNK;
101}
102
103static void iFlushRegs() {
104 int i;
105
106 for (i=1; i<32; i++) {
107 iFlushReg(i);
108 }
109}
110
111static void iRet() {
112 /* store cycle */
113 count = ((pc - pcold) / 4) * BIAS;
114 ADD32ItoM((uptr)&psxRegs.cycle, count);
115 StackRes();
116 RET();
117}
118
119static int iLoadTest() {
120 u32 tmp;
121
122 // check for load delay
123 tmp = psxRegs.code >> 26;
124 switch (tmp) {
125 case 0x10: // COP0
126 switch (_Rs_) {
127 case 0x00: // MFC0
128 case 0x02: // CFC0
129 return 1;
130 }
131 break;
132 case 0x12: // COP2
133 switch (_Funct_) {
134 case 0x00:
135 switch (_Rs_) {
136 case 0x00: // MFC2
137 case 0x02: // CFC2
138 return 1;
139 }
140 break;
141 }
142 break;
143 case 0x32: // LWC2
144 return 1;
145 default:
146 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
147 return 1;
148 }
149 break;
150 }
151 return 0;
152}
153
154/* set a pending branch */
155static void SetBranch() {
156 branch = 1;
157 psxRegs.code = PSXMu32(pc);
158 pc+=4;
159
160 if (iLoadTest() == 1) {
161 iFlushRegs();
162 MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
163 /* store cycle */
164 count = ((pc - pcold) / 4) * BIAS;
165 ADD32ItoM((uptr)&psxRegs.cycle, count);
166
167 //PUSH64M((uptr)&target);
168 MOV32MtoR(X86ARG2, (uptr)&target);
169 //PUSHI(_Rt_);
170 MOV64ItoR(X86ARG1, _Rt_);
171 CALLFunc((uptr)psxDelayTest);
172 StackRes();
173 RET();
174 return;
175 }
176
177 recBSC[psxRegs.code>>26]();
178
179 iFlushRegs();
180 MOV32MtoR(EAX, (uptr)&target);
181 MOV32RtoM((uptr)&psxRegs.pc, EAX);
182 CALLFunc((uptr)psxBranchTest);
183
184 iRet();
185}
186
187static void iJump(u32 branchPC) {
188 branch = 1;
189 psxRegs.code = PSXMu32(pc);
190 pc+=4;
191
192 if (iLoadTest() == 1) {
193 iFlushRegs();
194 MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
195 /* store cycle */
196 count = ((pc - pcold) / 4) * BIAS;
197 ADD32ItoM((uptr)&psxRegs.cycle, count);
198
199 //PUSHI(branchPC);
200 MOV64ItoR(X86ARG2, branchPC);
201 //PUSHI(_Rt_);
202 MOV64ItoR(X86ARG1, _Rt_);
203 CALLFunc((uptr)psxDelayTest);
204 //ADD32ItoR(ESP, 2*8);
205 StackRes();
206 RET();
207 return;
208 }
209
210 recBSC[psxRegs.code>>26]();
211
212 iFlushRegs();
213 MOV32ItoM((uptr)&psxRegs.pc, branchPC);
214 CALLFunc((uptr)psxBranchTest);
215 /* store cycle */
216 count = ((pc - pcold) / 4) * BIAS;
217 ADD32ItoM((uptr)&psxRegs.cycle, count);
218 StackRes();
219
220 RET();
221 //* XXX?
222 // maybe just happened an interruption, check so
223 CMP32ItoM((uptr)&psxRegs.pc, branchPC);
224 j8Ptr[0] = JE8(0);
225
226 RET();
227
228 x86SetJ8(j8Ptr[0]);
229 MOV64MtoR(RAX, PC_REC(branchPC));
230 TEST64RtoR(RAX,RAX);
231 j8Ptr[1] = JNE8(0);
232
233 RET();
234
235 x86SetJ8(j8Ptr[1]);
236
237 RET();
238 //JMP32R(EAX);
239 JMPR(EAX);
240 //*/
241}
242
243static void iBranch(u32 branchPC, int savectx) {
244 u32 respold=0;
245
246 if (savectx) {
247 respold = resp;
248 memcpy(iRegsS, iRegs, sizeof(iRegs));
249 }
250
251 branch = 1;
252 psxRegs.code = PSXMu32(pc);
253
254 // the delay test is only made when the branch is taken
255 // savectx == 0 will mean that :)
256 if (savectx == 0 && iLoadTest() == 1) {
257 iFlushRegs();
258 MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
259 /* store cycle */
260 count = (((pc+4) - pcold) / 4) * BIAS;
261 ADD32ItoM((uptr)&psxRegs.cycle, count);
262 //if (resp) ADD32ItoR(ESP, resp);
263
264 //PUSHI(branchPC);
265 MOV64ItoR(X86ARG2, branchPC);
266 //PUSHI(_Rt_);
267 MOV64ItoR(X86ARG1,_Rt_);
268 CALLFunc((uptr)psxDelayTest);
269 StackRes();
270 RET();
271 return;
272 }
273
274 pc+= 4;
275 recBSC[psxRegs.code>>26]();
276
277 iFlushRegs();
278 MOV32ItoM((uptr)&psxRegs.pc, branchPC);
279 CALLFunc((uptr)psxBranchTest);
280 /* store cycle */
281 count = ((pc - pcold) / 4) * BIAS;
282 ADD32ItoM((uptr)&psxRegs.cycle, count);
283
284 StackRes();
285
286 // maybe just happened an interruption, check so
287 CMP32ItoM((uptr)&psxRegs.pc, branchPC);
288 j8Ptr[1] = JE8(0);
289
290 RET();
291
292 x86SetJ8(j8Ptr[1]);
293 MOV64MtoR(RAX, PC_REC(branchPC));
294 TEST64RtoR(RAX, RAX);
295 j8Ptr[2] = JNE8(0);
296
297 RET();
298
299 x86SetJ8(j8Ptr[2]);
300 //JMP32R(EAX);
301 JMPR(EAX);
302
303 pc-= 4;
304 if (savectx) {
305 resp = respold;
306 memcpy(iRegs, iRegsS, sizeof(iRegs));
307 }
308}
309
310
311char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n";
312char *txt1 = "EAX = %x\n";
313char *txt2 = "M32 = %x\n";
314
315/*
316void iLogX86() {
317 PUSHA32();
318
319 PUSH32R (EDX);
320 PUSH32R (ECX);
321 PUSH32R (EAX);
322 PUSH32M ((uptr)&txt0);
323 CALLFunc((uptr)SysPrintf);
324 ADD32ItoR(ESP, 4*4);
325
326 POPA32();
327}
328*/
329
330void iLogEAX() {
331 PUSH64R (EAX);
332 PUSH64M ((uptr)&txt1);
333 CALLFunc((uptr)SysPrintf);
334 ADD32ItoR(ESP, 8*2);
335}
336
337void iLogM32(u32 mem) {
338 PUSH64M (mem);
339 PUSH64M ((uptr)&txt2);
340 CALLFunc((uptr)SysPrintf);
341 ADD32ItoR(ESP, 8*2);
342}
343
344static void iDumpRegs() {
345 int i, j;
346
347 printf("%x %x\n", psxRegs.pc, psxRegs.cycle);
348 for (i = 0; i < 4; i++) {
349 for (j = 0; j < 8; j++)
350 printf("%x ", psxRegs.GPR.r[j*i]);
351 printf("\n");
352 }
353}
354
355void iDumpBlock(char *ptr) {
356 FILE *f;
357 u32 i;
358
359 SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxRegs.cycle);
360
361 for (i = psxRegs.pc; i < pc; i+=4)
362 SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
363
364 fflush(stdout);
365 f = fopen("dump1", "w");
366 fwrite(ptr, 1, (uptr)x86Ptr - (uptr)ptr, f);
367 fclose(f);
368 //system("ndisasm -b64 dump1");
369 fflush(stdout);
370}
371
372#define REC_FUNC(f) \
373void psx##f(); \
374static void rec##f() { \
375 iFlushRegs(); \
376 MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
377 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
378 CALLFunc((uptr)psx##f); \
379/* branch = 2; */\
380}
381
382#define REC_SYS(f) \
383void psx##f(); \
384static void rec##f() { \
385 iFlushRegs(); \
386 MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
387 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
388 CALLFunc((uptr)psx##f); \
389 branch = 2; \
390 iRet(); \
391}
392
393#define REC_BRANCH(f) \
394void psx##f(); \
395static void rec##f() { \
396 iFlushRegs(); \
397 MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
398 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
399 CALLFunc((uptr)psx##f); \
400 branch = 2; \
401 iRet(); \
402}
403
404static void recRecompile();
405
406static int recInit() {
407 int i;
408
409 psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));
410
411 recMem = mmap(0,
412 RECMEM_SIZE + PTRMULT*0x1000,
413 PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
414
415 recRAM = mmap(0,
416 0x280000*PTRMULT,
417 PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
418 recROM = &recRAM[0x200000*PTRMULT];
419
420 if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) {
421 SysMessage("Error allocating memory"); return -1;
422 }
423 memset(recMem, 0, RECMEM_SIZE);
424 memset(recRAM, 0, 0x200000 * PTRMULT);
425 memset(recROM, 0, 0x080000 * PTRMULT);
426
427 for (i=0; i<0x80; i++) psxRecLUT[i + 0x0000] = (uptr)&recRAM[PTRMULT*((i & 0x1f) << 16)];
428 memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * sizeof(uptr));
429 memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * sizeof(uptr));
430
431 for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (uptr)&recROM[PTRMULT*(i << 16)];
432
433 return 0;
434}
435
436static void recReset() {
437 memset(recRAM, 0, 0x200000 * PTRMULT);
438 memset(recROM, 0, 0x080000 * PTRMULT);
439
440 //x86Init();
441 cpudetectInit();
442 x86SetPtr(recMem);
443
444 branch = 0;
445 memset(iRegs, 0, sizeof(iRegs));
446 iRegs[0].state = ST_CONST;
447 iRegs[0].k = 0;
448}
449
450static void recShutdown() {
451 if (recMem == NULL) return;
452 free(psxRecLUT);
453 munmap(recMem, RECMEM_SIZE + PTRMULT*0x1000);
454 munmap(recRAM, 0x280000*PTRMULT);
455 x86Shutdown();
456}
457
458static void recError() {
459 SysReset();
460 ClosePlugins();
461 SysMessage("Unrecoverable error while running recompiler\n");
462 SysRunGui();
463}
464
465/*__inline*/ static void execute() {
466 void (*recFunc)();
467 uptr *p;
468
469 p = (uptr *)PC_REC(psxRegs.pc);
470 // if (!p) { recError(); return; }
471
472 if (*p == 0) {
473 recRecompile();
474 }
475
476 if (*p < (uptr)recMem || *p >= (uptr)recMem + RECMEM_SIZE)
477 {
478 recError();
479 return;
480 }
481 recFunc = (void (*)())*p;
482 (*recFunc)();
483}
484
485static void recExecute() {
486 for (;;) execute();
487}
488
489static void recExecuteBlock() {
490 execute();
491}
492
493static void recClear(u32 Addr, u32 Size) {
494 memset((void*)PC_REC(Addr), 0, Size * sizeof(uptr));
495}
496
497static void recNULL() {
498// SysMessage("recUNK: %8.8x\n", psxRegs.code);
499}
500
501/*********************************************************
502* goes to opcodes tables... *
503* Format: table[something....] *
504*********************************************************/
505
506//REC_SYS(SPECIAL);
507#if 1
508static void recSPECIAL() {
509 recSPC[_Funct_]();
510}
511#endif
512
513static void recREGIMM() {
514 recREG[_Rt_]();
515}
516
517static void recCOP0() {
518 recCP0[_Rs_]();
519}
520
521//REC_SYS(COP2);
522#if 1
523static void recCOP2() {
524 recCP2[_Funct_]();
525}
526#endif
527
528static void recBASIC() {
529 recCP2BSC[_Rs_]();
530}
531
532//end of Tables opcodes...
533
534/*********************************************************
535* Arithmetic with immediate operand *
536* Format: OP rt, rs, immediate *
537*********************************************************/
538
539#if 0
540REC_FUNC(ADDI);
541REC_FUNC(ADDIU);
542REC_FUNC(ANDI);
543REC_FUNC(ORI);
544REC_FUNC(XORI);
545REC_FUNC(SLTI);
546REC_FUNC(SLTIU);
547#endif
548
549#if 1
550static void recADDIU() {
551// Rt = Rs + Im
552 if (!_Rt_) return;
553
554// iFlushRegs();
555
556 if (_Rs_ == _Rt_) {
557 if (IsConst(_Rt_)) {
558 iRegs[_Rt_].k+= _Imm_;
559 } else {
560 if (_Imm_ == 1) {
561 INC32M((uptr)&psxRegs.GPR.r[_Rt_]);
562 } else if (_Imm_ == -1) {
563 DEC32M((uptr)&psxRegs.GPR.r[_Rt_]);
564 } else if (_Imm_) {
565 ADD32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _Imm_);
566 }
567 }
568 } else {
569 if (IsConst(_Rs_)) {
570 MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
571 } else {
572 iRegs[_Rt_].state = ST_UNK;
573
574 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
575 if (_Imm_ == 1) {
576 INC32R(EAX);
577 } else if (_Imm_ == -1) {
578 DEC32R(EAX);
579 } else if (_Imm_) {
580 ADD32ItoR(EAX, _Imm_);
581 }
582 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
583 }
584 }
585}
586
587static void recADDI() {
588// Rt = Rs + Im
589 recADDIU();
590}
591
592static void recSLTI() {
593// Rt = Rs < Im (signed)
594 if (!_Rt_) return;
595
596// iFlushRegs();
597
598 if (IsConst(_Rs_)) {
599 MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
600 } else {
601 iRegs[_Rt_].state = ST_UNK;
602
603 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
604 CMP32ItoR(EAX, _Imm_);
605 SETL8R (EAX);
606 AND32ItoR(EAX, 0xff);
607 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
608 }
609}
610
611static void recSLTIU() {
612// Rt = Rs < Im (unsigned)
613 if (!_Rt_) return;
614
615// iFlushRegs();
616
617 if (IsConst(_Rs_)) {
618 MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
619 } else {
620 iRegs[_Rt_].state = ST_UNK;
621
622 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
623 CMP32ItoR(EAX, _Imm_);
624 SETB8R (EAX);
625 AND32ItoR(EAX, 0xff);
626 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
627 }
628}
629
630static void recANDI() {
631// Rt = Rs And Im
632 if (!_Rt_) return;
633
634// iFlushRegs();
635
636 if (_Rs_ == _Rt_) {
637 if (IsConst(_Rt_)) {
638 iRegs[_Rt_].k&= _ImmU_;
639 } else {
640 AND32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
641 }
642 } else {
643 if (IsConst(_Rs_)) {
644 MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
645 } else {
646 iRegs[_Rt_].state = ST_UNK;
647
648 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
649 AND32ItoR(EAX, _ImmU_);
650 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
651 }
652 }
653}
654
655static void recORI() {
656// Rt = Rs Or Im
657 if (!_Rt_) return;
658
659// iFlushRegs();
660
661 if (_Rs_ == _Rt_) {
662 if (IsConst(_Rt_)) {
663 iRegs[_Rt_].k|= _ImmU_;
664 } else {
665 OR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
666 }
667 } else {
668 if (IsConst(_Rs_)) {
669 MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
670 } else {
671 iRegs[_Rt_].state = ST_UNK;
672
673 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
674 if (_ImmU_) OR32ItoR (EAX, _ImmU_);
675 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
676 }
677 }
678}
679
680static void recXORI() {
681// Rt = Rs Xor Im
682 if (!_Rt_) return;
683
684// iFlushRegs();
685
686 if (_Rs_ == _Rt_) {
687 if (IsConst(_Rt_)) {
688 iRegs[_Rt_].k^= _ImmU_;
689 } else {
690 XOR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
691 }
692 } else {
693 if (IsConst(_Rs_)) {
694 MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
695 } else {
696 iRegs[_Rt_].state = ST_UNK;
697
698 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
699 XOR32ItoR(EAX, _ImmU_);
700 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
701 }
702 }
703}
704#endif
705//end of * Arithmetic with immediate operand
706
707/*********************************************************
708* Load higher 16 bits of the first word in GPR with imm *
709* Format: OP rt, immediate *
710*********************************************************/
711//REC_FUNC(LUI);
712#if 1
713static void recLUI() {
714// Rt = Imm << 16
715 if (!_Rt_) return;
716
717 MapConst(_Rt_, psxRegs.code << 16);
718}
719#endif
720//End of Load Higher .....
721
722
723/*********************************************************
724* Register arithmetic *
725* Format: OP rd, rs, rt *
726*********************************************************/
727
728
729#if 0
730REC_FUNC(ADD);
731REC_FUNC(ADDU);
732REC_FUNC(SUB);
733REC_FUNC(SUBU);
734REC_FUNC(AND);
735REC_FUNC(OR);
736REC_FUNC(XOR);
737REC_FUNC(NOR);
738REC_FUNC(SLT);
739REC_FUNC(SLTU);
740#endif
741
742#if 1
743static void recADDU() {
744// Rd = Rs + Rt
745 if (!_Rd_) return;
746
747// iFlushRegs();
748
749 if (IsConst(_Rs_) && IsConst(_Rt_)) {
750 MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k);
751 } else if (IsConst(_Rs_)) {
752 iRegs[_Rd_].state = ST_UNK;
753
754 if (_Rt_ == _Rd_) {
755 if (iRegs[_Rs_].k == 1) {
756 INC32M((uptr)&psxRegs.GPR.r[_Rd_]);
757 } else if (iRegs[_Rs_].k == -1) {
758 DEC32M((uptr)&psxRegs.GPR.r[_Rd_]);
759 } else if (iRegs[_Rs_].k) {
760 ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
761 }
762 } else {
763 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
764 if (iRegs[_Rs_].k == 1) {
765 INC32R(EAX);
766 } else if (iRegs[_Rs_].k == 0xffffffff) {
767 DEC32R(EAX);
768 } else if (iRegs[_Rs_].k) {
769 ADD32ItoR(EAX, iRegs[_Rs_].k);
770 }
771 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
772 }
773 } else if (IsConst(_Rt_)) {
774 iRegs[_Rd_].state = ST_UNK;
775
776 if (_Rs_ == _Rd_) {
777 if (iRegs[_Rt_].k == 1) {
778 INC32M((uptr)&psxRegs.GPR.r[_Rd_]);
779 } else if (iRegs[_Rt_].k == -1) {
780 DEC32M((uptr)&psxRegs.GPR.r[_Rd_]);
781 } else if (iRegs[_Rt_].k) {
782 ADD32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
783 }
784 } else {
785 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
786 if (iRegs[_Rt_].k == 1) {
787 INC32R(EAX);
788 } else if (iRegs[_Rt_].k == 0xffffffff) {
789 DEC32R(EAX);
790 } else if (iRegs[_Rt_].k) {
791 ADD32ItoR(EAX, iRegs[_Rt_].k);
792 }
793 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
794 }
795 } else {
796 iRegs[_Rd_].state = ST_UNK;
797
798 if (_Rs_ == _Rd_) { // Rd+= Rt
799 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
800 ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
801 } else if (_Rt_ == _Rd_) { // Rd+= Rs
802 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
803 ADD32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
804 } else { // Rd = Rs + Rt
805 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
806 ADD32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
807 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
808 }
809 }
810}
811
812static void recADD() {
813// Rd = Rs + Rt
814 recADDU();
815}
816
817static void recSUBU() {
818// Rd = Rs - Rt
819 if (!_Rd_) return;
820
821// iFlushRegs();
822
823 if (IsConst(_Rs_) && IsConst(_Rt_)) {
824 MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k);
825 } else if (IsConst(_Rs_)) {
826 iRegs[_Rd_].state = ST_UNK;
827
828 MOV32ItoR(EAX, iRegs[_Rs_].k);
829 SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
830 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
831 } else if (IsConst(_Rt_)) {
832 iRegs[_Rd_].state = ST_UNK;
833
834 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
835 SUB32ItoR(EAX, iRegs[_Rt_].k);
836 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
837 } else {
838 iRegs[_Rd_].state = ST_UNK;
839
840 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
841 SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
842 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
843 }
844}
845
846static void recSUB() {
847// Rd = Rs - Rt
848 recSUBU();
849}
850
851static void recAND() {
852// Rd = Rs And Rt
853 if (!_Rd_) return;
854
855// iFlushRegs();
856
857 if (IsConst(_Rs_) && IsConst(_Rt_)) {
858 MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k);
859 } else if (IsConst(_Rs_)) {
860 iRegs[_Rd_].state = ST_UNK;
861
862 if (_Rd_ == _Rt_) { // Rd&= Rs
863 AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
864 } else {
865 MOV32ItoR(EAX, iRegs[_Rs_].k);
866 AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
867 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
868 }
869 } else if (IsConst(_Rt_)) {
870 iRegs[_Rd_].state = ST_UNK;
871
872 if (_Rd_ == _Rs_) { // Rd&= kRt
873 AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
874 } else { // Rd = Rs & kRt
875 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
876 AND32ItoR(EAX, iRegs[_Rt_].k);
877 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
878 }
879 } else {
880 iRegs[_Rd_].state = ST_UNK;
881
882 if (_Rs_ == _Rd_) { // Rd&= Rt
883 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
884 AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
885 } else if (_Rt_ == _Rd_) { // Rd&= Rs
886 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
887 AND32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
888 } else { // Rd = Rs & Rt
889 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
890 AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
891 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
892 }
893 }
894}
895
896static void recOR() {
897// Rd = Rs Or Rt
898 if (!_Rd_) return;
899
900// iFlushRegs();
901
902 if (IsConst(_Rs_) && IsConst(_Rt_)) {
903 MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k);
904 } else if (IsConst(_Rs_)) {
905 iRegs[_Rd_].state = ST_UNK;
906
907 MOV32ItoR(EAX, iRegs[_Rs_].k);
908 OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
909 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
910 } else if (IsConst(_Rt_)) {
911 iRegs[_Rd_].state = ST_UNK;
912
913 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
914 OR32ItoR (EAX, iRegs[_Rt_].k);
915 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
916 } else {
917 iRegs[_Rd_].state = ST_UNK;
918
919 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
920 OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
921 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
922 }
923}
924
925static void recXOR() {
926// Rd = Rs Xor Rt
927 if (!_Rd_) return;
928
929// iFlushRegs();
930
931 if (IsConst(_Rs_) && IsConst(_Rt_)) {
932 MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k);
933 } else if (IsConst(_Rs_)) {
934 iRegs[_Rd_].state = ST_UNK;
935
936 MOV32ItoR(EAX, iRegs[_Rs_].k);
937 XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
938 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
939 } else if (IsConst(_Rt_)) {
940 iRegs[_Rd_].state = ST_UNK;
941
942 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
943 XOR32ItoR(EAX, iRegs[_Rt_].k);
944 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
945 } else {
946 iRegs[_Rd_].state = ST_UNK;
947
948 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
949 XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
950 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
951 }
952}
953
954static void recNOR() {
955// Rd = Rs Nor Rt
956 if (!_Rd_) return;
957
958// iFlushRegs();
959
960 if (IsConst(_Rs_) && IsConst(_Rt_)) {
961 MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k));
962 } else if (IsConst(_Rs_)) {
963 iRegs[_Rd_].state = ST_UNK;
964
965 MOV32ItoR(EAX, iRegs[_Rs_].k);
966 OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
967 NOT32R (EAX);
968 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
969 } else if (IsConst(_Rt_)) {
970 iRegs[_Rd_].state = ST_UNK;
971
972 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
973 OR32ItoR (EAX, iRegs[_Rt_].k);
974 NOT32R (EAX);
975 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
976 } else {
977 iRegs[_Rd_].state = ST_UNK;
978
979 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
980 OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
981 NOT32R (EAX);
982 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
983 }
984}
985
986static void recSLT() {
987// Rd = Rs < Rt (signed)
988 if (!_Rd_) return;
989
990// iFlushRegs();
991
992 if (IsConst(_Rs_) && IsConst(_Rt_)) {
993 MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k);
994 } else if (IsConst(_Rs_)) {
995 iRegs[_Rd_].state = ST_UNK;
996
997 MOV32ItoR(EAX, iRegs[_Rs_].k);
998 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
999 SETL8R (EAX);
1000 AND32ItoR(EAX, 0xff);
1001 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1002 } else if (IsConst(_Rt_)) {
1003 iRegs[_Rd_].state = ST_UNK;
1004
1005 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1006 CMP32ItoR(EAX, iRegs[_Rt_].k);
1007 SETL8R (EAX);
1008 AND32ItoR(EAX, 0xff);
1009 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1010 } else {
1011 iRegs[_Rd_].state = ST_UNK;
1012
1013 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1014 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1015 SETL8R (EAX);
1016 AND32ItoR(EAX, 0xff);
1017 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1018 }
1019}
1020
1021static void recSLTU() {
1022// Rd = Rs < Rt (unsigned)
1023 if (!_Rd_) return;
1024
1025// iFlushRegs();
1026
1027 if (IsConst(_Rs_) && IsConst(_Rt_)) {
1028 MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k);
1029 } else if (IsConst(_Rs_)) {
1030 iRegs[_Rd_].state = ST_UNK;
1031
1032 MOV32ItoR(EAX, iRegs[_Rs_].k);
1033 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1034 SBB32RtoR(EAX, EAX);
1035 NEG32R (EAX);
1036 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1037 } else if (IsConst(_Rt_)) {
1038 iRegs[_Rd_].state = ST_UNK;
1039
1040 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1041 CMP32ItoR(EAX, iRegs[_Rt_].k);
1042 SBB32RtoR(EAX, EAX);
1043 NEG32R (EAX);
1044 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1045 } else {
1046 iRegs[_Rd_].state = ST_UNK;
1047
1048 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1049 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1050 SBB32RtoR(EAX, EAX);
1051 NEG32R (EAX);
1052 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1053 }
1054}
1055#endif
1056//End of * Register arithmetic
1057
1058/*********************************************************
1059* Register mult/div & Register trap logic *
1060* Format: OP rs, rt *
1061*********************************************************/
1062
1063#if 0
1064REC_FUNC(MULT);
1065REC_FUNC(MULTU);
1066REC_FUNC(DIV);
1067REC_FUNC(DIVU);
1068#endif
1069
1070#if 1
1071static void recMULT() {
1072// Lo/Hi = Rs * Rt (signed)
1073
1074// iFlushRegs();
1075
1076 if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
1077 (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
1078 XOR32RtoR(EAX, EAX);
1079 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1080 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
1081 return;
1082 }
1083
1084 if (IsConst(_Rs_)) {
1085 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k);
1086 } else {
1087 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1088 }
1089 if (IsConst(_Rt_)) {
1090 MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k);
1091 IMUL32R (EDX);
1092 } else {
1093 IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]);
1094 }
1095 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1096 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1097}
1098
1099static void recMULTU() {
1100// Lo/Hi = Rs * Rt (unsigned)
1101
1102// iFlushRegs();
1103
1104 if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
1105 (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
1106 XOR32RtoR(EAX, EAX);
1107 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1108 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
1109 return;
1110 }
1111
1112 if (IsConst(_Rs_)) {
1113 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k);
1114 } else {
1115 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1116 }
1117 if (IsConst(_Rt_)) {
1118 MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k);
1119 MUL32R (EDX);
1120 } else {
1121 MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]);
1122 }
1123 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1124 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1125}
1126
1127static void recDIV() {
1128// Lo/Hi = Rs / Rt (signed)
1129
1130// iFlushRegs();
1131
1132 if (IsConst(_Rt_)) {
1133 if (iRegs[_Rt_].k == 0) return;
1134 MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k);
1135 } else {
1136 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1137 CMP32ItoR(ECX, 0);
1138 j8Ptr[0] = JE8(0);
1139 }
1140 if (IsConst(_Rs_)) {
1141 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k);
1142 } else {
1143 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1144 }
1145 CDQ();
1146 IDIV32R (ECX);
1147 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1148 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1149 if (!IsConst(_Rt_)) {
1150 x86SetJ8(j8Ptr[0]);
1151 }
1152}
1153
1154static void recDIVU() {
1155// Lo/Hi = Rs / Rt (unsigned)
1156
1157// iFlushRegs();
1158
1159 if (IsConst(_Rt_)) {
1160 if (iRegs[_Rt_].k == 0) return;
1161 MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k);
1162 } else {
1163 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1164 CMP32ItoR(ECX, 0);
1165 j8Ptr[0] = JE8(0);
1166 }
1167 if (IsConst(_Rs_)) {
1168 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k);
1169 } else {
1170 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1171 }
1172 XOR32RtoR(EDX, EDX);
1173 DIV32R (ECX);
1174 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1175 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1176 if (!IsConst(_Rt_)) {
1177 x86SetJ8(j8Ptr[0]);
1178 }
1179}
1180#endif
1181//End of * Register mult/div & Register trap logic
1182
1183#if 0
1184REC_FUNC(LB);
1185REC_FUNC(LBU);
1186REC_FUNC(LH);
1187REC_FUNC(LHU);
1188REC_FUNC(LW);
1189
1190REC_FUNC(SB);
1191REC_FUNC(SH);
1192REC_FUNC(SW);
1193
1194REC_FUNC(LWL);
1195REC_FUNC(LWR);
1196REC_FUNC(SWL);
1197REC_FUNC(SWR);
1198#endif
1199
1200
1201static void SetArg_OfB(x86IntRegType arg) {
1202 if (IsConst(_Rs_))
1203#ifdef __x86_64__
1204 MOV64ItoR(arg, iRegs[_Rs_].k + _Imm_);
1205#else
1206 PUSH32I (iRegs[_Rs_].k + _Imm_);
1207#endif
1208 else {
1209#ifdef __x86_64__
1210 MOV32MtoR(arg, (uptr)&psxRegs.GPR.r[_Rs_]);
1211 if (_Imm_)
1212 ADD32ItoR(arg, _Imm_);
1213#else
1214 if (_Imm_) {
1215 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
1216 ADD32ItoR(EAX, _Imm_);
1217 PUSH32R (EAX);
1218 } else {
1219 PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]);
1220 }
1221#endif
1222 }
1223#ifndef __x86_64__
1224 resp += 4;
1225#endif
1226}
1227
1228#if 1
1229static void recLB() {
1230// Rt = mem[Rs + Im] (signed)
1231
1232// iFlushRegs();
1233
1234 if (IsConst(_Rs_)) {
1235 u32 addr = iRegs[_Rs_].k + _Imm_;
1236 int t = addr >> 16;
1237
1238 if ((t & 0xfff0) == 0xbfc0) {
1239 if (!_Rt_) return;
1240 // since bios is readonly it won't change
1241 MapConst(_Rt_, psxRs8(addr));
1242 return;
1243 }
1244 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1245 if (!_Rt_) return;
1246 iRegs[_Rt_].state = ST_UNK;
1247
1248 MOVSX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1249 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1250 return;
1251 }
1252 if (t == 0x1f80 && addr < 0x1f801000) {
1253 if (!_Rt_) return;
1254 iRegs[_Rt_].state = ST_UNK;
1255
1256 MOVSX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]);
1257 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1258 return;
1259 }
1260// SysPrintf("unhandled r8 %x\n", addr);
1261 }
1262
1263 SetArg_OfB(X86ARG1);
1264 CALLFunc((uptr)psxMemRead8);
1265 if (_Rt_) {
1266 iRegs[_Rt_].state = ST_UNK;
1267 MOVSX32R8toR(EAX, EAX);
1268 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1269 }
1270// ADD32ItoR(ESP, 4);
1271}
1272
1273static void recLBU() {
1274// Rt = mem[Rs + Im] (unsigned)
1275
1276// iFlushRegs();
1277
1278 if (IsConst(_Rs_)) {
1279 u32 addr = iRegs[_Rs_].k + _Imm_;
1280 int t = addr >> 16;
1281
1282 if ((t & 0xfff0) == 0xbfc0) {
1283 if (!_Rt_) return;
1284 // since bios is readonly it won't change
1285 MapConst(_Rt_, psxRu8(addr));
1286 return;
1287 }
1288 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1289 if (!_Rt_) return;
1290 iRegs[_Rt_].state = ST_UNK;
1291
1292 MOVZX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1293 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1294 return;
1295 }
1296 if (t == 0x1f80 && addr < 0x1f801000) {
1297 if (!_Rt_) return;
1298 iRegs[_Rt_].state = ST_UNK;
1299
1300 MOVZX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]);
1301 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1302 return;
1303 }
1304// SysPrintf("unhandled r8u %x\n", addr);
1305 }
1306
1307 SetArg_OfB(X86ARG1);
1308 CALLFunc((uptr)psxMemRead8);
1309 if (_Rt_) {
1310 iRegs[_Rt_].state = ST_UNK;
1311 MOVZX32R8toR(EAX, EAX);
1312 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1313 }
1314// ADD32ItoR(ESP, 4);
1315}
1316
1317static void recLH() {
1318// Rt = mem[Rs + Im] (signed)
1319
1320// iFlushRegs();
1321
1322 if (IsConst(_Rs_)) {
1323 u32 addr = iRegs[_Rs_].k + _Imm_;
1324 int t = addr >> 16;
1325
1326 if ((t & 0xfff0) == 0xbfc0) {
1327 if (!_Rt_) return;
1328 // since bios is readonly it won't change
1329 MapConst(_Rt_, psxRs16(addr));
1330 return;
1331 }
1332 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1333 if (!_Rt_) return;
1334 iRegs[_Rt_].state = ST_UNK;
1335
1336 MOVSX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1337 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1338 return;
1339 }
1340 if (t == 0x1f80 && addr < 0x1f801000) {
1341 if (!_Rt_) return;
1342 iRegs[_Rt_].state = ST_UNK;
1343
1344 MOVSX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]);
1345 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1346 return;
1347 }
1348// SysPrintf("unhandled r16 %x\n", addr);
1349 }
1350
1351 SetArg_OfB(X86ARG1);
1352 CALLFunc((uptr)psxMemRead16);
1353 if (_Rt_) {
1354 iRegs[_Rt_].state = ST_UNK;
1355 MOVSX32R16toR(EAX, EAX);
1356 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1357 }
1358// ADD32ItoR(ESP, 4);
1359}
1360
1361static void recLHU() {
1362// Rt = mem[Rs + Im] (unsigned)
1363
1364// iFlushRegs();
1365
1366 if (IsConst(_Rs_)) {
1367 u32 addr = iRegs[_Rs_].k + _Imm_;
1368 int t = addr >> 16;
1369
1370 if ((t & 0xfff0) == 0xbfc0) {
1371 if (!_Rt_) return;
1372 // since bios is readonly it won't change
1373 MapConst(_Rt_, psxRu16(addr));
1374 return;
1375 }
1376 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1377 if (!_Rt_) return;
1378 iRegs[_Rt_].state = ST_UNK;
1379
1380 MOVZX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1381 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1382 return;
1383 }
1384 if (t == 0x1f80 && addr < 0x1f801000) {
1385 if (!_Rt_) return;
1386 iRegs[_Rt_].state = ST_UNK;
1387
1388 MOVZX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]);
1389 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1390 return;
1391 }
1392 if (t == 0x1f80) {
1393 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
1394 if (!_Rt_) return;
1395 iRegs[_Rt_].state = ST_UNK;
1396
1397 //PUSHI (addr);
1398 MOV64ItoR(X86ARG1, addr);
1399 //CALLFunc ((uptr)SPU_readRegister);
1400 MOV64ItoR(RAX, (uptr)SPU_readRegister);
1401 CALL64R(RAX);
1402 MOVZX32R16toR(EAX, EAX);
1403 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1404#ifndef __WIN32__
1405 resp+= 4;
1406#endif
1407 return;
1408 }
1409 switch (addr) {
1410 case 0x1f801100: case 0x1f801110: case 0x1f801120:
1411 if (!_Rt_) return;
1412 iRegs[_Rt_].state = ST_UNK;
1413
1414 //PUSHI((addr >> 4) & 0x3);
1415 MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
1416 CALLFunc((uptr)psxRcntRcount);
1417 MOVZX32R16toR(EAX, EAX);
1418 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1419 resp+= 4;
1420 return;
1421
1422 case 0x1f801104: case 0x1f801114: case 0x1f801124:
1423 if (!_Rt_) return;
1424 iRegs[_Rt_].state = ST_UNK;
1425
1426 MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
1427 CALLFunc((uptr)psxRcntRmode);
1428 MOVZX32R16toR(EAX, EAX);
1429 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1430 resp+= 4;
1431 return;
1432
1433 case 0x1f801108: case 0x1f801118: case 0x1f801128:
1434 if (!_Rt_) return;
1435 iRegs[_Rt_].state = ST_UNK;
1436
1437 MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
1438 CALLFunc((uptr)psxRcntRtarget);
1439 MOVZX32R16toR(EAX, EAX);
1440 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1441 resp+= 4;
1442 return;
1443 }
1444 }
1445// SysPrintf("unhandled r16u %x\n", addr);
1446 }
1447
1448 SetArg_OfB(X86ARG1);
1449 CALLFunc((uptr)psxMemRead16);
1450 if (_Rt_) {
1451 iRegs[_Rt_].state = ST_UNK;
1452 MOVZX32R16toR(EAX, EAX);
1453 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1454 }
1455// ADD32ItoR(ESP, 4);
1456}
1457
1458static void recLW() {
1459// Rt = mem[Rs + Im] (unsigned)
1460
1461// iFlushRegs();
1462
1463 if (IsConst(_Rs_)) {
1464 u32 addr = iRegs[_Rs_].k + _Imm_;
1465 int t = addr >> 16;
1466
1467 if ((t & 0xfff0) == 0xbfc0) {
1468 if (!_Rt_) return;
1469 // since bios is readonly it won't change
1470 MapConst(_Rt_, psxRu32(addr));
1471 return;
1472 }
1473 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1474 if (!_Rt_) return;
1475 iRegs[_Rt_].state = ST_UNK;
1476
1477 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1478 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1479 return;
1480 }
1481 if (t == 0x1f80 && addr < 0x1f801000) {
1482 if (!_Rt_) return;
1483 iRegs[_Rt_].state = ST_UNK;
1484
1485 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
1486 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1487 return;
1488 }
1489 if (t == 0x1f80) {
1490 switch (addr) {
1491 case 0x1f801080: case 0x1f801084: case 0x1f801088:
1492 case 0x1f801090: case 0x1f801094: case 0x1f801098:
1493 case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8:
1494 case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8:
1495 case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8:
1496 case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8:
1497 case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8:
1498 case 0x1f801070: case 0x1f801074:
1499 case 0x1f8010f0: case 0x1f8010f4:
1500 if (!_Rt_) return;
1501 iRegs[_Rt_].state = ST_UNK;
1502
1503 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffff]);
1504 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1505 return;
1506
1507 case 0x1f801810:
1508 if (!_Rt_) return;
1509 iRegs[_Rt_].state = ST_UNK;
1510
1511 CALLFunc((uptr)GPU_readData);
1512 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1513 return;
1514
1515 case 0x1f801814:
1516 if (!_Rt_) return;
1517 iRegs[_Rt_].state = ST_UNK;
1518
1519 CALLFunc((uptr)GPU_readStatus);
1520 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1521 return;
1522 }
1523 }
1524// SysPrintf("unhandled r32 %x\n", addr);
1525 }
1526
1527 SetArg_OfB(X86ARG1);
1528 CALLFunc((uptr)psxMemRead32);
1529 if (_Rt_) {
1530 iRegs[_Rt_].state = ST_UNK;
1531 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1532 }
1533// ADD32ItoR(ESP, 4);
1534}
1535
1536extern u32 LWL_MASK[4];
1537extern u32 LWL_SHIFT[4];
1538
1539void iLWLk(u32 shift) {
1540 if (IsConst(_Rt_)) {
1541 MOV32ItoR(ECX, iRegs[_Rt_].k);
1542 } else {
1543 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1544 }
1545 AND32ItoR(ECX, LWL_MASK[shift]);
1546 SHL32ItoR(EAX, LWL_SHIFT[shift]);
1547 OR32RtoR (EAX, ECX);
1548}
1549
1550void recLWL() {
1551// Rt = Rt Merge mem[Rs + Im]
1552
1553 if (IsConst(_Rs_)) {
1554 u32 addr = iRegs[_Rs_].k + _Imm_;
1555 int t = addr >> 16;
1556
1557 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1558 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
1559 iLWLk(addr & 3);
1560
1561 iRegs[_Rt_].state = ST_UNK;
1562 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1563 return;
1564 }
1565 if (t == 0x1f80 && addr < 0x1f801000) {
1566 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
1567 iLWLk(addr & 3);
1568
1569 iRegs[_Rt_].state = ST_UNK;
1570 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1571 return;
1572 }
1573 }
1574
1575 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
1576 else {
1577 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1578 if (_Imm_) ADD32ItoR(EAX, _Imm_);
1579 }
1580 //PUSH64R (EAX);
1581 AND32ItoR(EAX, ~3);
1582 //PUSH64R (EAX);
1583 MOV32RtoR(X86ARG1, EAX);
1584 CALLFunc((uptr)psxMemRead32);
1585
1586 if (_Rt_) {
1587 //ADD32ItoR(ESP, 4);
1588 //POP64R (EDX);
1589 if (IsConst(_Rs_)) MOV32ItoR(EDX, iRegs[_Rs_].k + _Imm_);
1590 else {
1591 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rs_]);
1592 if (_Imm_) ADD32ItoR(EDX, _Imm_);
1593 }
1594
1595 AND32ItoR(EDX, 0x3); // shift = addr & 3;
1596
1597 MOV64ItoR(ECX, (uptr)LWL_SHIFT);
1598 MOV32RmStoR(ECX, ECX, EDX, 2);
1599 SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
1600
1601 MOV64ItoR(ECX, (uptr)LWL_MASK);
1602 MOV32RmStoR(ECX, ECX, EDX, 2);
1603 if (IsConst(_Rt_)) {
1604 MOV32ItoR(EDX, iRegs[_Rt_].k);
1605 } else {
1606 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
1607 }
1608 AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
1609
1610 OR32RtoR(EAX, EDX);
1611
1612 iRegs[_Rt_].state = ST_UNK;
1613 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1614 //} else {
1615 //ADD64ItoR(RSP, 8);
1616 //resp+= 8;
1617 }
1618}
1619
1620/*
1621static void recLWBlock(int count) {
1622 u32 *code = PSXM(pc);
1623 int i, respsave;
1624// Rt = mem[Rs + Im] (unsigned)
1625
1626// iFlushRegs();
1627
1628 if (IsConst(_Rs_)) {
1629 u32 addr = iRegs[_Rs_].k + _Imm_;
1630 int t = addr >> 16;
1631
1632 if ((t & 0xfff0) == 0xbfc0) {
1633 // since bios is readonly it won't change
1634 for (i=0; i<count; i++, code++, addr+=4) {
1635 if (_fRt_(*code)) {
1636 MapConst(_fRt_(*code), psxRu32(addr));
1637 }
1638 }
1639 return;
1640 }
1641 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1642 for (i=0; i<count; i++, code++, addr+=4) {
1643 if (!_fRt_(*code)) return;
1644 iRegs[_fRt_(*code)].state = ST_UNK;
1645
1646 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1647 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
1648 }
1649 return;
1650 }
1651 if (t == 0x1f80 && addr < 0x1f801000) {
1652 for (i=0; i<count; i++, code++, addr+=4) {
1653 if (!_fRt_(*code)) return;
1654 iRegs[_fRt_(*code)].state = ST_UNK;
1655
1656 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
1657 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
1658 }
1659 return;
1660 }
1661 }
1662
1663 SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
1664 SetArg_OfB(X86ARG1);
1665 CALLFunc((uptr)psxMemPointer);
1666// ADD32ItoR(ESP, 4);
1667
1668 respsave = resp; resp = 0;
1669 TEST64RtoR(RAX,RAX);
1670 j32Ptr[4] = JZ32(0);
1671 XOR32RtoR(ECX, ECX);
1672 for (i=0; i<count; i++, code++) {
1673 if (_fRt_(*code)) {
1674 iRegs[_fRt_(*code)].state = ST_UNK;
1675
1676 MOV64RmStoR(EDX, EAX, ECX, 2);
1677 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EDX);
1678 }
1679 if (i != (count-1)) INC32R(ECX);
1680 }
1681 j32Ptr[5] = JMP32(0);
1682 x86SetJ32(j32Ptr[4]);
1683 for (i=0, code = PSXM(pc); i<count; i++, code++) {
1684 psxRegs.code = *code;
1685 recLW();
1686 }
1687#ifndef __x86_64__
1688 ADD32ItoR(ESP, resp);
1689#endif
1690 x86SetJ32(j32Ptr[5]);
1691 resp = respsave;
1692}
1693*/
1694
1695extern u32 LWR_MASK[4];
1696extern u32 LWR_SHIFT[4];
1697
1698void iLWRk(u32 shift) {
1699 if (IsConst(_Rt_)) {
1700 MOV32ItoR(ECX, iRegs[_Rt_].k);
1701 } else {
1702 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1703 }
1704 AND32ItoR(ECX, LWR_MASK[shift]);
1705 SHR32ItoR(EAX, LWR_SHIFT[shift]);
1706 OR32RtoR (EAX, ECX);
1707}
1708
1709void recLWR() {
1710// Rt = Rt Merge mem[Rs + Im]
1711
1712 if (IsConst(_Rs_)) {
1713 u32 addr = iRegs[_Rs_].k + _Imm_;
1714 int t = addr >> 16;
1715
1716 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1717 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
1718 iLWRk(addr & 3);
1719
1720 iRegs[_Rt_].state = ST_UNK;
1721 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1722 return;
1723 }
1724 if (t == 0x1f80 && addr < 0x1f801000) {
1725 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
1726 iLWRk(addr & 3);
1727
1728 iRegs[_Rt_].state = ST_UNK;
1729 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1730 return;
1731 }
1732 }
1733
1734 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
1735 else {
1736 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1737 if (_Imm_) ADD32ItoR(EAX, _Imm_);
1738 }
1739 PUSHR(EAX);
1740 AND32ItoR(EAX, ~3);
1741 MOV32RtoR(X86ARG1, EAX);
1742 CALLFunc((uptr)psxMemRead32);
1743
1744 POPR (EDX);
1745 if (_Rt_) {
1746 AND32ItoR(EDX, 0x3); // shift = addr & 3;
1747
1748 MOV64ItoR(ECX, (uptr)LWR_SHIFT);
1749 MOV32RmStoR(ECX, ECX, EDX, 2);
1750 SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
1751
1752 MOV64ItoR(ECX, (uptr)LWR_MASK);
1753 MOV32RmStoR(ECX, ECX, EDX, 2);
1754
1755 if (IsConst(_Rt_)) {
1756 MOV32ItoR(EDX, iRegs[_Rt_].k);
1757 } else {
1758 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
1759 }
1760 AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
1761
1762 OR32RtoR(EAX, EDX);
1763
1764 iRegs[_Rt_].state = ST_UNK;
1765 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1766 //} else {
1767 //resp+= 8;
1768 }
1769}
1770
1771static void recSB() {
1772// mem[Rs + Im] = Rt
1773
1774// iFlushRegs();
1775
1776 if (IsConst(_Rs_)) {
1777 u32 addr = iRegs[_Rs_].k + _Imm_;
1778 int t = addr >> 16;
1779
1780 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1781 if (IsConst(_Rt_)) {
1782 MOV8ItoM((uptr)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
1783 } else {
1784 MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1785 MOV8RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
1786 }
1787 return;
1788 }
1789 if (t == 0x1f80 && addr < 0x1f801000) {
1790 if (IsConst(_Rt_)) {
1791 MOV8ItoM((uptr)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
1792 } else {
1793 MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1794 MOV8RtoM((uptr)&psxH[addr & 0xfff], EAX);
1795 }
1796 return;
1797 }
1798// SysPrintf("unhandled w8 %x\n", addr);
1799 }
1800
1801 if (IsConst(_Rt_)) {
1802 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1803 } else {
1804 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1805 }
1806 SetArg_OfB(X86ARG1);
1807 CALLFunc((uptr)psxMemWrite8);
1808// ADD32ItoR(ESP, 8);
1809}
1810
1811static void recSH() {
1812// mem[Rs + Im] = Rt
1813
1814// iFlushRegs();
1815
1816 if (IsConst(_Rs_)) {
1817 u32 addr = iRegs[_Rs_].k + _Imm_;
1818 int t = addr >> 16;
1819
1820 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1821 if (IsConst(_Rt_)) {
1822 MOV16ItoM((uptr)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
1823 } else {
1824 MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1825 MOV16RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
1826 }
1827 return;
1828 }
1829 if (t == 0x1f80 && addr < 0x1f801000) {
1830 if (IsConst(_Rt_)) {
1831 MOV16ItoM((uptr)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
1832 } else {
1833 MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1834 MOV16RtoM((uptr)&psxH[addr & 0xfff], EAX);
1835 }
1836 return;
1837 }
1838 if (t == 0x1f80) {
1839 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
1840 if (IsConst(_Rt_)) {
1841 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1842 } else {
1843 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1844 }
1845 MOV64ItoR(X86ARG1, addr);
1846 CALLFunc ((uptr)SPU_writeRegister);
1847#ifndef __WIN32__
1848 //resp+= 8;
1849#endif
1850 return;
1851 }
1852 }
1853// SysPrintf("unhandled w16 %x\n", addr);
1854 }
1855
1856 if (IsConst(_Rt_)) {
1857 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1858 } else {
1859 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1860 }
1861 SetArg_OfB(X86ARG1);
1862 CALLFunc((uptr)psxMemWrite16);
1863// ADD32ItoR(ESP, 8);
1864}
1865
1866static void recSW() {
1867// mem[Rs + Im] = Rt
1868
1869// iFlushRegs();
1870
1871 if (IsConst(_Rs_)) {
1872 u32 addr = iRegs[_Rs_].k + _Imm_;
1873 int t = addr >> 16;
1874
1875 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1876 if (IsConst(_Rt_)) {
1877 MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_Rt_].k);
1878 } else {
1879 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1880 MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
1881 }
1882 return;
1883 }
1884 if (t == 0x1f80 && addr < 0x1f801000) {
1885 if (IsConst(_Rt_)) {
1886 MOV32ItoM((uptr)&psxH[addr & 0xfff], iRegs[_Rt_].k);
1887 } else {
1888 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1889 MOV32RtoM((uptr)&psxH[addr & 0xfff], EAX);
1890 }
1891 return;
1892 }
1893 if (t == 0x1f80) {
1894 switch (addr) {
1895 case 0x1f801080: case 0x1f801084:
1896 case 0x1f801090: case 0x1f801094:
1897 case 0x1f8010a0: case 0x1f8010a4:
1898 case 0x1f8010b0: case 0x1f8010b4:
1899 case 0x1f8010c0: case 0x1f8010c4:
1900 case 0x1f8010d0: case 0x1f8010d4:
1901 case 0x1f8010e0: case 0x1f8010e4:
1902 case 0x1f801074:
1903 case 0x1f8010f0:
1904 if (IsConst(_Rt_)) {
1905 MOV32ItoM((uptr)&psxH[addr & 0xffff], iRegs[_Rt_].k);
1906 } else {
1907 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1908 MOV32RtoM((uptr)&psxH[addr & 0xffff], EAX);
1909 }
1910 return;
1911
1912 case 0x1f801810:
1913 if (IsConst(_Rt_)) {
1914 MOV64ItoR(X86ARG1, iRegs[_Rt_].k);
1915 } else {
1916 MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]);
1917 }
1918 CALLFunc((uptr)GPU_writeData);
1919#ifndef __WIN32__
1920 //resp+= 4;
1921#endif
1922 return;
1923
1924 case 0x1f801814:
1925 if (IsConst(_Rt_)) {
1926 MOV64ItoR(X86ARG1, iRegs[_Rt_].k);
1927 } else {
1928 MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]);
1929 }
1930 CALLFunc((uptr)GPU_writeStatus);
1931#ifndef __WIN32__
1932 //resp+= 4;
1933#endif
1934 }
1935 }
1936// SysPrintf("unhandled w32 %x\n", addr);
1937 }
1938
1939 if (IsConst(_Rt_)) {
1940 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1941 } else {
1942 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1943 }
1944 SetArg_OfB(X86ARG1);
1945 CALLFunc((uptr)psxMemWrite32);
1946// ADD32ItoR(ESP, 8);
1947 //resp+= 8;
1948}
1949
1950/*
1951static void recSWBlock(int count) {
1952 u32 *code;
1953 int i, respsave;
1954// mem[Rs + Im] = Rt
1955
1956// iFlushRegs();
1957
1958 if (IsConst(_Rs_)) {
1959 u32 addr = iRegs[_Rs_].k + _Imm_;
1960 int t = addr >> 16;
1961 code = PSXM(pc);
1962
1963 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1964 for (i=0; i<count; i++, code++, addr+=4) {
1965 if (IsConst(_fRt_(*code))) {
1966 MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k);
1967 } else {
1968 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]);
1969 MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
1970 }
1971 }
1972 return;
1973 }
1974 if (t == 0x1f80 && addr < 0x1f801000) {
1975 for (i=0; i<count; i++, code++, addr+=4) {
1976 if (!_fRt_(*code)) return;
1977 iRegs[_fRt_(*code)].state = ST_UNK;
1978
1979 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
1980 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
1981 }
1982 return;
1983 }
1984 }
1985
1986 SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
1987 SetArg_OfB(X86ARG1);
1988 CALLFunc((uptr)psxMemPointer);
1989// ADD32ItoR(ESP, 4);
1990 //resp+= 4;
1991
1992 respsave = resp; resp = 0;
1993 TEST64RtoR(RAX,RAX);
1994 j32Ptr[4] = JZ32(0);
1995 XOR32RtoR(ECX, ECX);
1996 for (i=0, code = PSXM(pc); i<count; i++, code++) {
1997 if (IsConst(_fRt_(*code))) {
1998 MOV32ItoR(EDX, iRegs[_fRt_(*code)].k);
1999 } else {
2000 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]);
2001 }
2002 MOV32RtoRmS(EAX, ECX, 2, EDX);
2003 if (i != (count-1)) INC32R(ECX);
2004 }
2005 j32Ptr[5] = JMP32(0);
2006 x86SetJ32(j32Ptr[4]);
2007 for (i=0, code = PSXM(pc); i<count; i++, code++) {
2008 psxRegs.code = *code;
2009 recSW();
2010 }
2011 //ADD32ItoR(ESP, resp);
2012 x86SetJ32(j32Ptr[5]);
2013 resp = respsave;
2014}
2015*/
2016
2017extern u32 SWL_MASK[4];
2018extern u32 SWL_SHIFT[4];
2019
2020void iSWLk(u32 shift) {
2021 if (IsConst(_Rt_)) {
2022 MOV32ItoR(ECX, iRegs[_Rt_].k);
2023 } else {
2024 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
2025 }
2026 SHR32ItoR(ECX, SWL_SHIFT[shift]);
2027 AND32ItoR(EAX, SWL_MASK[shift]);
2028 OR32RtoR (EAX, ECX);
2029}
2030
2031void recSWL() {
2032// mem[Rs + Im] = Rt Merge mem[Rs + Im]
2033
2034 if (IsConst(_Rs_)) {
2035 u32 addr = iRegs[_Rs_].k + _Imm_;
2036 int t = addr >> 16;
2037
2038 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2039 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
2040 iSWLk(addr & 3);
2041 MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX);
2042 return;
2043 }
2044 if (t == 0x1f80 && addr < 0x1f801000) {
2045 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
2046 iSWLk(addr & 3);
2047 MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX);
2048 return;
2049 }
2050 }
2051
2052 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2053 else {
2054 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2055 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2056 }
2057 PUSHR (EAX);
2058 AND32ItoR(EAX, ~3);
2059 MOV32RtoR(X86ARG1, EAX);
2060
2061 CALLFunc((uptr)psxMemRead32);
2062
2063 POPR (EDX);
2064 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2065
2066 MOV64ItoR(ECX, (uptr)SWL_MASK);
2067 MOV32RmStoR(ECX, ECX, EDX, 2);
2068 AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
2069
2070 MOV64ItoR(ECX, (uptr)SWL_SHIFT);
2071 MOV32RmStoR(ECX, ECX, EDX, 2);
2072 if (IsConst(_Rt_)) {
2073 MOV32ItoR(EDX, iRegs[_Rt_].k);
2074 } else {
2075 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
2076 }
2077 SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
2078
2079 OR32RtoR (EAX, EDX);
2080 MOV32RtoR(X86ARG2, EAX);
2081
2082 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2083 else {
2084 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2085 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2086 }
2087 AND32ItoR(EAX, ~3);
2088 MOV32RtoR(X86ARG1, EAX);
2089
2090 CALLFunc((uptr)psxMemWrite32);
2091// ADD32ItoR(ESP, 8);
2092 //resp+= 8;
2093}
2094
2095extern u32 SWR_MASK[4];
2096extern u32 SWR_SHIFT[4];
2097
2098void iSWRk(u32 shift) {
2099 if (IsConst(_Rt_)) {
2100 MOV32ItoR(ECX, iRegs[_Rt_].k);
2101 } else {
2102 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
2103 }
2104 SHL32ItoR(ECX, SWR_SHIFT[shift]);
2105 AND32ItoR(EAX, SWR_MASK[shift]);
2106 OR32RtoR (EAX, ECX);
2107}
2108
2109void recSWR() {
2110// mem[Rs + Im] = Rt Merge mem[Rs + Im]
2111
2112 if (IsConst(_Rs_)) {
2113 u32 addr = iRegs[_Rs_].k + _Imm_;
2114 int t = addr >> 16;
2115
2116 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2117 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
2118 iSWRk(addr & 3);
2119 MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX);
2120 return;
2121 }
2122 if (t == 0x1f80 && addr < 0x1f801000) {
2123 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
2124 iSWRk(addr & 3);
2125 MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX);
2126 return;
2127 }
2128 }
2129
2130 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2131 else {
2132 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2133 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2134 }
2135 PUSHR (EAX);
2136
2137 AND32ItoR(EAX, ~3);
2138 MOV32RtoR(X86ARG1, EAX);
2139
2140 CALLFunc((uptr)psxMemRead32);
2141
2142 POPR (EDX);
2143 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2144
2145 MOV64ItoR(ECX, (uptr)SWR_MASK);
2146 MOV32RmStoR(ECX, ECX, EDX, 2);
2147 AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
2148
2149 MOV64ItoR(ECX, (uptr)SWR_SHIFT);
2150 MOV32RmStoR(ECX, ECX, EDX, 2);
2151 if (IsConst(_Rt_)) {
2152 MOV32ItoR(EDX, iRegs[_Rt_].k);
2153 } else {
2154 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
2155 }
2156 SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
2157
2158 OR32RtoR (EAX, EDX);
2159 MOV32RtoR(X86ARG2, EAX);
2160
2161 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2162 else {
2163 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2164 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2165 }
2166 AND32ItoR(EAX, ~3);
2167 MOV32RtoR(X86ARG1, EAX);
2168 CALLFunc((uptr)psxMemWrite32);
2169// ADD32ItoR(ESP, 8);
2170 //resp+= 8;
2171}
2172
2173#endif
2174
2175#if 0
2176REC_FUNC(SLL);
2177REC_FUNC(SRL);
2178REC_FUNC(SRA);
2179#endif
2180#if 1
2181static void recSLL() {
2182// Rd = Rt << Sa
2183 if (!_Rd_) return;
2184
2185// iFlushRegs();
2186
2187 if (IsConst(_Rt_)) {
2188 MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
2189 } else {
2190 iRegs[_Rd_].state = ST_UNK;
2191
2192 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2193 if (_Sa_) SHL32ItoR(EAX, _Sa_);
2194 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2195 }
2196}
2197
2198static void recSRL() {
2199// Rd = Rt >> Sa
2200 if (!_Rd_) return;
2201
2202// iFlushRegs();
2203
2204 if (IsConst(_Rt_)) {
2205 MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
2206 } else {
2207 iRegs[_Rd_].state = ST_UNK;
2208
2209 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2210 if (_Sa_) SHR32ItoR(EAX, _Sa_);
2211 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2212 }
2213}
2214
2215static void recSRA() {
2216// Rd = Rt >> Sa
2217 if (!_Rd_) return;
2218
2219// iFlushRegs();
2220
2221 if (IsConst(_Rt_)) {
2222 MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
2223 } else {
2224 iRegs[_Rd_].state = ST_UNK;
2225
2226 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2227 if (_Sa_) SAR32ItoR(EAX, _Sa_);
2228 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2229 }
2230}
2231#endif
2232
2233#if 0
2234REC_FUNC(SLLV);
2235REC_FUNC(SRLV);
2236REC_FUNC(SRAV);
2237#endif
2238
2239#if 1
2240static void recSLLV() {
2241// Rd = Rt << Rs
2242 if (!_Rd_) return;
2243
2244// iFlushRegs();
2245
2246 if (IsConst(_Rt_) && IsConst(_Rs_)) {
2247 MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k);
2248 } else if (IsConst(_Rs_)) {
2249 iRegs[_Rd_].state = ST_UNK;
2250
2251 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2252 MOV32ItoR(ECX, iRegs[_Rs_].k);
2253 SHL32CLtoR(EAX);
2254 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2255 } else if (IsConst(_Rt_)) {
2256 iRegs[_Rd_].state = ST_UNK;
2257
2258 MOV32ItoR(EAX, iRegs[_Rt_].k);
2259 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2260 SHL32CLtoR(EAX);
2261 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2262 } else {
2263 iRegs[_Rd_].state = ST_UNK;
2264
2265 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2266 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2267 SHL32CLtoR(EAX);
2268 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2269 }
2270}
2271
2272static void recSRLV() {
2273// Rd = Rt >> Rs
2274 if (!_Rd_) return;
2275
2276// iFlushRegs();
2277
2278 if (IsConst(_Rt_) && IsConst(_Rs_)) {
2279 MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k);
2280 } else if (IsConst(_Rs_)) {
2281 iRegs[_Rd_].state = ST_UNK;
2282
2283 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2284 MOV32ItoR(ECX, iRegs[_Rs_].k);
2285 SHR32CLtoR(EAX);
2286 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2287 } else if (IsConst(_Rt_)) {
2288 iRegs[_Rd_].state = ST_UNK;
2289
2290 MOV32ItoR(EAX, iRegs[_Rt_].k);
2291 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2292 SHR32CLtoR(EAX);
2293 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2294 } else {
2295 iRegs[_Rd_].state = ST_UNK;
2296
2297 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2298 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2299 SHR32CLtoR(EAX);
2300 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2301 }
2302}
2303
2304static void recSRAV() {
2305// Rd = Rt >> Rs
2306 if (!_Rd_) return;
2307
2308// iFlushRegs();
2309
2310 if (IsConst(_Rt_) && IsConst(_Rs_)) {
2311 MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k);
2312 } else if (IsConst(_Rs_)) {
2313 iRegs[_Rd_].state = ST_UNK;
2314
2315 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2316 MOV32ItoR(ECX, iRegs[_Rs_].k);
2317 SAR32CLtoR(EAX);
2318 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2319 } else if (IsConst(_Rt_)) {
2320 iRegs[_Rd_].state = ST_UNK;
2321
2322 MOV32ItoR(EAX, iRegs[_Rt_].k);
2323 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2324 SAR32CLtoR(EAX);
2325 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2326 } else {
2327 iRegs[_Rd_].state = ST_UNK;
2328
2329 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2330 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2331 SAR32CLtoR(EAX);
2332 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2333 }
2334}
2335#endif
2336
2337#if 0
2338REC_SYS(SYSCALL);
2339REC_SYS(BREAK);
2340#endif
2341
2342int dump = 0;
2343
2344#if 1
2345static void recSYSCALL() {
2346// dump=1;
2347 iFlushRegs();
2348
2349 MOV32ItoR(EAX, pc - 4);
2350 MOV32RtoM((uptr)&psxRegs.pc, EAX);
2351 MOV64ItoR(X86ARG2, branch == 1 ? 1 : 0);
2352 MOV64ItoR(X86ARG1, 0x20);
2353 CALLFunc((uptr)psxException);
2354 //ADD32ItoR(ESP, 8);
2355
2356 branch = 2;
2357 iRet();
2358}
2359
2360static void recBREAK() {
2361}
2362#endif
2363
2364#if 0
2365REC_FUNC(MFHI);
2366REC_FUNC(MTHI);
2367REC_FUNC(MFLO);
2368REC_FUNC(MTLO);
2369#endif
2370#if 1
2371static void recMFHI() {
2372// Rd = Hi
2373 if (!_Rd_) return;
2374
2375 iRegs[_Rd_].state = ST_UNK;
2376 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi);
2377 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2378}
2379
2380static void recMTHI() {
2381// Hi = Rs
2382
2383 if (IsConst(_Rs_)) {
2384 MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
2385 } else {
2386 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2387 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
2388 }
2389}
2390
2391static void recMFLO() {
2392// Rd = Lo
2393 if (!_Rd_) return;
2394
2395 iRegs[_Rd_].state = ST_UNK;
2396 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo);
2397 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2398}
2399
2400static void recMTLO() {
2401// Lo = Rs
2402
2403 if (IsConst(_Rs_)) {
2404 MOV32ItoM((uptr)&psxRegs.GPR.n.lo, iRegs[_Rs_].k);
2405 } else {
2406 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2407 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
2408 }
2409}
2410#endif
2411
2412#if 0
2413REC_BRANCH(J);
2414REC_BRANCH(JR);
2415REC_BRANCH(JAL);
2416REC_BRANCH(JALR);
2417REC_BRANCH(BLTZ);
2418REC_BRANCH(BGTZ);
2419REC_BRANCH(BLTZAL);
2420REC_BRANCH(BGEZAL);
2421REC_BRANCH(BNE);
2422REC_BRANCH(BEQ);
2423REC_BRANCH(BLEZ);
2424REC_BRANCH(BGEZ);
2425#endif
2426#if 1
2427static void recBLTZ() {
2428// Branch if Rs < 0
2429 u32 bpc = _Imm_ * 4 + pc;
2430
2431// iFlushRegs();
2432
2433 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2434 return;
2435 }
2436
2437 if (IsConst(_Rs_)) {
2438 if ((s32)iRegs[_Rs_].k < 0) {
2439 iJump(bpc); return;
2440 } else {
2441 iJump(pc+4); return;
2442 }
2443 }
2444
2445 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2446 j32Ptr[4] = JL32(0);
2447
2448 iBranch(pc+4, 1);
2449
2450 x86SetJ32(j32Ptr[4]);
2451
2452 iBranch(bpc, 0);
2453 pc+=4;
2454}
2455
2456static void recBGTZ() {
2457// Branch if Rs > 0
2458 u32 bpc = _Imm_ * 4 + pc;
2459
2460// iFlushRegs();
2461 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2462 return;
2463 }
2464
2465 if (IsConst(_Rs_)) {
2466 if ((s32)iRegs[_Rs_].k > 0) {
2467 iJump(bpc); return;
2468 } else {
2469 iJump(pc+4); return;
2470 }
2471 }
2472
2473 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2474 j32Ptr[4] = JG32(0);
2475
2476 iBranch(pc+4, 1);
2477
2478 x86SetJ32(j32Ptr[4]);
2479
2480 iBranch(bpc, 0);
2481 pc+=4;
2482}
2483
2484static void recBLTZAL() {
2485// Branch if Rs < 0
2486 u32 bpc = _Imm_ * 4 + pc;
2487
2488// iFlushRegs();
2489 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2490 return;
2491 }
2492
2493 if (IsConst(_Rs_)) {
2494 if ((s32)iRegs[_Rs_].k < 0) {
2495 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2496 iJump(bpc); return;
2497 } else {
2498 iJump(pc+4); return;
2499 }
2500 }
2501
2502 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2503 j32Ptr[4] = JL32(0);
2504
2505 iBranch(pc+4, 1);
2506
2507 x86SetJ32(j32Ptr[4]);
2508
2509 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2510 iBranch(bpc, 0);
2511 pc+=4;
2512}
2513
2514static void recBGEZAL() {
2515// Branch if Rs >= 0
2516 u32 bpc = _Imm_ * 4 + pc;
2517
2518// iFlushRegs();
2519 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2520 return;
2521 }
2522
2523 if (IsConst(_Rs_)) {
2524 if ((s32)iRegs[_Rs_].k >= 0) {
2525 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2526 iJump(bpc); return;
2527 } else {
2528 iJump(pc+4); return;
2529 }
2530 }
2531
2532 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2533 j32Ptr[4] = JGE32(0);
2534
2535 iBranch(pc+4, 1);
2536
2537 x86SetJ32(j32Ptr[4]);
2538
2539 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2540 iBranch(bpc, 0);
2541 pc+=4;
2542}
2543
2544static void recJ() {
2545// j target
2546
2547 iJump(_Target_ * 4 + (pc & 0xf0000000));
2548}
2549
2550static void recJAL() {
2551// jal target
2552
2553 MapConst(31, pc + 4);
2554
2555 iJump(_Target_ * 4 + (pc & 0xf0000000));
2556}
2557
2558static void recJR() {
2559// jr Rs
2560
2561 if (IsConst(_Rs_)) {
2562 MOV32ItoM((uptr)&target, iRegs[_Rs_].k);
2563 } else {
2564 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2565 MOV32RtoM((uptr)&target, EAX);
2566 }
2567
2568 SetBranch();
2569}
2570
2571static void recJALR() {
2572// jalr Rs
2573
2574 if (IsConst(_Rs_)) {
2575 MOV32ItoM((uptr)&target, iRegs[_Rs_].k);
2576 } else {
2577 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2578 MOV32RtoM((uptr)&target, EAX);
2579 }
2580
2581 if (_Rd_) {
2582 MapConst(_Rd_, pc + 4);
2583 }
2584
2585 SetBranch();
2586}
2587
2588static void recBEQ() {
2589// Branch if Rs == Rt
2590 u32 bpc = _Imm_ * 4 + pc;
2591
2592// iFlushRegs();
2593 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2594 return;
2595 }
2596
2597 if (_Rs_ == _Rt_) {
2598 iJump(bpc);
2599 } else {
2600 if (IsConst(_Rs_) && IsConst(_Rt_)) {
2601 if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
2602 iJump(bpc); return;
2603 } else {
2604 iJump(pc+4); return;
2605 }
2606 } else if (IsConst(_Rs_)) {
2607 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
2608 } else if (IsConst(_Rt_)) {
2609 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
2610 } else {
2611 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2612 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2613 }
2614
2615 j32Ptr[4] = JE32(0);
2616
2617 iBranch(pc+4, 1);
2618
2619 x86SetJ32(j32Ptr[4]);
2620
2621 iBranch(bpc, 0);
2622 pc+=4;
2623 }
2624}
2625
2626static void recBNE() {
2627// Branch if Rs != Rt
2628 u32 bpc = _Imm_ * 4 + pc;
2629
2630// iFlushRegs();
2631 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2632 return;
2633 }
2634
2635 if (IsConst(_Rs_) && IsConst(_Rt_)) {
2636 if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
2637 iJump(bpc); return;
2638 } else {
2639 iJump(pc+4); return;
2640 }
2641 } else if (IsConst(_Rs_)) {
2642 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
2643 } else if (IsConst(_Rt_)) {
2644 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
2645 } else {
2646 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2647 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2648 }
2649 j32Ptr[4] = JNE32(0);
2650
2651 iBranch(pc+4, 1);
2652
2653 x86SetJ32(j32Ptr[4]);
2654
2655 iBranch(bpc, 0);
2656 pc+=4;
2657}
2658
2659static void recBLEZ() {
2660// Branch if Rs <= 0
2661 u32 bpc = _Imm_ * 4 + pc;
2662
2663// iFlushRegs();
2664 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2665 return;
2666 }
2667
2668 if (IsConst(_Rs_)) {
2669 if ((s32)iRegs[_Rs_].k <= 0) {
2670 iJump(bpc); return;
2671 } else {
2672 iJump(pc+4); return;
2673 }
2674 }
2675
2676 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2677 j32Ptr[4] = JLE32(0);
2678
2679 iBranch(pc+4, 1);
2680
2681 x86SetJ32(j32Ptr[4]);
2682
2683 iBranch(bpc, 0);
2684 pc+=4;
2685}
2686
2687static void recBGEZ() {
2688// Branch if Rs >= 0
2689 u32 bpc = _Imm_ * 4 + pc;
2690
2691// iFlushRegs();
2692 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2693 return;
2694 }
2695
2696 if (IsConst(_Rs_)) {
2697 if ((s32)iRegs[_Rs_].k >= 0) {
2698 iJump(bpc); return;
2699 } else {
2700 iJump(pc+4); return;
2701 }
2702 }
2703
2704 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2705 j32Ptr[4] = JGE32(0);
2706
2707 iBranch(pc+4, 1);
2708
2709 x86SetJ32(j32Ptr[4]);
2710
2711 iBranch(bpc, 0);
2712 pc+=4;
2713}
2714#endif
2715
2716#if 0
2717REC_FUNC(MFC0);
2718REC_SYS(MTC0);
2719REC_FUNC(CFC0);
2720REC_SYS(CTC0);
2721REC_FUNC(RFE);
2722#endif
2723//REC_SYS(MTC0);
2724#if 1
2725static void recMFC0() {
2726// Rt = Cop0->Rd
2727 if (!_Rt_) return;
2728
2729 iRegs[_Rt_].state = ST_UNK;
2730 MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]);
2731 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
2732}
2733
2734static void recCFC0() {
2735// Rt = Cop0->Rd
2736
2737 recMFC0();
2738}
2739
2740//*
2741void psxMTC0();
2742static void recMTC0() {
2743// Cop0->Rd = Rt
2744
2745 if (IsConst(_Rt_)) {
2746 switch (_Rd_) {
2747 case 12:
2748 MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
2749 break;
2750 case 13:
2751 MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
2752 break;
2753 default:
2754 MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
2755 break;
2756 }
2757 } else {
2758 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2759 switch (_Rd_) {
2760 case 13:
2761 AND32ItoR(EAX, ~(0xfc00));
2762 break;
2763 }
2764 MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX);
2765 }
2766
2767 if (_Rd_ == 12 || _Rd_ == 13) {
2768 iFlushRegs();
2769 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc);
2770 CALLFunc((uptr)psxTestSWInts);
2771 if (branch == 0) {
2772 branch = 2;
2773 iRet();
2774 }
2775 }
2776}//*/
2777
2778static void recCTC0() {
2779// Cop0->Rd = Rt
2780
2781 recMTC0();
2782}
2783
2784static void recRFE() {
2785 MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status);
2786 MOV32RtoR(ECX, EAX);
2787 AND32ItoR(EAX, 0xfffffff0);
2788 AND32ItoR(ECX, 0x3c);
2789 SHR32ItoR(ECX, 2);
2790 OR32RtoR (EAX, ECX);
2791 MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX);
2792
2793 iFlushRegs();
2794 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc);
2795 CALLFunc((uptr)psxTestSWInts);
2796 if (branch == 0) {
2797 branch = 2;
2798 iRet();
2799 }
2800}
2801#endif
2802
2803#include "iGte.h"
2804
2805//
2806
2807static void recHLE() {
2808 iFlushRegs();
2809
2810 CALLFunc((uptr)psxHLEt[psxRegs.code & 0xffff]);
2811 branch = 2;
2812 iRet();
2813}
2814
2815//
2816
2817static void (*recBSC[64])() = {
2818 recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ,
2819 recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI ,
2820 recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL,
2821 recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL,
2822 recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL,
2823 recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL,
2824 recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
2825 recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
2826};
2827
2828static void (*recSPC[64])() = {
2829 recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV,
2830 recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL,
2831 recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL,
2832 recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL,
2833 recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR ,
2834 recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL,
2835 recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL,
2836 recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL
2837};
2838
2839static void (*recREG[32])() = {
2840 recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
2841 recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
2842 recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
2843 recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
2844};
2845
2846static void (*recCP0[32])() = {
2847 recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL,
2848 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
2849 recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
2850 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
2851};
2852
2853static void (*recCP2[64])() = {
2854 recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00
2855 recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08
2856 recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10
2857 recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18
2858 recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20
2859 recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28
2860 recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30
2861 recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38
2862};
2863
2864static void (*recCP2BSC[32])() = {
2865 recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, recNULL,
2866 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
2867 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
2868 recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
2869};
2870
2871
2872static void recRecompile() {
2873 char *p;
2874 char *ptr;
2875
2876 dump = 0;
2877 resp = 0;
2878
2879 /* if x86Ptr reached the mem limit reset whole mem */
2880 if (((uptr)x86Ptr - (uptr)recMem) >= (RECMEM_SIZE - PTRMULT*0x10000))
2881 recReset();
2882
2883 x86Align(32);
2884 ptr = x86Ptr;
2885
2886 PC_RECP(psxRegs.pc) = x86Ptr;
2887 pc = psxRegs.pc;
2888 pcold = pc;
2889
2890 //Make some stack space for function arguments spill (x86-64 calling conventions)
2891 // 0x38 = 7 args, should be plenty...
2892 SUB64ItoR(RSP, STACKSIZE);
2893
2894 for (count=0; count<500;) {
2895 p = (char *)PSXM(pc);
2896 if (p == NULL) recError();
2897 psxRegs.code = *(u32 *)p;
2898/*
2899 if ((psxRegs.code >> 26) == 0x23) { // LW
2900 int i;
2901 u32 code;
2902
2903 for (i=1;; i++) {
2904 p = (char *)PSXM(pc+i*4);
2905 if (p == NULL) recError();
2906 code = *(u32 *)p;
2907
2908 if ((code >> 26) != 0x23 ||
2909 _fRs_(code) != _Rs_ ||
2910 _fImm_(code) != (_Imm_+i*4))
2911 break;
2912 }
2913 if (i > 1) {
2914 recLWBlock(i);
2915 pc = pc + i*4; continue;
2916 }
2917 }
2918
2919 if ((psxRegs.code >> 26) == 0x2b) { // SW
2920 int i;
2921 u32 code;
2922
2923 for (i=1;; i++) {
2924 p = (char *)PSXM(pc+i*4);
2925 if (p == NULL) recError();
2926 code = *(u32 *)p;
2927
2928 if ((code >> 26) != 0x2b ||
2929 _fRs_(code) != _Rs_ ||
2930 _fImm_(code) != (_Imm_+i*4))
2931 break;
2932 }
2933 if (i > 1) {
2934 recSWBlock(i);
2935 pc = pc + i*4; continue;
2936 }
2937 }*/
2938
2939 pc+=4; count++;
2940 recBSC[psxRegs.code>>26]();
2941
2942 if (branch) {
2943 branch = 0;
2944 if (dump) iDumpBlock(ptr);
2945 return;
2946 }
2947 }
2948
2949 iFlushRegs();
2950
2951 MOV32ItoM((uptr)&psxRegs.pc, pc);
2952 iRet();
2953}
2954
2955
2956R3000Acpu psxRec = {
2957 recInit,
2958 recReset,
2959 recExecute,
2960 recExecuteBlock,
2961 recClear,
2962 recShutdown
2963};