1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
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. *
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. *
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 ***************************************************************************/
21 * i386 assembly functions for R3000A core.
25 #include "../r3000a.h"
26 #include "../psxhle.h"
31 #define MAP_ANONYMOUS MAP_ANON
36 #define PTRMULT (sizeof(uptr) / sizeof(u32))
42 #define PC_REC(x) (psxRecLUT[(x) >> 16] + PTRMULT * ((x) & 0xffff))
43 #define PC_RECP(x) (*(uptr *)PC_REC(x))
45 #define RECMEM_SIZE (PTRMULT * 8 * 1024 * 1024)
47 static char *recMem; /* the recompiled blocks will be here */
48 static char *recRAM; /* and the ptr to the blocks here */
49 static char *recROM; /* and here */
51 static u32 pc; /* recompiler pc */
52 static u32 pcold; /* recompiler oldpc */
53 static int count; /* recompiler intruction count */
54 static int branch; /* set for branch */
55 static u32 target; /* branch target */
64 static iRegisters iRegs[32];
65 static iRegisters iRegsS[32];
71 #define IsConst(reg) (iRegs[reg].state == ST_CONST)
72 #define IsMapped(reg) (iRegs[reg].state == ST_MAPPED)
74 static void (*recBSC[64])();
75 static void (*recSPC[64])();
76 static void (*recREG[32])();
77 static void (*recCP0[32])();
78 static void (*recCP2[64])();
79 static void (*recCP2BSC[32])();
81 #define STACKSIZE 0x18
82 static void StackRes()
85 ADD64ItoR(RSP, STACKSIZE);
87 if (resp) ADD32ItoR(ESP, resp);
91 static void MapConst(int reg, u32 _const) {
92 iRegs[reg].k = _const;
93 iRegs[reg].state = ST_CONST;
96 static void iFlushReg(int reg) {
98 MOV32ItoM((uptr)&psxRegs.GPR.r[reg], iRegs[reg].k);
100 iRegs[reg].state = ST_UNK;
103 static void iFlushRegs() {
106 for (i=1; i<32; i++) {
113 count = ((pc - pcold) / 4) * BIAS;
114 ADD32ItoM((uptr)&psxRegs.cycle, count);
119 static int iLoadTest() {
122 // check for load delay
123 tmp = psxRegs.code >> 26;
146 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
154 /* set a pending branch */
155 static void SetBranch() {
157 psxRegs.code = PSXMu32(pc);
160 if (iLoadTest() == 1) {
162 MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
164 count = ((pc - pcold) / 4) * BIAS;
165 ADD32ItoM((uptr)&psxRegs.cycle, count);
167 //PUSH64M((uptr)&target);
168 MOV32MtoR(X86ARG2, (uptr)&target);
170 MOV64ItoR(X86ARG1, _Rt_);
171 CALLFunc((uptr)psxDelayTest);
177 recBSC[psxRegs.code>>26]();
180 MOV32MtoR(EAX, (uptr)&target);
181 MOV32RtoM((uptr)&psxRegs.pc, EAX);
182 CALLFunc((uptr)psxBranchTest);
187 static void iJump(u32 branchPC) {
189 psxRegs.code = PSXMu32(pc);
192 if (iLoadTest() == 1) {
194 MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
196 count = ((pc - pcold) / 4) * BIAS;
197 ADD32ItoM((uptr)&psxRegs.cycle, count);
200 MOV64ItoR(X86ARG2, branchPC);
202 MOV64ItoR(X86ARG1, _Rt_);
203 CALLFunc((uptr)psxDelayTest);
204 //ADD32ItoR(ESP, 2*8);
210 recBSC[psxRegs.code>>26]();
213 MOV32ItoM((uptr)&psxRegs.pc, branchPC);
214 CALLFunc((uptr)psxBranchTest);
216 count = ((pc - pcold) / 4) * BIAS;
217 ADD32ItoM((uptr)&psxRegs.cycle, count);
222 // maybe just happened an interruption, check so
223 CMP32ItoM((uptr)&psxRegs.pc, branchPC);
229 MOV64MtoR(RAX, PC_REC(branchPC));
243 static void iBranch(u32 branchPC, int savectx) {
248 memcpy(iRegsS, iRegs, sizeof(iRegs));
252 psxRegs.code = PSXMu32(pc);
254 // the delay test is only made when the branch is taken
255 // savectx == 0 will mean that :)
256 if (savectx == 0 && iLoadTest() == 1) {
258 MOV32ItoM((uptr)&psxRegs.code, psxRegs.code);
260 count = (((pc+4) - pcold) / 4) * BIAS;
261 ADD32ItoM((uptr)&psxRegs.cycle, count);
262 //if (resp) ADD32ItoR(ESP, resp);
265 MOV64ItoR(X86ARG2, branchPC);
267 MOV64ItoR(X86ARG1,_Rt_);
268 CALLFunc((uptr)psxDelayTest);
275 recBSC[psxRegs.code>>26]();
278 MOV32ItoM((uptr)&psxRegs.pc, branchPC);
279 CALLFunc((uptr)psxBranchTest);
281 count = ((pc - pcold) / 4) * BIAS;
282 ADD32ItoM((uptr)&psxRegs.cycle, count);
286 // maybe just happened an interruption, check so
287 CMP32ItoM((uptr)&psxRegs.pc, branchPC);
293 MOV64MtoR(RAX, PC_REC(branchPC));
294 TEST64RtoR(RAX, RAX);
306 memcpy(iRegs, iRegsS, sizeof(iRegs));
311 char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n";
312 char *txt1 = "EAX = %x\n";
313 char *txt2 = "M32 = %x\n";
322 PUSH32M ((uptr)&txt0);
323 CALLFunc((uptr)SysPrintf);
332 PUSH64M ((uptr)&txt1);
333 CALLFunc((uptr)SysPrintf);
337 void iLogM32(u32 mem) {
339 PUSH64M ((uptr)&txt2);
340 CALLFunc((uptr)SysPrintf);
344 static void iDumpRegs() {
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]);
355 void iDumpBlock(char *ptr) {
359 SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxRegs.cycle);
361 for (i = psxRegs.pc; i < pc; i+=4)
362 SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
365 f = fopen("dump1", "w");
366 fwrite(ptr, 1, (uptr)x86Ptr - (uptr)ptr, f);
368 //system("ndisasm -b64 dump1");
372 #define REC_FUNC(f) \
374 static void rec##f() { \
376 MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
377 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
378 CALLFunc((uptr)psx##f); \
384 static void rec##f() { \
386 MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
387 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
388 CALLFunc((uptr)psx##f); \
393 #define REC_BRANCH(f) \
395 static void rec##f() { \
397 MOV32ItoM((uptr)&psxRegs.code, (u32)psxRegs.code); \
398 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc); \
399 CALLFunc((uptr)psx##f); \
404 static void recRecompile();
406 static int recInit() {
409 psxRecLUT = (uptr*) malloc(0x010000 * sizeof(uptr));
412 RECMEM_SIZE + PTRMULT*0x1000,
413 PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
417 PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
418 recROM = &recRAM[0x200000*PTRMULT];
420 if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) {
421 SysMessage("Error allocating memory"); return -1;
423 memset(recMem, 0, RECMEM_SIZE);
424 memset(recRAM, 0, 0x200000 * PTRMULT);
425 memset(recROM, 0, 0x080000 * PTRMULT);
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));
431 for (i=0; i<0x08; i++) psxRecLUT[i + 0xbfc0] = (uptr)&recROM[PTRMULT*(i << 16)];
436 static void recReset() {
437 memset(recRAM, 0, 0x200000 * PTRMULT);
438 memset(recROM, 0, 0x080000 * PTRMULT);
445 memset(iRegs, 0, sizeof(iRegs));
446 iRegs[0].state = ST_CONST;
450 static void recShutdown() {
451 if (recMem == NULL) return;
453 munmap(recMem, RECMEM_SIZE + PTRMULT*0x1000);
454 munmap(recRAM, 0x280000*PTRMULT);
458 static void recError() {
461 SysMessage("Unrecoverable error while running recompiler\n");
465 /*__inline*/ static void execute() {
469 p = (uptr *)PC_REC(psxRegs.pc);
470 // if (!p) { recError(); return; }
476 if (*p < (uptr)recMem || *p >= (uptr)recMem + RECMEM_SIZE)
481 recFunc = (void (*)())*p;
485 static void recExecute() {
489 static void recExecuteBlock() {
493 static void recClear(u32 Addr, u32 Size) {
494 memset((void*)PC_REC(Addr), 0, Size * sizeof(uptr));
497 static void recNULL() {
498 // SysMessage("recUNK: %8.8x\n", psxRegs.code);
501 /*********************************************************
502 * goes to opcodes tables... *
503 * Format: table[something....] *
504 *********************************************************/
508 static void recSPECIAL() {
513 static void recREGIMM() {
517 static void recCOP0() {
523 static void recCOP2() {
528 static void recBASIC() {
532 //end of Tables opcodes...
534 /*********************************************************
535 * Arithmetic with immediate operand *
536 * Format: OP rt, rs, immediate *
537 *********************************************************/
550 static void recADDIU() {
558 iRegs[_Rt_].k+= _Imm_;
561 INC32M((uptr)&psxRegs.GPR.r[_Rt_]);
562 } else if (_Imm_ == -1) {
563 DEC32M((uptr)&psxRegs.GPR.r[_Rt_]);
565 ADD32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _Imm_);
570 MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
572 iRegs[_Rt_].state = ST_UNK;
574 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
577 } else if (_Imm_ == -1) {
580 ADD32ItoR(EAX, _Imm_);
582 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
587 static void recADDI() {
592 static void recSLTI() {
593 // Rt = Rs < Im (signed)
599 MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
601 iRegs[_Rt_].state = ST_UNK;
603 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
604 CMP32ItoR(EAX, _Imm_);
606 AND32ItoR(EAX, 0xff);
607 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
611 static void recSLTIU() {
612 // Rt = Rs < Im (unsigned)
618 MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
620 iRegs[_Rt_].state = ST_UNK;
622 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
623 CMP32ItoR(EAX, _Imm_);
625 AND32ItoR(EAX, 0xff);
626 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
630 static void recANDI() {
638 iRegs[_Rt_].k&= _ImmU_;
640 AND32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
644 MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
646 iRegs[_Rt_].state = ST_UNK;
648 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
649 AND32ItoR(EAX, _ImmU_);
650 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
655 static void recORI() {
663 iRegs[_Rt_].k|= _ImmU_;
665 OR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
669 MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
671 iRegs[_Rt_].state = ST_UNK;
673 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
674 if (_ImmU_) OR32ItoR (EAX, _ImmU_);
675 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
680 static void recXORI() {
688 iRegs[_Rt_].k^= _ImmU_;
690 XOR32ItoM((uptr)&psxRegs.GPR.r[_Rt_], _ImmU_);
694 MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
696 iRegs[_Rt_].state = ST_UNK;
698 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
699 XOR32ItoR(EAX, _ImmU_);
700 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
705 //end of * Arithmetic with immediate operand
707 /*********************************************************
708 * Load higher 16 bits of the first word in GPR with imm *
709 * Format: OP rt, immediate *
710 *********************************************************/
713 static void recLUI() {
717 MapConst(_Rt_, psxRegs.code << 16);
720 //End of Load Higher .....
723 /*********************************************************
724 * Register arithmetic *
725 * Format: OP rd, rs, rt *
726 *********************************************************/
743 static void recADDU() {
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;
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);
763 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
764 if (iRegs[_Rs_].k == 1) {
766 } else if (iRegs[_Rs_].k == 0xffffffff) {
768 } else if (iRegs[_Rs_].k) {
769 ADD32ItoR(EAX, iRegs[_Rs_].k);
771 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
773 } else if (IsConst(_Rt_)) {
774 iRegs[_Rd_].state = ST_UNK;
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);
785 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
786 if (iRegs[_Rt_].k == 1) {
788 } else if (iRegs[_Rt_].k == 0xffffffff) {
790 } else if (iRegs[_Rt_].k) {
791 ADD32ItoR(EAX, iRegs[_Rt_].k);
793 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
796 iRegs[_Rd_].state = ST_UNK;
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);
812 static void recADD() {
817 static void recSUBU() {
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;
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;
834 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
835 SUB32ItoR(EAX, iRegs[_Rt_].k);
836 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
838 iRegs[_Rd_].state = ST_UNK;
840 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
841 SUB32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
842 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
846 static void recSUB() {
851 static void recAND() {
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;
862 if (_Rd_ == _Rt_) { // Rd&= Rs
863 AND32ItoM((uptr)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
865 MOV32ItoR(EAX, iRegs[_Rs_].k);
866 AND32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
867 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
869 } else if (IsConst(_Rt_)) {
870 iRegs[_Rd_].state = ST_UNK;
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);
880 iRegs[_Rd_].state = ST_UNK;
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);
896 static void recOR() {
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;
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;
913 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
914 OR32ItoR (EAX, iRegs[_Rt_].k);
915 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
917 iRegs[_Rd_].state = ST_UNK;
919 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
920 OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
921 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
925 static void recXOR() {
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;
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;
942 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
943 XOR32ItoR(EAX, iRegs[_Rt_].k);
944 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
946 iRegs[_Rd_].state = ST_UNK;
948 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
949 XOR32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
950 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
954 static void recNOR() {
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;
965 MOV32ItoR(EAX, iRegs[_Rs_].k);
966 OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
968 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
969 } else if (IsConst(_Rt_)) {
970 iRegs[_Rd_].state = ST_UNK;
972 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
973 OR32ItoR (EAX, iRegs[_Rt_].k);
975 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
977 iRegs[_Rd_].state = ST_UNK;
979 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
980 OR32MtoR (EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
982 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
986 static void recSLT() {
987 // Rd = Rs < Rt (signed)
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;
997 MOV32ItoR(EAX, iRegs[_Rs_].k);
998 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1000 AND32ItoR(EAX, 0xff);
1001 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1002 } else if (IsConst(_Rt_)) {
1003 iRegs[_Rd_].state = ST_UNK;
1005 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1006 CMP32ItoR(EAX, iRegs[_Rt_].k);
1008 AND32ItoR(EAX, 0xff);
1009 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1011 iRegs[_Rd_].state = ST_UNK;
1013 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1014 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1016 AND32ItoR(EAX, 0xff);
1017 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1021 static void recSLTU() {
1022 // Rd = Rs < Rt (unsigned)
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;
1032 MOV32ItoR(EAX, iRegs[_Rs_].k);
1033 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1034 SBB32RtoR(EAX, EAX);
1036 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1037 } else if (IsConst(_Rt_)) {
1038 iRegs[_Rd_].state = ST_UNK;
1040 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1041 CMP32ItoR(EAX, iRegs[_Rt_].k);
1042 SBB32RtoR(EAX, EAX);
1044 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1046 iRegs[_Rd_].state = ST_UNK;
1048 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1049 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1050 SBB32RtoR(EAX, EAX);
1052 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
1056 //End of * Register arithmetic
1058 /*********************************************************
1059 * Register mult/div & Register trap logic *
1060 * Format: OP rs, rt *
1061 *********************************************************/
1071 static void recMULT() {
1072 // Lo/Hi = Rs * Rt (signed)
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);
1084 if (IsConst(_Rs_)) {
1085 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k);
1087 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1089 if (IsConst(_Rt_)) {
1090 MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k);
1093 IMUL32M ((uptr)&psxRegs.GPR.r[_Rt_]);
1095 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1096 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1099 static void recMULTU() {
1100 // Lo/Hi = Rs * Rt (unsigned)
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);
1112 if (IsConst(_Rs_)) {
1113 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k);
1115 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1117 if (IsConst(_Rt_)) {
1118 MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k);
1121 MUL32M ((uptr)&psxRegs.GPR.r[_Rt_]);
1123 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1124 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1127 static void recDIV() {
1128 // Lo/Hi = Rs / Rt (signed)
1132 if (IsConst(_Rt_)) {
1133 if (iRegs[_Rt_].k == 0) return;
1134 MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k);
1136 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1140 if (IsConst(_Rs_)) {
1141 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k);
1143 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1147 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1148 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1149 if (!IsConst(_Rt_)) {
1154 static void recDIVU() {
1155 // Lo/Hi = Rs / Rt (unsigned)
1159 if (IsConst(_Rt_)) {
1160 if (iRegs[_Rt_].k == 0) return;
1161 MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k);
1163 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1167 if (IsConst(_Rs_)) {
1168 MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k);
1170 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1172 XOR32RtoR(EDX, EDX);
1174 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
1175 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EDX);
1176 if (!IsConst(_Rt_)) {
1181 //End of * Register mult/div & Register trap logic
1201 static void SetArg_OfB(x86IntRegType arg) {
1204 MOV64ItoR(arg, iRegs[_Rs_].k + _Imm_);
1206 PUSH32I (iRegs[_Rs_].k + _Imm_);
1210 MOV32MtoR(arg, (uptr)&psxRegs.GPR.r[_Rs_]);
1212 ADD32ItoR(arg, _Imm_);
1215 MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
1216 ADD32ItoR(EAX, _Imm_);
1219 PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]);
1229 static void recLB() {
1230 // Rt = mem[Rs + Im] (signed)
1234 if (IsConst(_Rs_)) {
1235 u32 addr = iRegs[_Rs_].k + _Imm_;
1238 if ((t & 0xfff0) == 0xbfc0) {
1240 // since bios is readonly it won't change
1241 MapConst(_Rt_, psxRs8(addr));
1244 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1246 iRegs[_Rt_].state = ST_UNK;
1248 MOVSX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1249 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1252 if (t == 0x1f80 && addr < 0x1f801000) {
1254 iRegs[_Rt_].state = ST_UNK;
1256 MOVSX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]);
1257 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1260 // SysPrintf("unhandled r8 %x\n", addr);
1263 SetArg_OfB(X86ARG1);
1264 CALLFunc((uptr)psxMemRead8);
1266 iRegs[_Rt_].state = ST_UNK;
1267 MOVSX32R8toR(EAX, EAX);
1268 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1270 // ADD32ItoR(ESP, 4);
1273 static void recLBU() {
1274 // Rt = mem[Rs + Im] (unsigned)
1278 if (IsConst(_Rs_)) {
1279 u32 addr = iRegs[_Rs_].k + _Imm_;
1282 if ((t & 0xfff0) == 0xbfc0) {
1284 // since bios is readonly it won't change
1285 MapConst(_Rt_, psxRu8(addr));
1288 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1290 iRegs[_Rt_].state = ST_UNK;
1292 MOVZX32M8toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1293 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1296 if (t == 0x1f80 && addr < 0x1f801000) {
1298 iRegs[_Rt_].state = ST_UNK;
1300 MOVZX32M8toR(EAX, (uptr)&psxH[addr & 0xfff]);
1301 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1304 // SysPrintf("unhandled r8u %x\n", addr);
1307 SetArg_OfB(X86ARG1);
1308 CALLFunc((uptr)psxMemRead8);
1310 iRegs[_Rt_].state = ST_UNK;
1311 MOVZX32R8toR(EAX, EAX);
1312 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1314 // ADD32ItoR(ESP, 4);
1317 static void recLH() {
1318 // Rt = mem[Rs + Im] (signed)
1322 if (IsConst(_Rs_)) {
1323 u32 addr = iRegs[_Rs_].k + _Imm_;
1326 if ((t & 0xfff0) == 0xbfc0) {
1328 // since bios is readonly it won't change
1329 MapConst(_Rt_, psxRs16(addr));
1332 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1334 iRegs[_Rt_].state = ST_UNK;
1336 MOVSX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1337 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1340 if (t == 0x1f80 && addr < 0x1f801000) {
1342 iRegs[_Rt_].state = ST_UNK;
1344 MOVSX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]);
1345 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1348 // SysPrintf("unhandled r16 %x\n", addr);
1351 SetArg_OfB(X86ARG1);
1352 CALLFunc((uptr)psxMemRead16);
1354 iRegs[_Rt_].state = ST_UNK;
1355 MOVSX32R16toR(EAX, EAX);
1356 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1358 // ADD32ItoR(ESP, 4);
1361 static void recLHU() {
1362 // Rt = mem[Rs + Im] (unsigned)
1366 if (IsConst(_Rs_)) {
1367 u32 addr = iRegs[_Rs_].k + _Imm_;
1370 if ((t & 0xfff0) == 0xbfc0) {
1372 // since bios is readonly it won't change
1373 MapConst(_Rt_, psxRu16(addr));
1376 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1378 iRegs[_Rt_].state = ST_UNK;
1380 MOVZX32M16toR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1381 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1384 if (t == 0x1f80 && addr < 0x1f801000) {
1386 iRegs[_Rt_].state = ST_UNK;
1388 MOVZX32M16toR(EAX, (uptr)&psxH[addr & 0xfff]);
1389 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1393 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
1395 iRegs[_Rt_].state = ST_UNK;
1398 MOV64ItoR(X86ARG1, addr);
1399 //CALLFunc ((uptr)SPU_readRegister);
1400 MOV64ItoR(RAX, (uptr)SPU_readRegister);
1402 MOVZX32R16toR(EAX, EAX);
1403 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1410 case 0x1f801100: case 0x1f801110: case 0x1f801120:
1412 iRegs[_Rt_].state = ST_UNK;
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);
1422 case 0x1f801104: case 0x1f801114: case 0x1f801124:
1424 iRegs[_Rt_].state = ST_UNK;
1426 MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
1427 CALLFunc((uptr)psxRcntRmode);
1428 MOVZX32R16toR(EAX, EAX);
1429 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1433 case 0x1f801108: case 0x1f801118: case 0x1f801128:
1435 iRegs[_Rt_].state = ST_UNK;
1437 MOV64ItoR(X86ARG1, (addr >> 4) & 0x3);
1438 CALLFunc((uptr)psxRcntRtarget);
1439 MOVZX32R16toR(EAX, EAX);
1440 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1445 // SysPrintf("unhandled r16u %x\n", addr);
1448 SetArg_OfB(X86ARG1);
1449 CALLFunc((uptr)psxMemRead16);
1451 iRegs[_Rt_].state = ST_UNK;
1452 MOVZX32R16toR(EAX, EAX);
1453 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1455 // ADD32ItoR(ESP, 4);
1458 static void recLW() {
1459 // Rt = mem[Rs + Im] (unsigned)
1463 if (IsConst(_Rs_)) {
1464 u32 addr = iRegs[_Rs_].k + _Imm_;
1467 if ((t & 0xfff0) == 0xbfc0) {
1469 // since bios is readonly it won't change
1470 MapConst(_Rt_, psxRu32(addr));
1473 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1475 iRegs[_Rt_].state = ST_UNK;
1477 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1478 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1481 if (t == 0x1f80 && addr < 0x1f801000) {
1483 iRegs[_Rt_].state = ST_UNK;
1485 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
1486 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
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:
1501 iRegs[_Rt_].state = ST_UNK;
1503 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffff]);
1504 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1509 iRegs[_Rt_].state = ST_UNK;
1511 CALLFunc((uptr)GPU_readData);
1512 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1517 iRegs[_Rt_].state = ST_UNK;
1519 CALLFunc((uptr)GPU_readStatus);
1520 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1524 // SysPrintf("unhandled r32 %x\n", addr);
1527 SetArg_OfB(X86ARG1);
1528 CALLFunc((uptr)psxMemRead32);
1530 iRegs[_Rt_].state = ST_UNK;
1531 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1533 // ADD32ItoR(ESP, 4);
1536 extern u32 LWL_MASK[4];
1537 extern u32 LWL_SHIFT[4];
1539 void iLWLk(u32 shift) {
1540 if (IsConst(_Rt_)) {
1541 MOV32ItoR(ECX, iRegs[_Rt_].k);
1543 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1545 AND32ItoR(ECX, LWL_MASK[shift]);
1546 SHL32ItoR(EAX, LWL_SHIFT[shift]);
1547 OR32RtoR (EAX, ECX);
1551 // Rt = Rt Merge mem[Rs + Im]
1553 if (IsConst(_Rs_)) {
1554 u32 addr = iRegs[_Rs_].k + _Imm_;
1557 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1558 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
1561 iRegs[_Rt_].state = ST_UNK;
1562 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1565 if (t == 0x1f80 && addr < 0x1f801000) {
1566 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
1569 iRegs[_Rt_].state = ST_UNK;
1570 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1575 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
1577 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1578 if (_Imm_) ADD32ItoR(EAX, _Imm_);
1583 MOV32RtoR(X86ARG1, EAX);
1584 CALLFunc((uptr)psxMemRead32);
1587 //ADD32ItoR(ESP, 4);
1589 if (IsConst(_Rs_)) MOV32ItoR(EDX, iRegs[_Rs_].k + _Imm_);
1591 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rs_]);
1592 if (_Imm_) ADD32ItoR(EDX, _Imm_);
1595 AND32ItoR(EDX, 0x3); // shift = addr & 3;
1597 MOV64ItoR(ECX, (uptr)LWL_SHIFT);
1598 MOV32RmStoR(ECX, ECX, EDX, 2);
1599 SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
1601 MOV64ItoR(ECX, (uptr)LWL_MASK);
1602 MOV32RmStoR(ECX, ECX, EDX, 2);
1603 if (IsConst(_Rt_)) {
1604 MOV32ItoR(EDX, iRegs[_Rt_].k);
1606 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
1608 AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
1612 iRegs[_Rt_].state = ST_UNK;
1613 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1615 //ADD64ItoR(RSP, 8);
1621 static void recLWBlock(int count) {
1622 u32 *code = PSXM(pc);
1624 // Rt = mem[Rs + Im] (unsigned)
1628 if (IsConst(_Rs_)) {
1629 u32 addr = iRegs[_Rs_].k + _Imm_;
1632 if ((t & 0xfff0) == 0xbfc0) {
1633 // since bios is readonly it won't change
1634 for (i=0; i<count; i++, code++, addr+=4) {
1636 MapConst(_fRt_(*code), psxRu32(addr));
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;
1646 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1fffff]);
1647 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
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;
1656 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
1657 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
1663 SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
1664 SetArg_OfB(X86ARG1);
1665 CALLFunc((uptr)psxMemPointer);
1666 // ADD32ItoR(ESP, 4);
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++) {
1674 iRegs[_fRt_(*code)].state = ST_UNK;
1676 MOV64RmStoR(EDX, EAX, ECX, 2);
1677 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EDX);
1679 if (i != (count-1)) INC32R(ECX);
1681 j32Ptr[5] = JMP32(0);
1682 x86SetJ32(j32Ptr[4]);
1683 for (i=0, code = PSXM(pc); i<count; i++, code++) {
1684 psxRegs.code = *code;
1688 ADD32ItoR(ESP, resp);
1690 x86SetJ32(j32Ptr[5]);
1695 extern u32 LWR_MASK[4];
1696 extern u32 LWR_SHIFT[4];
1698 void iLWRk(u32 shift) {
1699 if (IsConst(_Rt_)) {
1700 MOV32ItoR(ECX, iRegs[_Rt_].k);
1702 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
1704 AND32ItoR(ECX, LWR_MASK[shift]);
1705 SHR32ItoR(EAX, LWR_SHIFT[shift]);
1706 OR32RtoR (EAX, ECX);
1710 // Rt = Rt Merge mem[Rs + Im]
1712 if (IsConst(_Rs_)) {
1713 u32 addr = iRegs[_Rs_].k + _Imm_;
1716 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1717 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
1720 iRegs[_Rt_].state = ST_UNK;
1721 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1724 if (t == 0x1f80 && addr < 0x1f801000) {
1725 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
1728 iRegs[_Rt_].state = ST_UNK;
1729 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1734 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
1736 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
1737 if (_Imm_) ADD32ItoR(EAX, _Imm_);
1741 MOV32RtoR(X86ARG1, EAX);
1742 CALLFunc((uptr)psxMemRead32);
1746 AND32ItoR(EDX, 0x3); // shift = addr & 3;
1748 MOV64ItoR(ECX, (uptr)LWR_SHIFT);
1749 MOV32RmStoR(ECX, ECX, EDX, 2);
1750 SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
1752 MOV64ItoR(ECX, (uptr)LWR_MASK);
1753 MOV32RmStoR(ECX, ECX, EDX, 2);
1755 if (IsConst(_Rt_)) {
1756 MOV32ItoR(EDX, iRegs[_Rt_].k);
1758 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
1760 AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
1764 iRegs[_Rt_].state = ST_UNK;
1765 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
1771 static void recSB() {
1772 // mem[Rs + Im] = Rt
1776 if (IsConst(_Rs_)) {
1777 u32 addr = iRegs[_Rs_].k + _Imm_;
1780 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1781 if (IsConst(_Rt_)) {
1782 MOV8ItoM((uptr)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
1784 MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1785 MOV8RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
1789 if (t == 0x1f80 && addr < 0x1f801000) {
1790 if (IsConst(_Rt_)) {
1791 MOV8ItoM((uptr)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
1793 MOV8MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1794 MOV8RtoM((uptr)&psxH[addr & 0xfff], EAX);
1798 // SysPrintf("unhandled w8 %x\n", addr);
1801 if (IsConst(_Rt_)) {
1802 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1804 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1806 SetArg_OfB(X86ARG1);
1807 CALLFunc((uptr)psxMemWrite8);
1808 // ADD32ItoR(ESP, 8);
1811 static void recSH() {
1812 // mem[Rs + Im] = Rt
1816 if (IsConst(_Rs_)) {
1817 u32 addr = iRegs[_Rs_].k + _Imm_;
1820 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1821 if (IsConst(_Rt_)) {
1822 MOV16ItoM((uptr)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
1824 MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1825 MOV16RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
1829 if (t == 0x1f80 && addr < 0x1f801000) {
1830 if (IsConst(_Rt_)) {
1831 MOV16ItoM((uptr)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
1833 MOV16MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1834 MOV16RtoM((uptr)&psxH[addr & 0xfff], EAX);
1839 if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
1840 if (IsConst(_Rt_)) {
1841 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1843 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1845 MOV64ItoR(X86ARG1, addr);
1846 CALLFunc ((uptr)SPU_writeRegister);
1853 // SysPrintf("unhandled w16 %x\n", addr);
1856 if (IsConst(_Rt_)) {
1857 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1859 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1861 SetArg_OfB(X86ARG1);
1862 CALLFunc((uptr)psxMemWrite16);
1863 // ADD32ItoR(ESP, 8);
1866 static void recSW() {
1867 // mem[Rs + Im] = Rt
1871 if (IsConst(_Rs_)) {
1872 u32 addr = iRegs[_Rs_].k + _Imm_;
1875 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
1876 if (IsConst(_Rt_)) {
1877 MOV32ItoM((uptr)&psxM[addr & 0x1fffff], iRegs[_Rt_].k);
1879 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1880 MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
1884 if (t == 0x1f80 && addr < 0x1f801000) {
1885 if (IsConst(_Rt_)) {
1886 MOV32ItoM((uptr)&psxH[addr & 0xfff], iRegs[_Rt_].k);
1888 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1889 MOV32RtoM((uptr)&psxH[addr & 0xfff], EAX);
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:
1904 if (IsConst(_Rt_)) {
1905 MOV32ItoM((uptr)&psxH[addr & 0xffff], iRegs[_Rt_].k);
1907 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
1908 MOV32RtoM((uptr)&psxH[addr & 0xffff], EAX);
1913 if (IsConst(_Rt_)) {
1914 MOV64ItoR(X86ARG1, iRegs[_Rt_].k);
1916 MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]);
1918 CALLFunc((uptr)GPU_writeData);
1925 if (IsConst(_Rt_)) {
1926 MOV64ItoR(X86ARG1, iRegs[_Rt_].k);
1928 MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rt_]);
1930 CALLFunc((uptr)GPU_writeStatus);
1936 // SysPrintf("unhandled w32 %x\n", addr);
1939 if (IsConst(_Rt_)) {
1940 MOV64ItoR(X86ARG2, iRegs[_Rt_].k);
1942 MOV32MtoR(X86ARG2, (uptr)&psxRegs.GPR.r[_Rt_]);
1944 SetArg_OfB(X86ARG1);
1945 CALLFunc((uptr)psxMemWrite32);
1946 // ADD32ItoR(ESP, 8);
1951 static void recSWBlock(int count) {
1954 // mem[Rs + Im] = Rt
1958 if (IsConst(_Rs_)) {
1959 u32 addr = iRegs[_Rs_].k + _Imm_;
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);
1968 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]);
1969 MOV32RtoM((uptr)&psxM[addr & 0x1fffff], EAX);
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;
1979 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xfff]);
1980 MOV32RtoM((uptr)&psxRegs.GPR.r[_fRt_(*code)], EAX);
1986 SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
1987 SetArg_OfB(X86ARG1);
1988 CALLFunc((uptr)psxMemPointer);
1989 // ADD32ItoR(ESP, 4);
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);
2000 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_fRt_(*code)]);
2002 MOV32RtoRmS(EAX, ECX, 2, EDX);
2003 if (i != (count-1)) INC32R(ECX);
2005 j32Ptr[5] = JMP32(0);
2006 x86SetJ32(j32Ptr[4]);
2007 for (i=0, code = PSXM(pc); i<count; i++, code++) {
2008 psxRegs.code = *code;
2011 //ADD32ItoR(ESP, resp);
2012 x86SetJ32(j32Ptr[5]);
2017 extern u32 SWL_MASK[4];
2018 extern u32 SWL_SHIFT[4];
2020 void iSWLk(u32 shift) {
2021 if (IsConst(_Rt_)) {
2022 MOV32ItoR(ECX, iRegs[_Rt_].k);
2024 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
2026 SHR32ItoR(ECX, SWL_SHIFT[shift]);
2027 AND32ItoR(EAX, SWL_MASK[shift]);
2028 OR32RtoR (EAX, ECX);
2032 // mem[Rs + Im] = Rt Merge mem[Rs + Im]
2034 if (IsConst(_Rs_)) {
2035 u32 addr = iRegs[_Rs_].k + _Imm_;
2038 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2039 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
2041 MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX);
2044 if (t == 0x1f80 && addr < 0x1f801000) {
2045 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
2047 MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX);
2052 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2054 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2055 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2059 MOV32RtoR(X86ARG1, EAX);
2061 CALLFunc((uptr)psxMemRead32);
2064 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2066 MOV64ItoR(ECX, (uptr)SWL_MASK);
2067 MOV32RmStoR(ECX, ECX, EDX, 2);
2068 AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
2070 MOV64ItoR(ECX, (uptr)SWL_SHIFT);
2071 MOV32RmStoR(ECX, ECX, EDX, 2);
2072 if (IsConst(_Rt_)) {
2073 MOV32ItoR(EDX, iRegs[_Rt_].k);
2075 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
2077 SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
2079 OR32RtoR (EAX, EDX);
2080 MOV32RtoR(X86ARG2, EAX);
2082 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2084 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2085 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2088 MOV32RtoR(X86ARG1, EAX);
2090 CALLFunc((uptr)psxMemWrite32);
2091 // ADD32ItoR(ESP, 8);
2095 extern u32 SWR_MASK[4];
2096 extern u32 SWR_SHIFT[4];
2098 void iSWRk(u32 shift) {
2099 if (IsConst(_Rt_)) {
2100 MOV32ItoR(ECX, iRegs[_Rt_].k);
2102 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rt_]);
2104 SHL32ItoR(ECX, SWR_SHIFT[shift]);
2105 AND32ItoR(EAX, SWR_MASK[shift]);
2106 OR32RtoR (EAX, ECX);
2110 // mem[Rs + Im] = Rt Merge mem[Rs + Im]
2112 if (IsConst(_Rs_)) {
2113 u32 addr = iRegs[_Rs_].k + _Imm_;
2116 if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
2117 MOV32MtoR(EAX, (uptr)&psxM[addr & 0x1ffffc]);
2119 MOV32RtoM((uptr)&psxM[addr & 0x1ffffc], EAX);
2122 if (t == 0x1f80 && addr < 0x1f801000) {
2123 MOV32MtoR(EAX, (uptr)&psxH[addr & 0xffc]);
2125 MOV32RtoM((uptr)&psxH[addr & 0xffc], EAX);
2130 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2132 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2133 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2138 MOV32RtoR(X86ARG1, EAX);
2140 CALLFunc((uptr)psxMemRead32);
2143 AND32ItoR(EDX, 0x3); // shift = addr & 3;
2145 MOV64ItoR(ECX, (uptr)SWR_MASK);
2146 MOV32RmStoR(ECX, ECX, EDX, 2);
2147 AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
2149 MOV64ItoR(ECX, (uptr)SWR_SHIFT);
2150 MOV32RmStoR(ECX, ECX, EDX, 2);
2151 if (IsConst(_Rt_)) {
2152 MOV32ItoR(EDX, iRegs[_Rt_].k);
2154 MOV32MtoR(EDX, (uptr)&psxRegs.GPR.r[_Rt_]);
2156 SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
2158 OR32RtoR (EAX, EDX);
2159 MOV32RtoR(X86ARG2, EAX);
2161 if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
2163 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2164 if (_Imm_) ADD32ItoR(EAX, _Imm_);
2167 MOV32RtoR(X86ARG1, EAX);
2168 CALLFunc((uptr)psxMemWrite32);
2169 // ADD32ItoR(ESP, 8);
2181 static void recSLL() {
2187 if (IsConst(_Rt_)) {
2188 MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
2190 iRegs[_Rd_].state = ST_UNK;
2192 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2193 if (_Sa_) SHL32ItoR(EAX, _Sa_);
2194 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2198 static void recSRL() {
2204 if (IsConst(_Rt_)) {
2205 MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
2207 iRegs[_Rd_].state = ST_UNK;
2209 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2210 if (_Sa_) SHR32ItoR(EAX, _Sa_);
2211 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2215 static void recSRA() {
2221 if (IsConst(_Rt_)) {
2222 MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
2224 iRegs[_Rd_].state = ST_UNK;
2226 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2227 if (_Sa_) SAR32ItoR(EAX, _Sa_);
2228 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2240 static void recSLLV() {
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;
2251 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2252 MOV32ItoR(ECX, iRegs[_Rs_].k);
2254 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2255 } else if (IsConst(_Rt_)) {
2256 iRegs[_Rd_].state = ST_UNK;
2258 MOV32ItoR(EAX, iRegs[_Rt_].k);
2259 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2261 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2263 iRegs[_Rd_].state = ST_UNK;
2265 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2266 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2268 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2272 static void recSRLV() {
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;
2283 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2284 MOV32ItoR(ECX, iRegs[_Rs_].k);
2286 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2287 } else if (IsConst(_Rt_)) {
2288 iRegs[_Rd_].state = ST_UNK;
2290 MOV32ItoR(EAX, iRegs[_Rt_].k);
2291 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2293 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2295 iRegs[_Rd_].state = ST_UNK;
2297 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2298 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2300 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2304 static void recSRAV() {
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;
2315 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2316 MOV32ItoR(ECX, iRegs[_Rs_].k);
2318 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2319 } else if (IsConst(_Rt_)) {
2320 iRegs[_Rd_].state = ST_UNK;
2322 MOV32ItoR(EAX, iRegs[_Rt_].k);
2323 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2325 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2327 iRegs[_Rd_].state = ST_UNK;
2329 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2330 MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
2332 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2345 static void recSYSCALL() {
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);
2360 static void recBREAK() {
2371 static void recMFHI() {
2375 iRegs[_Rd_].state = ST_UNK;
2376 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.hi);
2377 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2380 static void recMTHI() {
2383 if (IsConst(_Rs_)) {
2384 MOV32ItoM((uptr)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
2386 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2387 MOV32RtoM((uptr)&psxRegs.GPR.n.hi, EAX);
2391 static void recMFLO() {
2395 iRegs[_Rd_].state = ST_UNK;
2396 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.n.lo);
2397 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rd_], EAX);
2400 static void recMTLO() {
2403 if (IsConst(_Rs_)) {
2404 MOV32ItoM((uptr)&psxRegs.GPR.n.lo, iRegs[_Rs_].k);
2406 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2407 MOV32RtoM((uptr)&psxRegs.GPR.n.lo, EAX);
2427 static void recBLTZ() {
2429 u32 bpc = _Imm_ * 4 + pc;
2433 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2437 if (IsConst(_Rs_)) {
2438 if ((s32)iRegs[_Rs_].k < 0) {
2441 iJump(pc+4); return;
2445 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2446 j32Ptr[4] = JL32(0);
2450 x86SetJ32(j32Ptr[4]);
2456 static void recBGTZ() {
2458 u32 bpc = _Imm_ * 4 + pc;
2461 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2465 if (IsConst(_Rs_)) {
2466 if ((s32)iRegs[_Rs_].k > 0) {
2469 iJump(pc+4); return;
2473 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2474 j32Ptr[4] = JG32(0);
2478 x86SetJ32(j32Ptr[4]);
2484 static void recBLTZAL() {
2486 u32 bpc = _Imm_ * 4 + pc;
2489 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2493 if (IsConst(_Rs_)) {
2494 if ((s32)iRegs[_Rs_].k < 0) {
2495 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2498 iJump(pc+4); return;
2502 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2503 j32Ptr[4] = JL32(0);
2507 x86SetJ32(j32Ptr[4]);
2509 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2514 static void recBGEZAL() {
2515 // Branch if Rs >= 0
2516 u32 bpc = _Imm_ * 4 + pc;
2519 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2523 if (IsConst(_Rs_)) {
2524 if ((s32)iRegs[_Rs_].k >= 0) {
2525 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2528 iJump(pc+4); return;
2532 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2533 j32Ptr[4] = JGE32(0);
2537 x86SetJ32(j32Ptr[4]);
2539 MOV32ItoM((uptr)&psxRegs.GPR.r[31], pc + 4);
2544 static void recJ() {
2547 iJump(_Target_ * 4 + (pc & 0xf0000000));
2550 static void recJAL() {
2553 MapConst(31, pc + 4);
2555 iJump(_Target_ * 4 + (pc & 0xf0000000));
2558 static void recJR() {
2561 if (IsConst(_Rs_)) {
2562 MOV32ItoM((uptr)&target, iRegs[_Rs_].k);
2564 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2565 MOV32RtoM((uptr)&target, EAX);
2571 static void recJALR() {
2574 if (IsConst(_Rs_)) {
2575 MOV32ItoM((uptr)&target, iRegs[_Rs_].k);
2577 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2578 MOV32RtoM((uptr)&target, EAX);
2582 MapConst(_Rd_, pc + 4);
2588 static void recBEQ() {
2589 // Branch if Rs == Rt
2590 u32 bpc = _Imm_ * 4 + pc;
2593 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2600 if (IsConst(_Rs_) && IsConst(_Rt_)) {
2601 if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
2604 iJump(pc+4); return;
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);
2611 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2612 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2615 j32Ptr[4] = JE32(0);
2619 x86SetJ32(j32Ptr[4]);
2626 static void recBNE() {
2627 // Branch if Rs != Rt
2628 u32 bpc = _Imm_ * 4 + pc;
2631 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2635 if (IsConst(_Rs_) && IsConst(_Rt_)) {
2636 if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
2639 iJump(pc+4); return;
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);
2646 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rs_]);
2647 CMP32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2649 j32Ptr[4] = JNE32(0);
2653 x86SetJ32(j32Ptr[4]);
2659 static void recBLEZ() {
2660 // Branch if Rs <= 0
2661 u32 bpc = _Imm_ * 4 + pc;
2664 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2668 if (IsConst(_Rs_)) {
2669 if ((s32)iRegs[_Rs_].k <= 0) {
2672 iJump(pc+4); return;
2676 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2677 j32Ptr[4] = JLE32(0);
2681 x86SetJ32(j32Ptr[4]);
2687 static void recBGEZ() {
2688 // Branch if Rs >= 0
2689 u32 bpc = _Imm_ * 4 + pc;
2692 if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
2696 if (IsConst(_Rs_)) {
2697 if ((s32)iRegs[_Rs_].k >= 0) {
2700 iJump(pc+4); return;
2704 CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0);
2705 j32Ptr[4] = JGE32(0);
2709 x86SetJ32(j32Ptr[4]);
2725 static void recMFC0() {
2729 iRegs[_Rt_].state = ST_UNK;
2730 MOV32MtoR(EAX, (uptr)&psxRegs.CP0.r[_Rd_]);
2731 MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
2734 static void recCFC0() {
2742 static void recMTC0() {
2745 if (IsConst(_Rt_)) {
2748 MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
2751 MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
2754 MOV32ItoM((uptr)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
2758 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[_Rt_]);
2761 AND32ItoR(EAX, ~(0xfc00));
2764 MOV32RtoM((uptr)&psxRegs.CP0.r[_Rd_], EAX);
2767 if (_Rd_ == 12 || _Rd_ == 13) {
2769 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc);
2770 CALLFunc((uptr)psxTestSWInts);
2778 static void recCTC0() {
2784 static void recRFE() {
2785 MOV32MtoR(EAX, (uptr)&psxRegs.CP0.n.Status);
2786 MOV32RtoR(ECX, EAX);
2787 AND32ItoR(EAX, 0xfffffff0);
2788 AND32ItoR(ECX, 0x3c);
2790 OR32RtoR (EAX, ECX);
2791 MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX);
2794 MOV32ItoM((uptr)&psxRegs.pc, (u32)pc);
2795 CALLFunc((uptr)psxTestSWInts);
2807 static void recHLE() {
2810 CALLFunc((uptr)psxHLEt[psxRegs.code & 0xffff]);
2817 static 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
2828 static 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
2839 static 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
2846 static 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
2853 static 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
2864 static 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
2872 static void recRecompile() {
2879 /* if x86Ptr reached the mem limit reset whole mem */
2880 if (((uptr)x86Ptr - (uptr)recMem) >= (RECMEM_SIZE - PTRMULT*0x10000))
2886 PC_RECP(psxRegs.pc) = x86Ptr;
2890 //Make some stack space for function arguments spill (x86-64 calling conventions)
2891 // 0x38 = 7 args, should be plenty...
2892 SUB64ItoR(RSP, STACKSIZE);
2894 for (count=0; count<500;) {
2895 p = (char *)PSXM(pc);
2896 if (p == NULL) recError();
2897 psxRegs.code = *(u32 *)p;
2899 if ((psxRegs.code >> 26) == 0x23) { // LW
2904 p = (char *)PSXM(pc+i*4);
2905 if (p == NULL) recError();
2908 if ((code >> 26) != 0x23 ||
2909 _fRs_(code) != _Rs_ ||
2910 _fImm_(code) != (_Imm_+i*4))
2915 pc = pc + i*4; continue;
2919 if ((psxRegs.code >> 26) == 0x2b) { // SW
2924 p = (char *)PSXM(pc+i*4);
2925 if (p == NULL) recError();
2928 if ((code >> 26) != 0x2b ||
2929 _fRs_(code) != _Rs_ ||
2930 _fImm_(code) != (_Imm_+i*4))
2935 pc = pc + i*4; continue;
2940 recBSC[psxRegs.code>>26]();
2944 if (dump) iDumpBlock(ptr);
2951 MOV32ItoM((uptr)&psxRegs.pc, pc);
2956 R3000Acpu psxRec = {