git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@60002 e17a0e51-4ae3-4d35-97c3-1a29b211df97
This commit is contained in:
parent
4953fde289
commit
6b375badaf
|
@ -0,0 +1,91 @@
|
|||
/* Pcsx - Pc Psx Emulator
|
||||
* Copyright (C) 1999-2003 Pcsx Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PGET_H
|
||||
#define PGET_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int psxCP2time[64] = {
|
||||
2, 16 , 1 , 1, 1, 1 , 8, 1, // 00
|
||||
1 , 1 , 1 , 1, 6 , 1 , 1 , 1, // 08
|
||||
8 , 8, 8, 19, 13 , 1 , 44 , 1, // 10
|
||||
1 , 1 , 1 , 17, 11 , 1 , 14 , 1, // 18
|
||||
30 , 1 , 1 , 1, 1, 1 , 1 , 1, // 20
|
||||
5 , 8 , 17 , 1, 1, 5, 6, 1, // 28
|
||||
23 , 1 , 1 , 1, 1, 1 , 1 , 1, // 30
|
||||
1 , 1 , 1 , 1, 1, 6 , 5 , 39 // 38
|
||||
};
|
||||
|
||||
#define CP2_FUNC(f) \
|
||||
void gte##f(); \
|
||||
static void rec##f() { \
|
||||
if (pc < cop2readypc) idlecyclecount += (cop2readypc - pc)>>2; \
|
||||
iFlushRegs(0); \
|
||||
LIW(0, (u32)psxRegs.code); \
|
||||
STW(0, OFFSET(&psxRegs, &psxRegs.code), GetHWRegSpecial(PSXREGS)); \
|
||||
FlushAllHWReg(); \
|
||||
CALLFunc ((u32)gte##f); \
|
||||
cop2readypc = pc + psxCP2time[_fFunct_(psxRegs.code)]<<2; \
|
||||
}
|
||||
|
||||
#define CP2_FUNCNC(f) \
|
||||
void gte##f(); \
|
||||
static void rec##f() { \
|
||||
if (pc < cop2readypc) idlecyclecount += (cop2readypc - pc)>>2; \
|
||||
iFlushRegs(0); \
|
||||
CALLFunc ((u32)gte##f); \
|
||||
/* branch = 2; */\
|
||||
cop2readypc = pc + psxCP2time[_fFunct_(psxRegs.code)]; \
|
||||
}
|
||||
|
||||
CP2_FUNC(MFC2);
|
||||
CP2_FUNC(MTC2);
|
||||
CP2_FUNC(CFC2);
|
||||
CP2_FUNC(CTC2);
|
||||
CP2_FUNC(LWC2);
|
||||
CP2_FUNC(SWC2);
|
||||
CP2_FUNCNC(RTPS);
|
||||
CP2_FUNC(OP);
|
||||
CP2_FUNCNC(NCLIP);
|
||||
CP2_FUNC(DPCS);
|
||||
CP2_FUNC(INTPL);
|
||||
CP2_FUNC(MVMVA);
|
||||
CP2_FUNCNC(NCDS);
|
||||
CP2_FUNCNC(NCDT);
|
||||
CP2_FUNCNC(CDP);
|
||||
CP2_FUNCNC(NCCS);
|
||||
CP2_FUNCNC(CC);
|
||||
CP2_FUNCNC(NCS);
|
||||
CP2_FUNCNC(NCT);
|
||||
CP2_FUNC(SQR);
|
||||
CP2_FUNC(DCPL);
|
||||
CP2_FUNCNC(DPCT);
|
||||
CP2_FUNCNC(AVSZ3);
|
||||
CP2_FUNCNC(AVSZ4);
|
||||
CP2_FUNCNC(RTPT);
|
||||
CP2_FUNC(GPF);
|
||||
CP2_FUNC(GPL);
|
||||
CP2_FUNCNC(NCCT);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,124 @@
|
|||
|
||||
|
||||
#define OLD_REGISTER_OFFSET (19*4)
|
||||
#define SP_SIZE (OLD_REGISTER_OFFSET+4+8)
|
||||
|
||||
/*asm void recRun(register void (*func)(), register u32 hw1, register u32 hw2)*/
|
||||
.text
|
||||
.align 4
|
||||
.globl recRun
|
||||
recRun:
|
||||
/* prologue code */
|
||||
mflr r0
|
||||
stmw r13, -(32-13)*4(r1)
|
||||
stw r0, 4(r1)
|
||||
stwu r1, -((32-13)*4+8)(r1)
|
||||
|
||||
/* execute code */
|
||||
mtctr r3
|
||||
mr r31, r4
|
||||
mr r30, r5
|
||||
bctrl
|
||||
/*
|
||||
}
|
||||
asm void returnPC()
|
||||
{*/
|
||||
.text
|
||||
.align 4
|
||||
.globl returnPC
|
||||
returnPC:
|
||||
// end code
|
||||
lwz r0, (32-13)*4+8+4(r1)
|
||||
addi r1, r1, (32-13)*4+8
|
||||
mtlr r0
|
||||
lmw r13, -(32-13)*4(r1)
|
||||
blr
|
||||
//}*/
|
||||
|
||||
// Memory functions that only works with a linear memory
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl dynMemRead8
|
||||
dynMemRead8:
|
||||
// assumes that memory pointer is in r30
|
||||
addis r2,r3,-0x1f80
|
||||
srwi. r4,r2,16
|
||||
bne+ .norm8
|
||||
cmplwi r2,0x1000
|
||||
blt- .norm8
|
||||
b psxHwRead8
|
||||
.norm8:
|
||||
clrlwi r5,r3,3
|
||||
lbzx r3,r5,r30
|
||||
blr
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl dynMemRead16
|
||||
dynMemRead16:
|
||||
// assumes that memory pointer is in r30
|
||||
addis r2,r3,-0x1f80
|
||||
srwi. r4,r2,16
|
||||
bne+ .norm16
|
||||
cmplwi r2,0x1000
|
||||
blt- .norm16
|
||||
b psxHwRead16
|
||||
.norm16:
|
||||
clrlwi r5,r3,3
|
||||
lhbrx r3,r5,r30
|
||||
blr
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl dynMemRead32
|
||||
dynMemRead32:
|
||||
// assumes that memory pointer is in r30
|
||||
addis r2,r3,-0x1f80
|
||||
srwi. r4,r2,16
|
||||
bne+ .norm32
|
||||
cmplwi r2,0x1000
|
||||
blt- .norm32
|
||||
b psxHwRead32
|
||||
.norm32:
|
||||
clrlwi r5,r3,3
|
||||
lwbrx r3,r5,r30
|
||||
blr
|
||||
|
||||
/*
|
||||
N P Z
|
||||
0 0 0 X
|
||||
- 0 0 1 X
|
||||
1 0 0 X
|
||||
1 0 1 X
|
||||
|
||||
P | (!N & Z)
|
||||
P | !(N | !Z)
|
||||
*/
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl dynMemWrite32
|
||||
dynMemWrite32:
|
||||
// assumes that memory pointer is in r30
|
||||
addis r2,r3,-0x1f80
|
||||
srwi. r5,r2,16
|
||||
bne+ .normw32
|
||||
cmplwi r2,0x1000
|
||||
blt .normw32
|
||||
b psxHwWrite32
|
||||
.normw32:
|
||||
mtcrf 0xFF, r3
|
||||
clrlwi r5,r3,3
|
||||
crandc 0, 2, 0
|
||||
cror 2, 1, 0
|
||||
bne+ .okw32
|
||||
// write test
|
||||
li r2,0x0130
|
||||
addis r2,r2,0xfffe
|
||||
cmplw r3,r2
|
||||
bnelr
|
||||
.okw32:
|
||||
stwbrx r4,r5,r30
|
||||
blr
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* ix86 core v0.5.1
|
||||
* Authors: linuzappz <linuzappz@pcsx.net>
|
||||
* alexey silinov
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ppc.h"
|
||||
|
||||
// General Purpose hardware registers
|
||||
int cpuHWRegisters[NUM_HW_REGISTERS] = {
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
};
|
||||
|
||||
u32 *ppcPtr;
|
||||
|
||||
void ppcInit() {
|
||||
}
|
||||
void ppcSetPtr(u32 *ptr) {
|
||||
ppcPtr = ptr;
|
||||
}
|
||||
void ppcAlign(int bytes) {
|
||||
// forward align
|
||||
ppcPtr = (u32*)(((u32)ppcPtr + bytes) & ~(bytes - 1));
|
||||
}
|
||||
|
||||
void ppcShutdown() {
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* ppc definitions v0.5.1
|
||||
* Authors: linuzappz <linuzappz@pcsx.net>
|
||||
* alexey silinov
|
||||
*/
|
||||
|
||||
#ifndef __PPC_H__
|
||||
#define __PPC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// include basic types
|
||||
#include "../psxcommon.h"
|
||||
#include "ppc_mnemonics.h"
|
||||
|
||||
#define NUM_HW_REGISTERS 29
|
||||
|
||||
/* general defines */
|
||||
#define write8(val) *(u8 *)ppcPtr = val; ppcPtr++;
|
||||
#define write16(val) *(u16*)ppcPtr = val; ppcPtr+=2;
|
||||
#define write32(val) *(u32*)ppcPtr = val; ppcPtr+=4;
|
||||
#define write64(val) *(u64*)ppcPtr = val; ppcPtr+=8;
|
||||
|
||||
#define CALLFunc(FUNC) \
|
||||
{ \
|
||||
u32 _func = (FUNC); \
|
||||
ReleaseArgs(); \
|
||||
if ((_func & 0x1fffffc) == _func) { \
|
||||
BLA(_func); \
|
||||
} else { \
|
||||
LIW(0, _func); \
|
||||
MTCTR(0); \
|
||||
BCTRL(); \
|
||||
} \
|
||||
}
|
||||
|
||||
extern int cpuHWRegisters[NUM_HW_REGISTERS];
|
||||
|
||||
extern u32 *ppcPtr;
|
||||
extern u8 *j8Ptr[32];
|
||||
extern u32 *j32Ptr[32];
|
||||
|
||||
void ppcInit();
|
||||
void ppcSetPtr(u32 *ptr);
|
||||
void ppcShutdown();
|
||||
|
||||
void ppcAlign(int bytes);
|
||||
void returnPC();
|
||||
void recRun(void (*func)(), u32 hw1, u32 hw2);
|
||||
u8 dynMemRead8(u32 mem);
|
||||
u16 dynMemRead16(u32 mem);
|
||||
u32 dynMemRead32(u32 mem);
|
||||
void dynMemWrite32(u32 mem, u32 val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,529 @@
|
|||
// ppc_mnemonics.h
|
||||
|
||||
#define INSTR (*(ppcPtr)++)
|
||||
|
||||
/* Link register related */
|
||||
#define MFLR(REG) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x7C0802A6 | (_reg << 21));}
|
||||
|
||||
#define MTLR(REG) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x7C0803A6 | (_reg << 21));}
|
||||
|
||||
#define MTCTR(REG) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x7C0903A6 | (_reg << 21));}
|
||||
|
||||
#define BLR() \
|
||||
{INSTR = (0x4E800020);}
|
||||
|
||||
#define BGTLR() \
|
||||
{INSTR = (0x4D810020);}
|
||||
|
||||
|
||||
/* Load ops */
|
||||
#define LI(REG, IMM) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x38000000 | (_reg << 21) | ((IMM) & 0xffff));}
|
||||
|
||||
#define LIS(REG_DST, IMM) \
|
||||
{int _dst = (REG_DST); \
|
||||
INSTR = (0x3C000000 | (_dst << 21) | ((IMM) & 0xffff));}
|
||||
|
||||
#define LWZ(REG_DST, OFFSET, REG) \
|
||||
{int _reg = (REG); int _dst=(REG_DST); \
|
||||
INSTR = (0x80000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define LWZX(REG_DST, REG, REG_OFF) \
|
||||
{int _reg = (REG), _off = (REG_OFF); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C00002E | (_dst << 21) | (_reg << 16) | (_off << 11));}
|
||||
|
||||
#define LWBRX(REG_DST, REG, REG_OFF) \
|
||||
{int _reg = (REG), _off = (REG_OFF); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C00042C | (_dst << 21) | (_reg << 16) | (_off << 11));}
|
||||
|
||||
#define LHZ(REG_DST, OFFSET, REG) \
|
||||
{int _reg = (REG); int _dst=(REG_DST); \
|
||||
INSTR = (0xA0000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define LHA(REG_DST, OFFSET, REG) \
|
||||
{int _reg = (REG); int _dst=(REG_DST); \
|
||||
INSTR = (0xA8000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define LHBRX(REG_DST, REG, REG_OFF) \
|
||||
{int _reg = (REG), _off = (REG_OFF); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C00062C | (_dst << 21) | (_reg << 16) | (_off << 11));}
|
||||
|
||||
#define LBZ(REG_DST, OFFSET, REG) \
|
||||
{int _reg = (REG); int _dst=(REG_DST); \
|
||||
INSTR = (0x88000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define LMW(REG_DST, OFFSET, REG) \
|
||||
{int _reg = (REG); int _dst=(REG_DST); \
|
||||
INSTR = (0xB8000000 | (_dst << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
|
||||
|
||||
/* Store ops */
|
||||
#define STMW(REG_SRC, OFFSET, REG) \
|
||||
{int _reg = (REG), _src=(REG_SRC); \
|
||||
INSTR = (0xBC000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define STW(REG_SRC, OFFSET, REG) \
|
||||
{int _reg = (REG), _src=(REG_SRC); \
|
||||
INSTR = (0x90000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define STWBRX(REG_SRC, REG, REG_OFF) \
|
||||
{int _reg = (REG), _src=(REG_SRC), _off = (REG_OFF); \
|
||||
INSTR = (0x7C00052C | (_src << 21) | (_reg << 16) | (_off << 11));}
|
||||
|
||||
#define STH(REG_SRC, OFFSET, REG) \
|
||||
{int _reg = (REG), _src=(REG_SRC); \
|
||||
INSTR = (0xB0000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define STHBRX(REG_SRC, REG, REG_OFF) \
|
||||
{int _reg = (REG), _src=(REG_SRC), _off = (REG_OFF); \
|
||||
INSTR = (0x7C00072C | (_src << 21) | (_reg << 16) | (_off << 11));}
|
||||
|
||||
#define STB(REG_SRC, OFFSET, REG) \
|
||||
{int _reg = (REG), _src=(REG_SRC); \
|
||||
INSTR = (0x98000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define STWU(REG_SRC, OFFSET, REG) \
|
||||
{int _reg = (REG), _src=(REG_SRC); \
|
||||
INSTR = (0x94000000 | (_src << 21) | (_reg << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
|
||||
/* Arithmic ops */
|
||||
#define ADDI(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x38000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define ADDIS(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x3C000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define MR(REG_DST, REG_SRC) \
|
||||
{int __src = (REG_SRC); int __dst=(REG_DST); \
|
||||
if (__src != __dst) {ADDI(__dst, __src, 0)}}
|
||||
|
||||
#define ADD(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000214 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define ADDO(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000614 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define ADDEO(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000514 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define ADDE(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000114 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define ADDCO(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000414 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define ADDIC(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x30000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define ADDIC_(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x34000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define ADDZE(REG_DST, REG_SRC) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000194 | (_dst << 21) | (_src << 16));}
|
||||
|
||||
#define SUBF(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000050 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define SUBFO(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000450 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define SUBFC(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000010 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define SUBFE(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000110 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define SUBFCO(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000410 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define SUBFCO_(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000411 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define SUB(REG_DST, REG1, REG2) \
|
||||
{SUBF(REG_DST, REG2, REG1)}
|
||||
|
||||
#define SUBO(REG_DST, REG1, REG2) \
|
||||
{SUBFO(REG_DST, REG2, REG1)}
|
||||
|
||||
#define SUBCO(REG_DST, REG1, REG2) \
|
||||
{SUBFCO(REG_DST, REG2, REG1)}
|
||||
|
||||
#define SUBCO_(REG_DST, REG1, REG2) \
|
||||
{SUBFCO_(REG_DST, REG2, REG1)}
|
||||
|
||||
#define SRAWI(REG_DST, REG_SRC, SHIFT) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000670 | (_src << 21) | (_dst << 16) | (SHIFT << 11));}
|
||||
|
||||
#define MULHW(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000096 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define MULLW(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C0001D6 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define MULHWU(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000016 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define MULLI(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x1C000000 | (_dst << 21) | (_src << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define DIVW(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C0003D6 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define DIVWU(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000396 | (_dst << 21) | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
|
||||
/* Branch ops */
|
||||
#define B_FROM(VAR) VAR = ppcPtr
|
||||
#define B_DST(VAR) *VAR = *VAR | (((s16)((u32)ppcPtr - (u32)VAR)) & 0xfffc)
|
||||
|
||||
#define B(DST) \
|
||||
{INSTR = (0x48000000 | (((s32)(((DST)+1)<<2)) & 0x3fffffc));}
|
||||
|
||||
#define B_L(VAR) \
|
||||
{B_FROM(VAR); INSTR = (0x48000000);}
|
||||
|
||||
#define BA(DST) \
|
||||
{INSTR = (0x48000002 | ((s32)((DST) & 0x3fffffc)));}
|
||||
|
||||
#define BLA(DST) \
|
||||
{INSTR = (0x48000003 | ((s32)((DST) & 0x3fffffc)));}
|
||||
|
||||
#define BNS(DST) \
|
||||
{INSTR = (0x40830000 | (((s16)(((DST)+1)<<2)) & 0xfffc));}
|
||||
|
||||
#define BNE(DST) \
|
||||
{INSTR = (0x40820000 | (((s16)(((DST)+1)<<2)) & 0xfffc));}
|
||||
|
||||
#define BNE_L(VAR) \
|
||||
{B_FROM(VAR); INSTR = (0x40820000);}
|
||||
|
||||
#define BEQ(DST) \
|
||||
{INSTR = (0x41820000 | (((s16)(((DST)+1)<<2)) & 0xfffc));}
|
||||
|
||||
#define BEQ_L(VAR) \
|
||||
{B_FROM(VAR); INSTR = (0x41820000);}
|
||||
|
||||
#define BLT(DST) \
|
||||
{INSTR = (0x41800000 | (((s16)(((DST)+1)<<2)) & 0xfffc));}
|
||||
|
||||
#define BLT_L(VAR) \
|
||||
{B_FROM(VAR); INSTR = (0x41800000);}
|
||||
|
||||
#define BGT(DST) \
|
||||
{INSTR = (0x41810000 | (((s16)(((DST)+1)<<2)) & 0xfffc));}
|
||||
|
||||
#define BGT_L(VAR) \
|
||||
{B_FROM(VAR); INSTR = (0x41810000);}
|
||||
|
||||
#define BGE(DST) \
|
||||
{INSTR = (0x40800000 | (((s16)(((DST)+1)<<2)) & 0xfffc));}
|
||||
|
||||
#define BGE_L(VAR) \
|
||||
{B_FROM(VAR); INSTR = (0x40800000);}
|
||||
|
||||
#define BLE(DST) \
|
||||
{INSTR = (0x40810000 | (((s16)(((DST)+1)<<2)) & 0xfffc));}
|
||||
|
||||
#define BLE_L(VAR) \
|
||||
{B_FROM(VAR); INSTR = (0x40810000);}
|
||||
|
||||
#define BCTRL() \
|
||||
{INSTR = (0x4E800421);}
|
||||
|
||||
#define BCTR() \
|
||||
{INSTR = (0x4E800420);}
|
||||
|
||||
|
||||
/* compare ops */
|
||||
#define CMPLWI(REG, IMM) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x28000000 | (_reg << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define CMPLWI2(REG, IMM) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x29000000 | (_reg << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define CMPLWI7(REG, IMM) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x2B800000 | (_reg << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define CMPLW(REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); \
|
||||
INSTR = (0x7C000040 | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define CMPLW1(REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); \
|
||||
INSTR = (0x7C800040 | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define CMPLW2(REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); \
|
||||
INSTR = (0x7D000040 | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define CMPW(REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); \
|
||||
INSTR = (0x7C000000 | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define CMPW1(REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); \
|
||||
INSTR = (0x7C800000 | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define CMPW2(REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); \
|
||||
INSTR = (0x7D000000 | (_reg1 << 16) | (_reg2 << 11));}
|
||||
|
||||
#define CMPWI(REG, IMM) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x2C000000 | (_reg << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define CMPWI2(REG, IMM) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x2D000000 | (_reg << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define MTCRF(MASK, REG) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x7C000120 | (_reg << 21) | (((MASK)&0xff)<<12));}
|
||||
|
||||
#define MFCR(REG) \
|
||||
{int _reg = (REG); \
|
||||
INSTR = (0x7C000026 | (_reg << 21));}
|
||||
|
||||
#define CROR(CR_DST, CR1, CR2) \
|
||||
{INSTR = (0x4C000382 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));}
|
||||
|
||||
#define CRXOR(CR_DST, CR1, CR2) \
|
||||
{INSTR = (0x4C000182 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));}
|
||||
|
||||
#define CRNAND(CR_DST, CR1, CR2) \
|
||||
{INSTR = (0x4C0001C2 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));}
|
||||
|
||||
#define CRANDC(CR_DST, CR1, CR2) \
|
||||
{INSTR = (0x4C000102 | ((CR_DST) << 21) | ((CR1) << 16) | ((CR2) << 11));}
|
||||
|
||||
|
||||
/* shift ops */
|
||||
#define RLWINM(REG_DST, REG_SRC, SHIFT, START, END) \
|
||||
{int _src = (REG_SRC); int _dst = (REG_DST); \
|
||||
INSTR = (0x54000000 | (_src << 21) | (_dst << 16) | (SHIFT << 11) | (START << 6) | (END << 1));}
|
||||
|
||||
#define RLWINM_(REG_DST, REG_SRC, SHIFT, START, END) \
|
||||
{int _src = (REG_SRC); int _dst = (REG_DST); \
|
||||
INSTR = (0x54000001 | (_src << 21) | (_dst << 16) | (SHIFT << 11) | (START << 6) | (END << 1));}
|
||||
|
||||
#define CLRRWI(REG_DST, REG_SRC, LEN) \
|
||||
RLWINM(REG_DST, REG_SRC, 0, 0, 31-LEN)
|
||||
|
||||
#define SLWI(REG_DST, REG_SRC, SHIFT) \
|
||||
{int _shift = (SHIFT); \
|
||||
if (_shift==0) {MR(REG_DST, REG_SRC)} else \
|
||||
{RLWINM(REG_DST, REG_SRC, _shift, 0, 31-_shift)}}
|
||||
|
||||
#define SRWI(REG_DST, REG_SRC, SHIFT) \
|
||||
{int _shift = (SHIFT); \
|
||||
if (_shift==0) {MR(REG_DST, REG_SRC)} else \
|
||||
RLWINM(REG_DST, REG_SRC, 32-_shift, _shift, 31)}
|
||||
|
||||
#define SLW(REG_DST, REG_SRC, REG_SHIFT) \
|
||||
{int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \
|
||||
INSTR = (0x7C000030 | (_src << 21) | (_dst << 16) | (_shift << 11));}
|
||||
|
||||
#define SRW(REG_DST, REG_SRC, REG_SHIFT) \
|
||||
{int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \
|
||||
INSTR = (0x7C000430 | (_src << 21) | (_dst << 16) | (_shift << 11));}
|
||||
|
||||
#define SRAW(REG_DST, REG_SRC, REG_SHIFT) \
|
||||
{int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \
|
||||
INSTR = (0x7C000630 | (_src << 21) | (_dst << 16) | (_shift << 11));}
|
||||
|
||||
#define SRAWI(REG_DST, REG_SRC, SHIFT) \
|
||||
{int _src = (REG_SRC); int _dst = (REG_DST); int _shift = (SHIFT); \
|
||||
if (_shift==0) {MR(REG_DST, REG_SRC)} else \
|
||||
INSTR = (0x7C000670 | (_src << 21) | (_dst << 16) | (_shift << 11));}
|
||||
|
||||
#define RLWNM(REG_DST, REG_SRC, REG_SHIFT, START, END) \
|
||||
{int _src = (REG_SRC), _shift = (REG_SHIFT); int _dst = (REG_DST); \
|
||||
INSTR = (0x5C000000 | (_src << 21) | (_dst << 16) | (_shift << 11) | (START << 6) | (END << 1));}
|
||||
|
||||
/* other ops */
|
||||
#define ORI(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC), _imm = (IMM); int _dst = (REG_DST); \
|
||||
if (!((_imm == 0) && ((_src^_dst) == 0))) \
|
||||
INSTR = (0x60000000 | (_src << 21) | (_dst << 16) | (_imm & 0xffff));}
|
||||
|
||||
#define ORIS(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC), _imm = (IMM); int _dst = (REG_DST); \
|
||||
if (!((_imm == 0) && ((_src^_dst) == 0))) \
|
||||
INSTR = (0x64000000 | (_src << 21) | (_dst << 16) | (_imm & 0xffff));}
|
||||
|
||||
#define OR(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000378 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));}
|
||||
|
||||
#define OR_(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000379 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));}
|
||||
|
||||
#define XORI(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x68000000 | (_src << 21) | (_dst << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define XOR(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000278 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));}
|
||||
|
||||
#define XOR_(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000279 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));}
|
||||
|
||||
#define ANDI_(REG_DST, REG_SRC, IMM) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x70000000 | (_src << 21) | (_dst << 16) | ((IMM) & 0xffff));}
|
||||
|
||||
#define AND(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000038 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));}
|
||||
|
||||
#define NOR(REG_DST, REG1, REG2) \
|
||||
{int _reg1 = (REG1), _reg2 = (REG2); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C0000f8 | (_reg1 << 21) | (_dst << 16) | (_reg2 << 11));}
|
||||
|
||||
#define NEG(REG_DST, REG_SRC) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C0000D0 | (_dst << 21) | (_src << 16));}
|
||||
|
||||
#define NOP() \
|
||||
{INSTR = 0x60000000;}
|
||||
|
||||
#define MCRXR(CR_DST) \
|
||||
{INSTR = (0x7C000400 | (CR_DST << 23));}
|
||||
|
||||
#define EXTSB(REG_DST, REG_SRC) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000774 | (_src << 21) | (_dst << 16));}
|
||||
|
||||
#define EXTSH(REG_DST, REG_SRC) \
|
||||
{int _src = (REG_SRC); int _dst=(REG_DST); \
|
||||
INSTR = (0x7C000734 | (_src << 21) | (_dst << 16));}
|
||||
|
||||
|
||||
/* floating point ops */
|
||||
#define FDIVS(FPR_DST, FPR1, FPR2) \
|
||||
{INSTR = (0xEC000024 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));}
|
||||
|
||||
#define FDIV(FPR_DST, FPR1, FPR2) \
|
||||
{INSTR = (0xFC000024 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));}
|
||||
|
||||
#define FMULS(FPR_DST, FPR1, FPR2) \
|
||||
{INSTR = (0xEC000032 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));}
|
||||
|
||||
#define FMUL(FPR_DST, FPR1, FPR2) \
|
||||
{INSTR = (0xFC000032 | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));}
|
||||
|
||||
#define FADDS(FPR_DST, FPR1, FPR2) \
|
||||
{INSTR = (0xEC00002A | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));}
|
||||
|
||||
#define FADD(FPR_DST, FPR1, FPR2) \
|
||||
{INSTR = (0xFC00002A | (FPR_DST << 21) | (FPR1 << 16) | (FPR2 << 11));}
|
||||
|
||||
#define FRSP(FPR_DST, FPR_SRC) \
|
||||
{INSTR = (0xFC000018 | (FPR_DST << 21) | (FPR_SRC << 11));}
|
||||
|
||||
#define FCTIW(FPR_DST, FPR_SRC) \
|
||||
{INSTR = (0xFC00001C | (FPR_DST << 21) | (FPR_SRC << 11));}
|
||||
|
||||
|
||||
#define LFS(FPR_DST, OFFSET, REG) \
|
||||
{INSTR = (0xC0000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define STFS(FPR_DST, OFFSET, REG) \
|
||||
{INSTR = (0xD0000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define LFD(FPR_DST, OFFSET, REG) \
|
||||
{INSTR = (0xC8000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
#define STFD(FPR_DST, OFFSET, REG) \
|
||||
{INSTR = (0xD8000000 | (FPR_DST << 21) | (REG << 16) | ((OFFSET) & 0xffff));}
|
||||
|
||||
|
||||
|
||||
/* extra combined opcodes */
|
||||
#if 1
|
||||
#define LIW(REG, IMM) /* Load Immidiate Word */ \
|
||||
{ \
|
||||
int __reg = (REG); u32 __imm = (u32)(IMM); \
|
||||
if ((s32)__imm == (s32)((s16)__imm)) \
|
||||
{ \
|
||||
LI(__reg, (s32)((s16)__imm)); \
|
||||
} else if (__reg == 0) { \
|
||||
LIS(__reg, (((u32)__imm)>>16)); \
|
||||
if ((((u32)__imm) & 0xffff) != 0) \
|
||||
{ \
|
||||
ORI(__reg, __reg, __imm); \
|
||||
} \
|
||||
} else { \
|
||||
if ((((u32)__imm) & 0xffff) == 0) { \
|
||||
LIS(__reg, (((u32)__imm)>>16)); \
|
||||
} else { \
|
||||
LI(__reg, __imm); \
|
||||
if ((__imm & 0x8000) == 0) { \
|
||||
ADDIS(__reg, __reg, ((u32)__imm)>>16); \
|
||||
} else { \
|
||||
ADDIS(__reg, __reg, ((((u32)__imm)>>16) & 0xffff) + 1); \
|
||||
} \
|
||||
} \
|
||||
/*if ((((u32)__imm) & 0xffff) != 0) \
|
||||
{ \
|
||||
ORI(__reg, __reg, __imm); \
|
||||
}*/ \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define LIW(REG, IMM) /* Load Immidiate Word */ \
|
||||
{ \
|
||||
int __reg = (REG); u32 __imm = (u32)(IMM); \
|
||||
if ((s32)__imm == (s32)((s16)__imm)) \
|
||||
{ \
|
||||
LI(__reg, (s32)((s16)__imm)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
LIS(__reg, (((u32)__imm)>>16)); \
|
||||
if ((((u32)__imm) & 0xffff) != 0) \
|
||||
{ \
|
||||
ORI(__reg, __reg, __imm); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,419 @@
|
|||
|
||||
#include "../psxcommon.h"
|
||||
#include "reguse.h"
|
||||
|
||||
#include "../r3000a.h"
|
||||
|
||||
//#define SAME_CYCLE_MODE
|
||||
|
||||
static const int useBSC[64] = {
|
||||
/*recSPECIAL*/ REGUSE_SUB | REGUSE_SPECIAL,
|
||||
/*recREGIMM*/ REGUSE_SUB | REGUSE_REGIMM,
|
||||
/*recJ*/ REGUSE_JUMP,
|
||||
/*recJAL*/ REGUSE_JUMP | REGUSE_R31_W,
|
||||
/*recBEQ*/ REGUSE_BRANCH | REGUSE_RS_R | REGUSE_RT_R,
|
||||
/*recBNE*/ REGUSE_BRANCH | REGUSE_RS_R | REGUSE_RT_R,
|
||||
/*recBLEZ*/ REGUSE_BRANCH | REGUSE_RS_R,
|
||||
/*recBGTZ*/ REGUSE_BRANCH | REGUSE_RS_R,
|
||||
/*recADDI*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recADDIU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recSLTI*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recSLTIU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recANDI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recORI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recXORI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recLUI*/ REGUSE_ACC | REGUSE_RT_W,
|
||||
/*recCOP0*/ REGUSE_SUB | REGUSE_COP0,
|
||||
REGUSE_NONE,
|
||||
/*recCOP2*/ REGUSE_SUB | REGUSE_COP2,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recLB*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recLH*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recLWL*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT,
|
||||
/*recLW*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recLBU*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recLHU*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT_W,
|
||||
/*recLWR*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_RT,
|
||||
REGUSE_NONE,
|
||||
/*recSB*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_RT_R,
|
||||
/*recSH*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_RT_R,
|
||||
/*recSWL*/ REGUSE_MEM | REGUSE_RS_R | REGUSE_RT_R,
|
||||
/*recSW*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_RT_R,
|
||||
REGUSE_NONE, REGUSE_NONE,
|
||||
/*recSWR*/ REGUSE_MEM | REGUSE_RS_R | REGUSE_RT_R,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recLWC2*/ REGUSE_MEM_R | REGUSE_RS_R | REGUSE_COP2_RT_W,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE,
|
||||
/*recSWC2*/ REGUSE_MEM_W | REGUSE_RS_R | REGUSE_COP2_RT_R,
|
||||
/*recHLE*/ REGUSE_UNKNOWN, // TODO: can this be done in a better way
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE
|
||||
};
|
||||
|
||||
static const int useSPC[64] = {
|
||||
/*recSLL*/ REGUSE_ACC | REGUSE_RT_R | REGUSE_RD_W,
|
||||
REGUSE_NONE,
|
||||
/*recSRL*/ REGUSE_ACC | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recSRA*/ REGUSE_ACC | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recSLLV*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
REGUSE_NONE,
|
||||
/*recSRLV*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recSRAV*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recJR*/ REGUSE_JUMPR | REGUSE_RS_R,
|
||||
/*recJALR*/ REGUSE_JUMPR | REGUSE_RS_R | REGUSE_RD_W,
|
||||
REGUSE_NONE, REGUSE_NONE,
|
||||
/*rSYSCALL*/ REGUSE_SYS | REGUSE_PC | REGUSE_COP0_STATUS | REGUSE_EXCEPTION,
|
||||
/*recBREAK*/ REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE,
|
||||
/*recMFHI*/ REGUSE_LOGIC | REGUSE_RD_W | REGUSE_HI_R,
|
||||
/*recMTHI*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_HI_W,
|
||||
/*recMFLO*/ REGUSE_LOGIC | REGUSE_RD_W | REGUSE_LO_R,
|
||||
/*recMTLO*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_LO_W,
|
||||
REGUSE_NONE, REGUSE_NONE , REGUSE_NONE, REGUSE_NONE,
|
||||
/*recMULT*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W,
|
||||
/*recMULTU*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W,
|
||||
/*recDIV*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W,
|
||||
/*recDIVU*/ REGUSE_MULT | REGUSE_RS_R | REGUSE_RT_R | REGUSE_LO_W | REGUSE_HI_W,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recADD*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recADDU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recSUB*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recSUBU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recAND*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recOR*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recXOR*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recNOR*/ REGUSE_LOGIC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
REGUSE_NONE, REGUSE_NONE,
|
||||
/*recSLT*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
/*recSLTU*/ REGUSE_ACC | REGUSE_RS_R | REGUSE_RT_R | REGUSE_RD_W,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE
|
||||
};
|
||||
|
||||
static const int useREGIMM[32] = {
|
||||
/*recBLTZ*/ REGUSE_BRANCH | REGUSE_RS_R,
|
||||
/*recBGEZ*/ REGUSE_BRANCH | REGUSE_RS_R,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE,
|
||||
/*recBLTZAL*/REGUSE_BRANCH | REGUSE_RS_R | REGUSE_R31_W,
|
||||
/*recBGEZAL*/REGUSE_BRANCH | REGUSE_RS_R | REGUSE_R31_W,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE
|
||||
};
|
||||
|
||||
static const int useCP0[32] = {
|
||||
/*recMFC0*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP0_RD_R,
|
||||
REGUSE_NONE,
|
||||
/*recCFC0*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP0_RD_R,
|
||||
REGUSE_NONE,
|
||||
/*recMTC0*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP0_RD_W,
|
||||
REGUSE_NONE,
|
||||
/*recCTC0*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP0_RD_W,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recRFE*/ REGUSE_LOGIC | REGUSE_COP0_STATUS,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE
|
||||
};
|
||||
|
||||
// TODO: make more explicit
|
||||
static const int useCP2[64] = {
|
||||
/*recBASIC*/ REGUSE_SUB | REGUSE_BASIC,
|
||||
/*recRTPS*/ REGUSE_GTE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recNCLIP*/ REGUSE_GTE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recOP*/ REGUSE_GTE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recDPCS*/ REGUSE_GTE,
|
||||
/*recINTPL*/ REGUSE_GTE,
|
||||
/*recMVMVA*/ REGUSE_GTE,
|
||||
/*recNCDS*/ REGUSE_GTE,
|
||||
/*recCDP*/ REGUSE_GTE,
|
||||
REGUSE_NONE,
|
||||
/*recNCDT*/ REGUSE_GTE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recNCCS*/ REGUSE_GTE,
|
||||
/*recCC*/ REGUSE_GTE,
|
||||
REGUSE_NONE,
|
||||
/*recNCS*/ REGUSE_GTE,
|
||||
REGUSE_NONE,
|
||||
/*recNCT*/ REGUSE_GTE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
/*recSQR*/ REGUSE_GTE,
|
||||
/*recDCPL*/ REGUSE_GTE,
|
||||
/*recDPCT*/ REGUSE_GTE,
|
||||
REGUSE_NONE, REGUSE_NONE,
|
||||
/*recAVSZ3*/ REGUSE_GTE,
|
||||
/*recAVSZ4*/ REGUSE_GTE,
|
||||
REGUSE_NONE,
|
||||
/*recRTPT*/ REGUSE_GTE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE, REGUSE_NONE,
|
||||
/*recGPF*/ REGUSE_GTE,
|
||||
/*recGPL*/ REGUSE_GTE,
|
||||
/*recNCCT*/ REGUSE_GTE
|
||||
};
|
||||
|
||||
static const int useCP2BSC[32] = {
|
||||
/*recMFC2*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP2_RD_R,
|
||||
REGUSE_NONE,
|
||||
/*recCFC2*/ REGUSE_LOGIC | REGUSE_RT_W | REGUSE_COP2_RD_R,
|
||||
REGUSE_NONE,
|
||||
/*recMTC2*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP2_RD_W,
|
||||
REGUSE_NONE,
|
||||
/*recCTC2*/ REGUSE_LOGIC | REGUSE_RT_R | REGUSE_COP2_RD_W,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE,
|
||||
REGUSE_NONE
|
||||
};
|
||||
|
||||
static int getRegUse(u32 code) __attribute__ ((__pure__));
|
||||
static int getRegUse(u32 code)
|
||||
{
|
||||
int use = useBSC[code>>26];
|
||||
|
||||
switch (use & REGUSE_SUBMASK) {
|
||||
case REGUSE_NONE:
|
||||
break;
|
||||
case REGUSE_SPECIAL:
|
||||
use = useSPC[_fFunct_(code)];
|
||||
break;
|
||||
case REGUSE_REGIMM:
|
||||
use = useREGIMM[_fRt_(code)];
|
||||
break;
|
||||
case REGUSE_COP0:
|
||||
use = useCP0[_fRs_(code)];
|
||||
break;
|
||||
case REGUSE_COP2:
|
||||
use = useCP2[_fFunct_(code)];
|
||||
if ((use & REGUSE_SUBMASK) == REGUSE_BASIC)
|
||||
use = useCP2BSC[_fRs_(code)];
|
||||
break;
|
||||
default:
|
||||
use = REGUSE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((use & REGUSE_COP0_RD_W)) {
|
||||
if (_fRd_(code) == 12 || _fRd_(code) == 13) {
|
||||
use = REGUSE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
return use;
|
||||
}
|
||||
|
||||
/* returns how psxreg is used in the code instruction */
|
||||
int useOfPsxReg(u32 code, int use, int psxreg)
|
||||
{
|
||||
int retval = REGUSE_NONE;
|
||||
|
||||
// get use if it wasn't supplied
|
||||
if (-1 == use) use = getRegUse(code);
|
||||
|
||||
// if we don't know what the usage is, assume it's read from
|
||||
if (REGUSE_UNKNOWN == use) return REGUSE_READ;
|
||||
|
||||
if (psxreg < 32) {
|
||||
// check for 3 standard types
|
||||
if ((use & REGUSE_RT) && _fRt_(code) == (u32)psxreg) {
|
||||
retval |= ((use & REGUSE_RT_R) ? REGUSE_READ:0) | ((use & REGUSE_RT_W) ? REGUSE_WRITE:0);
|
||||
}
|
||||
if ((use & REGUSE_RS) && _fRs_(code) == (u32)psxreg) {
|
||||
retval |= ((use & REGUSE_RS_R) ? REGUSE_READ:0) | ((use & REGUSE_RS_W) ? REGUSE_WRITE:0);
|
||||
}
|
||||
if ((use & REGUSE_RD) && _fRd_(code) == (u32)psxreg) {
|
||||
retval |= ((use & REGUSE_RD_R) ? REGUSE_READ:0) | ((use & REGUSE_RD_W) ? REGUSE_WRITE:0);
|
||||
}
|
||||
// some instructions explicitly writes to r31
|
||||
if ((use & REGUSE_R31_W) && 31 == psxreg) {
|
||||
retval |= REGUSE_WRITE;
|
||||
}
|
||||
} else if (psxreg == 32) { // Special register LO
|
||||
retval |= ((use & REGUSE_LO_R) ? REGUSE_READ:0) | ((use & REGUSE_LO_W) ? REGUSE_WRITE:0);
|
||||
} else if (psxreg == 33) { // Special register HI
|
||||
retval |= ((use & REGUSE_HI_R) ? REGUSE_READ:0) | ((use & REGUSE_HI_W) ? REGUSE_WRITE:0);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
//#define NOREGUSE_FOLLOW
|
||||
|
||||
static int _nextPsxRegUse(u32 pc, int psxreg, int numInstr) __attribute__ ((__pure__, __unused__));
|
||||
static int _nextPsxRegUse(u32 pc, int psxreg, int numInstr)
|
||||
{
|
||||
u32 *ptr, code, bPC = 0;
|
||||
int i, use, reguse = 0;
|
||||
|
||||
for (i=0; i<numInstr; ) {
|
||||
// load current instruction
|
||||
ptr = PSXM(pc);
|
||||
if (ptr==NULL) {
|
||||
// going nowhere... might as well assume a write, since we will hopefully never reach here
|
||||
reguse = REGUSE_WRITE;
|
||||
break;
|
||||
}
|
||||
code = SWAP32(*ptr);
|
||||
// get usage patterns for instruction
|
||||
use = getRegUse(code);
|
||||
// find the use of psxreg in the instruction
|
||||
reguse = useOfPsxReg(code, use, psxreg);
|
||||
|
||||
// return if we have found a use
|
||||
if (reguse != REGUSE_NONE)
|
||||
break;
|
||||
|
||||
// goto next instruction
|
||||
pc += 4;
|
||||
i++;
|
||||
|
||||
// check for code branches/jumps
|
||||
if (i != numInstr) {
|
||||
if ((use & REGUSE_TYPEM) == REGUSE_BRANCH) {
|
||||
#ifndef NOREGUSE_FOLLOW
|
||||
// check delay slot
|
||||
reguse = _nextPsxRegUse(pc, psxreg, 1);
|
||||
if (reguse != REGUSE_NONE) break;
|
||||
|
||||
bPC = _fImm_(code) * 4 + pc;
|
||||
reguse = _nextPsxRegUse(pc+4, psxreg, (numInstr-i-1)/2);
|
||||
if (reguse != REGUSE_NONE) {
|
||||
int reguse2 = _nextPsxRegUse(bPC, psxreg, (numInstr-i-1)/2);
|
||||
if (reguse2 != REGUSE_NONE)
|
||||
reguse |= reguse2;
|
||||
else
|
||||
reguse = REGUSE_NONE;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
} else if ((use & REGUSE_TYPEM) == REGUSE_JUMP) {
|
||||
#ifndef NOREGUSE_FOLLOW
|
||||
// check delay slot
|
||||
reguse = _nextPsxRegUse(pc, psxreg, 1);
|
||||
if (reguse != REGUSE_NONE) break;
|
||||
|
||||
bPC = _fTarget_(code) * 4 + (pc & 0xf0000000);
|
||||
reguse = _nextPsxRegUse(bPC, psxreg, numInstr-i-1);
|
||||
#endif
|
||||
break;
|
||||
} else if ((use & REGUSE_TYPEM) == REGUSE_JUMPR) {
|
||||
#ifndef NOREGUSE_FOLLOW
|
||||
// jump to unknown location - bail after checking delay slot
|
||||
reguse = _nextPsxRegUse(pc, psxreg, 1);
|
||||
#endif
|
||||
break;
|
||||
} else if ((use & REGUSE_TYPEM) == REGUSE_SYS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reguse;
|
||||
}
|
||||
|
||||
|
||||
int nextPsxRegUse(u32 pc, int psxreg)
|
||||
{
|
||||
#if 1
|
||||
if (psxreg == 0)
|
||||
return REGUSE_WRITE; // pretend we are writing to it to fool compiler
|
||||
|
||||
#ifdef SAME_CYCLE_MODE
|
||||
return REGUSE_READ;
|
||||
#else
|
||||
return _nextPsxRegUse(pc, psxreg, 80);
|
||||
#endif
|
||||
#else
|
||||
u32 code, bPC = 0;
|
||||
int use, reguse = 0, reguse1 = 0, b = 0, i, index = 0;
|
||||
|
||||
retry:
|
||||
for (i=index; i<80; i++) {
|
||||
code = PSXMu32(pc);
|
||||
use = getRegUse(code);
|
||||
reguse = useOfPsxReg(code, use, psxreg);
|
||||
|
||||
if (reguse != REGUSE_NONE) break;
|
||||
|
||||
pc += 4;
|
||||
if ((use & REGUSE_TYPEM) == REGUSE_BRANCH) {
|
||||
if (b == 0) {
|
||||
bPC = _fImm_(code) * 4 + pc;
|
||||
index = i+1;
|
||||
}
|
||||
b += 1; // TODO: follow branches
|
||||
continue;
|
||||
} else if ((use & REGUSE_TYPEM) == REGUSE_JUMP) {
|
||||
if (b == 0) {
|
||||
bPC = _fTarget_(code) * 4 + (pc & 0xf0000000);
|
||||
}
|
||||
b = 2;
|
||||
continue;
|
||||
} else if ((use & REGUSE_TYPEM) == REGUSE_JUMPR ||
|
||||
(use & REGUSE_TYPEM) == REGUSE_SYS) {
|
||||
b = 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 2 && bPC && index == 0) {
|
||||
pc = bPC; bPC = 0;
|
||||
b = 1;
|
||||
}
|
||||
if (b >= 2) break; // only follow 1 branch
|
||||
}
|
||||
if (reguse == REGUSE_NONE) return reguse;
|
||||
|
||||
if (bPC) {
|
||||
reguse1 = reguse;
|
||||
pc = bPC; bPC = 0;
|
||||
b = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
return reguse1 | reguse;
|
||||
#endif
|
||||
}
|
||||
|
||||
int isPsxRegUsed(u32 pc, int psxreg)
|
||||
{
|
||||
int use = nextPsxRegUse(pc, psxreg);
|
||||
|
||||
if (use == REGUSE_NONE)
|
||||
return 2; // unknown use - assume it is used
|
||||
else if (use & REGUSE_READ)
|
||||
return 1; // the next use is a read
|
||||
else
|
||||
return 0; // the next use is a write, i.e. current value is not important
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef __REGUSE_H__
|
||||
#define __REGUSE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// include basic types
|
||||
#include "../psxcommon.h"
|
||||
|
||||
#define REGUSE_NONE 0x0000
|
||||
#define REGUSE_UNKNOWN 0x0001
|
||||
|
||||
//sub functions
|
||||
#define REGUSE_SPECIAL 0x0002
|
||||
#define REGUSE_REGIMM 0x0004
|
||||
#define REGUSE_COP0 0x0006
|
||||
#define REGUSE_COP2 0x0008
|
||||
#define REGUSE_BASIC 0x000a
|
||||
#define REGUSE_SUBMASK 0x000e /* sub function mask */
|
||||
|
||||
#define REGUSE_ACC 0x0010 /* accumulator */
|
||||
#define REGUSE_LOGIC 0x0020 /* logic operations */
|
||||
#define REGUSE_MULT 0x0030 /* multiplier */
|
||||
#define REGUSE_JUMP 0x0040 /* jump to dest */
|
||||
#define REGUSE_JUMPR 0x0050 /* jump to reg */
|
||||
#define REGUSE_BRANCH 0x0060 /* branch */
|
||||
#define REGUSE_MEM_R 0x0070 /* read from memory */
|
||||
#define REGUSE_MEM_W 0x0080 /* write to memory */
|
||||
#define REGUSE_MEM 0x0090 /* read and write to memory */
|
||||
#define REGUSE_SYS 0x00a0 /* syscall */
|
||||
#define REGUSE_GTE 0x00b0 /* gte operation */
|
||||
#define REGUSE_SUB 0x00f0 /* sub usage */
|
||||
#define REGUSE_TYPEM 0x00f0 /* type mask */
|
||||
|
||||
|
||||
#define REGUSE_RS_R 0x0100
|
||||
#define REGUSE_RS_W 0x0200
|
||||
#define REGUSE_RS (REGUSE_RS_R | REGUSE_RS_W)
|
||||
#define REGUSE_RT_R 0x0400
|
||||
#define REGUSE_RT_W 0x0800
|
||||
#define REGUSE_RT (REGUSE_RT_R | REGUSE_RT_W)
|
||||
#define REGUSE_RD_R 0x1000
|
||||
#define REGUSE_RD_W 0x2000
|
||||
#define REGUSE_RD (REGUSE_RD_R | REGUSE_RD_W)
|
||||
|
||||
#define REGUSE_R31_W 0x4000 /* writes to link register (r31) */
|
||||
#define REGUSE_PC 0x8000 /* reads pc */
|
||||
|
||||
#define REGUSE_LO_R 0x10000
|
||||
#define REGUSE_LO_W 0x20000
|
||||
#define REGUSE_LO (REGUSE_LO_R | REGUSE_LO_W)
|
||||
#define REGUSE_HI_R 0x40000
|
||||
#define REGUSE_HI_W 0x80000
|
||||
#define REGUSE_HI (REGUSE_HI_R | REGUSE_HI_W)
|
||||
|
||||
#define REGUSE_COP0_RD_R 0x100000
|
||||
#define REGUSE_COP0_RD_W 0x200000
|
||||
#define REGUSE_COP0_RD (REGUSE_COP0_RD_R | REGUSE_COP0_RD_W)
|
||||
#define REGUSE_COP0_STATUS 0x400000
|
||||
#define REGUSE_EXCEPTION 0x800000
|
||||
|
||||
#define REGUSE_COP2_RT_R 0x1000000
|
||||
#define REGUSE_COP2_RT_W 0x2000000
|
||||
#define REGUSE_COP2_RT (REGUSE_COP2_RT_R | REGUSE_COP2_RT_W)
|
||||
#define REGUSE_COP2_RD_R 0x4000000
|
||||
#define REGUSE_COP2_RD_W 0x8000000
|
||||
#define REGUSE_COP2_RD (REGUSE_COP2_RD_R | REGUSE_COP2_RD_W)
|
||||
|
||||
|
||||
// specific register use
|
||||
#define REGUSE_READ 1
|
||||
#define REGUSE_WRITE 2
|
||||
#define REGUSE_RW 3
|
||||
|
||||
int useOfPsxReg(u32 code, int use, int psxreg) __attribute__ ((__pure__));;
|
||||
int nextPsxRegUse(u32 pc, int psxreg) __attribute__ ((__pure__));;
|
||||
int isPsxRegUsed(u32 pc, int psxreg) __attribute__ ((__pure__));;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in New Issue