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