📄 arm9es-opcodes.cpp
字号:
/*************************************************************************** DSemu - The Next Generation ** Portable ARM9ES core: ARM9-specific opcodes [arm9es-opcodes.cpp] ** Copyright Imran Nazar, 2005; released under the BSD public licence. ***************************************************************************/#include "arm9es.h"#include "plgmmu32.h"#include "armmasks.h"#include "armhelp.h"#include "datadefs.h"#include "log.h"#include "err.h"//---Conditional execution-------------------------------------------------// Each of these functions returns 1 or 0, dependent on flag state.// Called by the dispatcher, by lookup in the condition LUT.int ARM9ES::condEQ(){return reg.flags[FLAG_Z];}int ARM9ES::condNE(){return !reg.flags[FLAG_Z];}int ARM9ES::condCS(){return reg.flags[FLAG_C];}int ARM9ES::condCC(){return !reg.flags[FLAG_C];}int ARM9ES::condMI(){return reg.flags[FLAG_N];}int ARM9ES::condPL(){return !reg.flags[FLAG_N];}int ARM9ES::condVS(){return reg.flags[FLAG_V];}int ARM9ES::condVC(){return !reg.flags[FLAG_V];}int ARM9ES::condHI(){return (!reg.flags[FLAG_Z])®.flags[FLAG_C];}int ARM9ES::condLS(){return reg.flags[FLAG_Z]|(!reg.flags[FLAG_C]);}int ARM9ES::condGE(){return !(reg.flags[FLAG_N]^reg.flags[FLAG_V]);}int ARM9ES::condLT(){return (reg.flags[FLAG_N]^reg.flags[FLAG_V]);}int ARM9ES::condGT(){return (!reg.flags[FLAG_Z])&(!(reg.flags[FLAG_N]^reg.flags[FLAG_V]));}int ARM9ES::condLE(){return reg.flags[FLAG_Z]|(reg.flags[FLAG_N]^reg.flags[FLAG_V]);}int ARM9ES::condAL(){return 1;}int ARM9ES::condNV(){return 0;}//---Branching-------------------------------------------------------------OPC opB(){ s32 i = (reg.curop & 0x00FFFFFF) << 2; // Extract address i = (i & 0x02000000)?(0xFC000000 | i):i; // Sign extend reg.r[15] += i+4; // And branch return 3;}OPC opBL(){ reg.r[14] = reg.r[15]; // Save link addr s32 i = (reg.curop & 0x00FFFFFF) << 2; // Extract address i = (i & 0x02000000)?(0xFC000000 | i):i; // Sign extend reg.r[15] += i+4; // And branch return 3;}OPC opBX(){/* if((_RM&3)==2) opUNP();*/ reg.r[15]=(_RM&~1)+Rm15hack; reg.flags[FLAG_T]=_RM&1; return 1;}OPC opBLXr(){/* if((_RM&3)==2) opUNP();*//* if(_OP_RM==15) opUNP();*/ reg.r[14] = reg.r[15]; reg.r[15]=(_RM&~1)+Rm15hack; reg.flags[FLAG_T]=_RM&1; return 1;}// TODO: BLXimm is pending a method to call unconditional opcodesOPC opBLX(){ return 1;}//---Coprocessor execution-------------------------------------------------OPC opMCR(){/* if(_OP_RD==15) opUNP();*/ copro[_OP_RS]->set((reg.curop&MSK_OPLO)>>21, (reg.curop&MSK_FUNC)>>5, _OP_RN, _OP_RM, _RD); return 1;}OPC opMRC(){ reg.tmp1 = copro[_OP_RS]->get((reg.curop&MSK_OPLO)>>21, (reg.curop&MSK_FUNC)>>5, _OP_RN, _OP_RM); if(_OP_RD==15) { reg.flags[FLAG_N]=(reg.tmp1&0x80000000)?1:0; reg.flags[FLAG_Z]=(reg.tmp1&0x40000000)?1:0; reg.flags[FLAG_C]=(reg.tmp1&0x20000000)?1:0; reg.flags[FLAG_V]=(reg.tmp1&0x10000000)?1:0; } else _RD=reg.tmp1; return 1;}OPC opCDP(){ copro[_OP_RS]->op((reg.curop&MSK_OPLO)>>21, (reg.curop&MSK_FUNC)>>5, _OP_RN, _OP_RM, _OP_RD); return 1;}#define LCi ((reg.curop&MSK_IMM8)<<2)#define LCofm reg.tmp1 = _RN + Rn15hack - LCi#define LCofp reg.tmp1 = _RN + Rn15hack + LCi#define LCwb _RN = reg.tmp1#define LCun reg.tmp1 = _RN + Rn15hack#define LCptm _RN -= LCi#define LCptp _RN += LCiOPC opLDCofm() { LCofm; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opLDCofp() { LCofp; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opLDCprm() { LCofm; LCwb; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opLDCprp() { LCofp; LCwb; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opLDCunm() { LCun; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, reg.curop&255); return 1; }OPC opLDCunp() { LCun; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, reg.curop&255); return 1; }OPC opLDCptm() { LCun; LCptm; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opLDCptp() { LCun; LCptp; copro[_OP_RS]->read(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opSTCofm() { LCofm; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opSTCofp() { LCofp; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opSTCprm() { LCofm; LCwb; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opSTCprp() { LCofp; LCwb; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opSTCunm() { LCun; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, reg.curop&255); return 1; }OPC opSTCunp() { LCun; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, reg.curop&255); return 1; }OPC opSTCptm() { LCun; LCptm; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }OPC opSTCptp() { LCun; LCptp; copro[_OP_RS]->write(_OP_RD, reg.tmp1, (reg.curop&0x00400000)?1:0, 0); return 1; }//---Enhanced DSP extension------------------------------------------------// LDRD/STRD are very similar to the standard halfword-style load/stores,// hence the defines from there are duplicated here.#define Rn15hack ((_OP_RN==15)?4:0)#define Rm15hack ((_OP_RM==15)?4:0)#define LSofm /*if(_OP_RM==15) opUNP();*/ reg.tmp1 = _RN + Rn15hack -#define LSofp /*if(_OP_RM==15) opUNP();*/ reg.tmp1 = _RN + Rn15hack +#define LSwb _RN = reg.tmp1#define LSptm /*if(_OP_RM==15 || _OP_RN==15) opUNP();*/ reg.tmp1 = _RN; _RN -=#define LSptp /*if(_OP_RM==15 || _OP_RN==15) opUNP();*/ reg.tmp1 = _RN; _RN +=#define LHi ((reg.curop&MSK_RM)|((reg.curop&MSK_RS)>>4))#define LHr _RM + Rm15hack#define LDRD { reg.r[_OP_RD]=MMU->rdW(reg.tmp1); reg.r[_OP_RD+1]=MMU->rdW(reg.tmp1+4); }#define STRD { MMU->wrW(reg.tmp1,reg.r[_OP_RD]); MMU->wrW(reg.tmp1+4,reg.r[_OP_RD+1]); } OPC opLDRDptim(){ LSptm(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDptip(){ LSptp(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDptrm(){ LSptm(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDptrp(){ LSptp(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDofim(){ LSofm(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDofip(){ LSofp(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDofrm(){ LSofm(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDofrp(){ LSofp(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDprim(){ LSofm(LHi); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDprip(){ LSofp(LHi); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDprrm(){ LSofm(LHr); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opLDRDprrp(){ LSofp(LHr); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) LDRD; return 3; }OPC opSTRDptim(){ LSptm(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDptip(){ LSptp(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDptrm(){ LSptm(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDptrp(){ LSptp(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDofim(){ LSofm(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDofip(){ LSofp(LHi); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDofrm(){ LSofm(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDofrp(){ LSofp(LHr); if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDprim(){ LSofm(LHi); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDprip(){ LSofp(LHi); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDprrm(){ LSofm(LHr); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }OPC opSTRDprrp(){ LSofp(LHr); LSwb; if(_OP_RD&1) return opUND(); reg.tmp1&=~3; if(_OP_RD<14) STRD; return 3; }#define flagDPqADD sat=( (reg.tmp2^_RD) & (~(reg.tmp1^reg.tmp2)) & 0x80000000); if(sat) reg.flags[FLAG_Q]=1#define flagDPqSUB sat=( (~(reg.tmp1^_RD)) & (reg.tmp1^reg.tmp2) & 0x80000000); if(sat) reg.flags[FLAG_Q]=1#define flagDPqSMLA sat=( (reg.tmp2^_RN) & (~(reg.tmp1^reg.tmp2)) & 0x80000000); if(sat) reg.flags[FLAG_Q]=1#define flagDPcSMLAL carry=(((_RD<reg.tmp2)||(_RD<reg.tmp1))?1:0)OPC opQADD(){ int sat; reg.tmp1=_RM; reg.tmp2=_RN; _RD=_RM+_RN; flagDPqADD; if(sat) _RD=(_RD&0x80000000)?0x7FFFFFFF:0x80000000; return 1;}OPC opQSUB(){ int sat; reg.tmp1=_RM; reg.tmp2=_RN; _RD=_RM-_RN; flagDPqSUB; if(sat) _RD=(_RD&0x80000000)?0x7FFFFFFF:0x80000000; return 1;}OPC opQDADD(){ int sat; reg.tmp1=_RN; reg.tmp2=_RN; _RD=reg.tmp1+reg.tmp2; flagDPqADD; if(sat) _RD=(_RD&0x80000000)?0x7FFFFFFF:0x80000000; reg.tmp1=_RM; reg.tmp2=_RD; _RD=reg.tmp1+reg.tmp2; flagDPqADD; if(sat) _RD=(_RD&0x80000000)?0x7FFFFFFF:0x80000000; return 1;}OPC opQDSUB(){ int sat; reg.tmp1=_RN; reg.tmp2=_RN; _RD=reg.tmp1+reg.tmp2; flagDPqADD; if(sat) _RD=(_RD&0x80000000)?0x7FFFFFFF:0x80000000; reg.tmp1=_RM; reg.tmp2=_RD; _RD=reg.tmp1-reg.tmp2; flagDPqSUB; if(sat) _RD=(_RD&0x80000000)?0x7FFFFFFF:0x80000000; return 1;}OPC opSMULBB(){/* if((_OP_RM==15)| (_OP_RS==15)| (_OP_RD==15)| (_OP_RN==15)) opUNP();*/ u32 r=(_RM&65535), d=(_RS&65535); r=(r&0x8000)?(0xFFFF0000|r):r; d=(d&0x8000)?(0xFFFF0000|d):d; _RN = r*d; return 1; }OPC opSMULBT(){/* if((_OP_RM==15)| (_OP_RS==15)| (_OP_RD==15)| (_OP_RN==15)) opUNP();*/ u32 r=(_RM&65535), d=(_RS>>16); r=(r&0x8000)?(0xFFFF0000|r):r; d=(d&0x8000)?(0xFFFF0000|d):d; _RN = r*d; return 1;}OPC opSMULTB(){/* if((_OP_RM==15)| (_OP_RS==15)| (_OP_RD==15)| (_OP_RN==15)) opUNP();*/ u32 r=(_RM>>16), d=(_RS&65535); r=(r&0x8000)?(0xFFFF0000|r):r; d=(d&0x8000)?(0xFFFF0000|d):d; _RN = r*d; return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -