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