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