/* sh4 base core most of it is (very) old could use many cleanups, lets hope someone does them */ //All non fpu opcodes :) #include "types.h" #include "dc/pvr/pvr_if.h" #include "sh4_interpreter.h" #include "dc/mem/sh4_mem.h" #include "dc/mem/sh4_internal_reg.h" #include "sh4_registers.h" #include "sh4_interpreter.h" #include "ccn.h" #include "intc.h" #include "tmu.h" #include "dc/gdrom/gdrom_if.h" #include "sh4r_rename.h" #include #define GetN(str) ((str>>8) & 0xf) #define GetM(str) ((str>>4) & 0xf) #define GetImm4(str) ((str>>0) & 0xf) #define GetImm8(str) ((str>>0) & 0xff) #define GetSImm8(str) ((s8)((str>>0) & 0xff)) #define GetImm12(str) ((str>>0) & 0xfff) #define GetSImm12(str) (((s16)((GetImm12(str))<<4))>>3) #define iNimp cpu_iNimp #define iWarn cpu_iWarn //Read Mem macros #define ReadMemU64(to,addr) (u64&)to=ReadMem64(addr) #define ReadMemU32(to,addr) to=ReadMem32(addr) #define ReadMemS32(to,addr) to=(s32)ReadMem32(addr) #define ReadMemS16(to,addr) to=(u32)(s32)(s16)ReadMem16(addr) #define ReadMemS8(to,addr) to=(u32)(s32)(s8)ReadMem8(addr) //Base,offset format #define ReadMemBOU32(to,addr,offset) ReadMemU32(to,addr+offset) #define ReadMemBOS16(to,addr,offset) ReadMemS16(to,addr+offset) #define ReadMemBOS8(to,addr,offset) ReadMemS8(to,addr+offset) //Write Mem Macros #define WriteMemU64(addr,data) WriteMem64(addr,(u64&)data) #define WriteMemU32(addr,data) WriteMem32(addr,(u32)data) #define WriteMemU16(addr,data) WriteMem16(addr,(u16)data) #define WriteMemU8(addr,data) WriteMem8(addr,(u8)data) //Base,offset format #define WriteMemBOU32(addr,offset,data) WriteMemU32(addr+offset,data) #define WriteMemBOU16(addr,offset,data) WriteMemU16(addr+offset,data) #define WriteMemBOU8(addr,offset,data) WriteMemU8(addr+offset,data) #define exept_tet_now {if (sh4_exept_raised) return;} #ifdef NO_MMU #define EXEPT_EXIT() #else #define EXEPT_EXIT() if (sex) return; #endif #define _INTERPRETER_COMPILE_ bool sh4_sleeping; // 0xxx void cpu_iNimp(u32 op, char* info) { dlog("not implemented opcode : %X : ", op); dlog(info); dlog(" @ %X\n", pc); dbgbreak; //sh4_cpu->Stop(); } void cpu_iWarn(u32 op, char* info) { dlog("Check opcode : %X : ", op); dlog(info); dlog(" @ %X\n", pc); } #include "sh4_cpu_movs.h" #include "sh4_cpu_loadstore.h" #include "sh4_cpu_branch.h" #include "sh4_cpu_arith.h" #include "sh4_cpu_logic.h" #include "dc/mem/mmu.h" //************************ TLB/Cache ************************ //ldtlb sh4op(i0000_0000_0011_1000) { //u32 size[4]={1,4,64,1024}; //u32 size_2[4]={1,1,1,1024/64}; //dlog("ldtlb : ASID : %d , VPN : 0x%X ,PPN 0x%X,V %d , SZ : %d kb,PR %d, C %d , D %d , SH %d , WT %d\n" // ,CCN_PTEH.ASID,CCN_PTEH.VPN, // CCN_PTEL.PPN,CCN_PTEL.V,size[CCN_PTEL.SZ1*2 + CCN_PTEL.SZ0],CCN_PTEL.PR, // CCN_PTEL.C,CCN_PTEL.D,CCN_PTEL.SH,CCN_PTEL.WT); //u32 newmap=CCN_PTEH.VPN <<10; //u32 start=CCN_PTEL.PPN<<10; //dlog("Map 0x%X to 0x%X\n",start,newmap); //start >>=16; //newmap >>=16; //for (u32 i=0;i<4;i++) // _vmem_mirror_mapping((i<<29) | (newmap & 0x1FFFFFFF),start,size_2[CCN_PTEL.SZ1*2 + CCN_PTEL.SZ0]); //_vmem_mirror_mapping((3<<30) | (newmap & 0x1FFFFFFF),start,size_2[CCN_PTEL.SZ1*2 + CCN_PTEL.SZ0]); //dlog("ldtlb %d/%d\n",CCN_MMUCR.URC,CCN_MMUCR.URB); UTLB_SyncUnmap(CCN_MMUCR.URC); UTLB[CCN_MMUCR.URC].Data=CCN_PTEL; UTLB[CCN_MMUCR.URC].Address=CCN_PTEH; bool is_sq_remap=UTLB_SyncMap(CCN_MMUCR.URC); #ifdef NO_MMU if (!is_sq_remap) iNimp(op, "ldtlb"); #endif } //ocbi @ sh4op(i0000_nnnn_1001_0011) { //u32 n = GetN(op); //dlog("ocbi @0x%08X \n",r[n]); } //ocbp @ sh4op(i0000_nnnn_1010_0011) { //u32 n = GetN(op); //dlog("ocbp @0x%08X \n",r[n]); } //ocbwb @ sh4op(i0000_nnnn_1011_0011) { //u32 n = GetN(op); //dlog("ocbwb @0x%08X \n",r[n]); } u64 time_pref=0; //pref @ void __fastcall do_pref(u32 addr) { // u64 prt=mftb(); u32 * sq=(u32*)(0x60000000 | ( addr & 0x1FFF0020)); // u32* sq = (u32*)&sq_page[addr& 0x20]; /* int i; bool thr=false; for (i=0;i<64;++i) if (sq_page[64+i]!=0x42) thr=true; if (thr) printf("foirade %p\n",addr); memset(&sq_page[64],0x42,64);*/ if (!mmu_TranslateSQW(addr)) { dlog("Read Exeption From SQ WRITE \n"); return; } if (((addr >> 26) & 0x7) == 4)//Area 4 !11!! { TAWriteSQ(addr,sq); } else { WriteMemBlock_nommu_ptr(addr,sq,8*4); } /* prt=mftb()-prt; time_pref+=prt;*/ } sh4op(i0000_nnnn_1000_0011) { u32 n = GetN(op); u32 Dest = r[n]; if ((Dest & 0xFC000000) == 0xE0000000) //Store Queue { do_pref(Dest); } } //************************ Set/Get T/S ************************ //sets sh4op(i0000_0000_0101_1000) { sr.S = 1; } //clrs sh4op(i0000_0000_0100_1000) { sr.S = 0; } //sett sh4op(i0000_0000_0001_1000) { sr.SetT( 1); } //clrt sh4op(i0000_0000_0000_1000) { sr.SetT( 0); } //movt sh4op(i0000_nnnn_0010_1001) { u32 n = GetN(op); r[n] = sr.GetT(); } //************************ Reg Compares ************************ //cmp/pz sh4op(i0100_nnnn_0001_0001) { u32 n = GetN(op); if (((s32)r[n]) >= 0) sr.SetT( 1); else sr.SetT( 0); } //cmp/pl sh4op(i0100_nnnn_0001_0101) { //iNimp("cmp/pl "); u32 n = GetN(op); if ((s32)r[n] > 0) sr.SetT( 1); else sr.SetT( 0); } //cmp/eq #,R0 sh4op(i1000_1000_iiii_iiii) { u32 imm = (u32)(s32)(GetSImm8(op)); if (r[0] == imm) sr.SetT(1); else sr.SetT(0); } //cmp/eq , sh4op(i0011_nnnn_mmmm_0000) { //iNimp("cmp/eq ,"); u32 n = GetN(op); u32 m = GetM(op); if (r[m] == r[n]) sr.SetT( 1); else sr.SetT( 0); } //cmp/hs , sh4op(i0011_nnnn_mmmm_0010) {//ToDo : Check Me [26/4/05] u32 n = GetN(op); u32 m = GetM(op); if (r[n] >= r[m]) sr.SetT(1); else sr.SetT(0); } //cmp/ge , sh4op(i0011_nnnn_mmmm_0011) { //iNimp("cmp/ge ,"); u32 n = GetN(op); u32 m = GetM(op); if ((s32)r[n] >= (s32)r[m]) sr.SetT( 1); else sr.SetT( 0); } //cmp/hi , sh4op(i0011_nnnn_mmmm_0110) { u32 n = GetN(op); u32 m = GetM(op); if (r[n] > r[m]) sr.SetT(1); else sr.SetT(0); } //cmp/gt , sh4op(i0011_nnnn_mmmm_0111) { //iNimp("cmp/gt ,"); u32 n = GetN(op); u32 m = GetM(op); if (((s32)r[n]) > ((s32)r[m])) sr.SetT( 1); else sr.SetT( 0); } //cmp/str , sh4op(i0010_nnnn_mmmm_1100) { //iNimp("cmp/str ,"); u32 n = GetN(op); u32 m = GetM(op); u32 temp; u32 HH, HL, LH, LL; temp = r[n] ^ r[m]; HH=(temp&0xFF000000)>>24; HL=(temp&0x00FF0000)>>16; LH=(temp&0x0000FF00)>>8; LL=temp&0x000000FF; HH=HH&&HL&&LH&&LL; if (HH==0) sr.SetT(1); else sr.SetT(0); } //tst #,R0 sh4op(i1100_1000_iiii_iiii) { //iNimp("tst #,R0"); u32 utmp1 = r[0] & GetImm8(op); if (utmp1 == 0) sr.SetT( 1); else sr.SetT( 0); } //tst , sh4op(i0010_nnnn_mmmm_1000) {//ToDo : Check This [26/4/05] u32 n = GetN(op); u32 m = GetM(op); if ((r[n] & r[m])!=0) sr.SetT(0); else sr.SetT(1); } //************************ mulls! ************************ //mulu.w , sh4op(i0010_nnnn_mmmm_1110) { //iNimp("mulu.w ,");//check ++ u32 n = GetN(op); u32 m = GetM(op); mac.l=((u16)r[n])* ((u16)r[m]); } //muls.w , sh4op(i0010_nnnn_mmmm_1111) { //iNimp("muls ,"); u32 n = GetN(op); u32 m = GetM(op); mac.l = (u32)(((s16)(u16)r[n]) * ((s16)(u16)r[m])); } //dmulu.l , sh4op(i0011_nnnn_mmmm_0101) { //iNimp("dmulu.l ,"); u32 n = GetN(op); u32 m = GetM(op); mac.full = (u64)r[n] * (u64)r[m]; } //dmuls.l , sh4op(i0011_nnnn_mmmm_1101) { //iNimp("dmuls.l ,");//check ++ u32 n = GetN(op); u32 m = GetM(op); mac.full = (s64)(s32)r[n] * (s64)(s32)r[m]; } //mac.w @+,@+ sh4op(i0100_nnnn_mmmm_1111) { u32 n = GetN(op); u32 m = GetM(op); if (sr.S==1) { dlog("mac.w @+,@+ : s=%d\n",sr.S); } else { s32 rm,rn; rn = (s32)(s16)ReadMem16(r[n]); r[n]+=2; //if (n==m) //{ // r[n]+=2; // r[m]+=2; //} rm = (s32)(s16)ReadMem16(r[m]); verify(sh4_exept_raised==false); r[m]+=2; s32 mul=rm * rn; mac.full+=(s64)mul; } } //mac.l @+,@+ sh4op(i0000_nnnn_mmmm_1111) { //iNimp("mac.l @+,@+"); u32 n = GetN(op); u32 m = GetM(op); s32 rm, rn; verify(sr.S==0); ReadMemS32(rm,r[m]); r[m] += 4; ReadMemS32(rn,r[n]); r[n] += 4; verify(sh4_exept_raised==false); mac.full += (s64)rm * (s64)rn; //dlog("%I64u %I64u | %d %d | %d %d\n",mac,mul,macl,mach,rm,rn); } //mul.l , sh4op(i0000_nnnn_mmmm_0111) { u32 n = GetN(op); u32 m = GetM(op); mac.l = (u32)((((s32)r[n]) * ((s32)r[m]))); } //************************ Div ! ************************ void FASTCALL sh4_div0u() { sr.Q = 0; sr.M = 0; sr.SetT( 0); } //div0u sh4op(i0000_0000_0001_1001) { sh4_div0u(); } void FASTCALL sh4_div0s(u32 rn,u32 rm) { sr.Q=rn>>31; sr.M=rm>>31; sr.SetT(sr.M^sr.Q); } //div0s , sh4op(i0010_nnnn_mmmm_0111) { u32 n = GetN(op); u32 m = GetM(op); sh4_div0s(r[n],r[m]); } u32 FASTCALL sh4_div1(u32 rn,u32 rm) { unsigned long tmp0, tmp2; unsigned char old_q, tmp1; old_q = sr.Q; sr.Q = (u8)((0x80000000 & rn) !=0); rn <<= 1; rn |= sr.GetT(); tmp0 = rn; // this need only be done once here .. tmp2 = rm; if( 0 == old_q ) { if( 0 == sr.M ) { rn -= tmp2; tmp1 = (rn>tmp0); sr.Q = (sr.Q==0) ? tmp1 : (u8)(tmp1==0) ; } else { rn += tmp2; tmp1 =(rntmp0); sr.Q = (sr.Q==0) ? (u8)(tmp1==0) : tmp1 ; } } sr.SetT( (sr.Q==sr.M)); return rn; /* u32 op1=r[m]; u32 op2=(u32)(s32)r[n]; u32 oldq=sr.Q; sr.Q=(r[n]>>31)&1; op2=(op2<<1)| (sr.GetT()); u32 of=0; if (oldq==sr.M) { op2=op2-op1; if (underflow) of=1; } else { op2=op2+op1; if (overflow) of=1; } sr.Q=(sr.Q^sr.M)^of; sr.SetT(1^(sr.Q ^ sr.M); r[n]=(u32)op2;*/ //dlog("Q %d , S %d , T %d , r[n] %d, r[m] %d\n",sr.Q,sr.S,sr.GetT(),r[n],r[m]); } //div1 , sh4op(i0011_nnnn_mmmm_0100) {//ToDo : Check This [26/4/05] u32 n=GetN(op); //dividend 'sign' u32 m=GetM(op); //divisor r[n]=sh4_div1(r[n],r[m]); } //************************ Simple maths ************************ //addc , sh4op(i0011_nnnn_mmmm_1110) {//ToDo : Check This [26/4/05] //iNimp(op,"addc ,"); u32 n = GetN(op); u32 m = GetM(op); u32 tmp1 = r[n] + r[m]; u32 tmp0 = r[n]; r[n] = tmp1 + sr.GetT(); if (tmp0 > tmp1) sr.SetT( 1); else sr.SetT( 0); if (tmp1 > r[n]) sr.SetT( 1); } // addv , sh4op(i0011_nnnn_mmmm_1111) { //iNimp(op, "addv ,"); u32 n = GetN(op); u32 m = GetM(op); s64 br=(s64)(s32)r[n]+(s64)(s32)r[m]; // u32 rm=r[m]; u32 rn=r[n]; // u8 tmp; TR/*gli __asm { mov eax,rm; mov ecx,rn; add eax,ecx; seto tmp;//cond = (@cf ==> flip(F(o)[msb])) movzx ebx,tmp; mov [sr.GetT()],ebx; };*/ r[n]=rn; if (br >=0x80000000) sr.SetT(1); else if (br < (s64) (0xFFFFFFFF80000000u)) sr.SetT(1); else sr.SetT(0); if (br>>32) sr.SetT(1); else sr.SetT(0); r[n]+=r[m]; } //subc , sh4op(i0011_nnnn_mmmm_1010) {//ToDo : Check This [26/4/05] //iNimp(op,"subc ,"); u32 n = GetN(op); u32 m = GetM(op); u32 tmp1 = (u32)(((s32)r[n]) - ((s32)r[m])); u32 tmp0 = r[n]; r[n] = tmp1 - sr.GetT(); if (tmp0 < tmp1) sr.SetT(1); else sr.SetT(0); if (tmp1 < r[n]) sr.SetT(1); } //subv , sh4op(i0011_nnnn_mmmm_1011) { //iNimp(op, "subv ,"); u32 n = GetN(op); u32 m = GetM(op); s64 br=(s64)(s32)r[n]-(s64)(s32)r[m]; if (br >=0x80000000) sr.SetT(1); else if (br < (s64) (0xFFFFFFFF80000000u)) sr.SetT(1); else sr.SetT(0); if (br>>32) sr.SetT(1); else sr.SetT(0); r[n]-=r[m]; // u32 rm=r[m]; u32 rn=r[n]; // u8 tmp; TR/*gli __asm { mov eax,rm; mov ecx,rn; sub eax,ecx; seto tmp;//cond = (@cf ==> flip(F(o)[msb])) movzx ebx,tmp; mov [sr.GetT()],ebx; };*/ r[n]=rn; } //dt sh4op(i0100_nnnn_0001_0000) { u32 n = GetN(op); r[n]-=1; if (r[n] == 0) sr.SetT(1); else sr.SetT(0); } //negc , sh4op(i0110_nnnn_mmmm_1010) { //iNimp("negc ,"); u32 n = GetN(op); u32 m = GetM(op); //r[n]=-r[m]-sr.GetT(); u32 tmp=0-r[m]; r[n]=tmp-sr.GetT(); if (0>31; } //neg , sh4op(i0110_nnnn_mmmm_1011) {//ToDo : Check This [26/4/05] u32 n = GetN(op); u32 m = GetM(op); r[n] = -(s32)r[m]; } //not , sh4op(i0110_nnnn_mmmm_0111) { //iNimp("not ,"); u32 n = GetN(op); u32 m = GetM(op); r[n] = ~r[m]; } //************************ shifts/rotates ************************ //shll sh4op(i0100_nnnn_0000_0000) {//ToDo : Check This [26/4/05] u32 n = GetN(op); sr.SetT( r[n] >> 31); r[n] <<= 1; } //shal sh4op(i0100_nnnn_0010_0000) { u32 n=GetN(op); sr.SetT(r[n]>>31); r[n]=((s32)r[n])<<1; } //shlr sh4op(i0100_nnnn_0000_0001) {//ToDo : Check This [26/4/05] u32 n = GetN(op); sr.SetT( r[n] & 0x1); r[n] >>= 1; } //shar sh4op(i0100_nnnn_0010_0001) {//ToDo : Check This [26/4/05] x2 //iNimp("shar "); u32 n = GetN(op); sr.SetT(r[n] & 1); r[n]=((s32)r[n])>>1; } //shad , sh4op(i0100_nnnn_mmmm_1100) { //iNimp(op,"shad ,"); u32 n = GetN(op); u32 m = GetM(op); u32 sgn = r[m] & 0x80000000; if (sgn == 0) r[n] <<= (r[m] & 0x1F); else if ((r[m] & 0x1F) == 0) { if ((r[n] & 0x80000000) == 0) r[n] = 0; else r[n] = 0xFFFFFFFF; } else r[n] = ((s32)r[n]) >> ((~r[m] & 0x1F) + 1); } //shld , sh4op(i0100_nnnn_mmmm_1101) {//ToDo : Check This [26/4/05] x2 //iNimp("shld ,"); //HACK : CHECKME /*u32 n = GetN(op); u32 m = GetM(op); s32 s; s = (s32)(r[m] & 0x80000000); if (s == 0) r[n] <<= (r[m]); else if ((r[m] & 0x1f) == 0) r[n] = 0; else r[n] = (u32)r[n] >> (32-r[m]);*/ // -> bug ! 32-r[m] -> -(r[m]&0x1F) u32 n = GetN(op); u32 m = GetM(op); u32 sgn = r[m] & 0x80000000; if (sgn == 0) r[n] <<= (r[m] & 0x1F); else if ((r[m] & 0x1F) == 0) { r[n] = 0; } else r[n] = ((u32)r[n]) >> ((~r[m] & 0x1F) + 1); } u32 FASTCALL sh4_rotcl(u32 rn) { u32 t = sr.GetT(); sr.SetT( rn >> 31); rn <<= 1; rn|=t; return rn; } //rotcl sh4op(i0100_nnnn_0010_0100) {//ToDo : Check This [26/4/05] //iNimp("rotcl "); u32 n = GetN(op); r[n]=sh4_rotcl(r[n]); } //rotl sh4op(i0100_nnnn_0000_0100) { //iNimp("rotl "); u32 n = GetN(op); //return; /* if ((r[n] & 0x80000000)!=0) sr.SetT(1; else sr.SetT( 0;*/ sr.SetT(r[n]>>31); r[n] <<= 1; /*if (sr.GetT()!=0) r[n] |= 0x00000001; else r[n] &= 0xFFFFFFFE;*/ r[n]|=sr.GetT(); } //rotcr sh4op(i0100_nnnn_0010_0101) { //iNimp("rotcr "); u32 n = GetN(op); u32 temp; /*if ((R[n] & 0x00000001) == 0) temp = 0; else temp = 1;*/ temp = r[n] & 0x1; r[n] >>= 1; /* if (sr.SetT(= 1) r[n] |= 0x80000000; else r[n] &= 0x7FFFFFFF;*/ r[n] |=sr.GetT()<<31; sr.SetT( temp); /*if (temp == 1) T = 1; else T = 0;*/ } //rotr sh4op(i0100_nnnn_0000_0101) { //iNimp("rotr ");//check ++ u32 n = GetN(op); sr.SetT( r[n] & 0x1); r[n] >>= 1; r[n] |= (sr.GetT() << 31); } //************************ byte reorder/sign ************************ //swap.b , sh4op(i0110_nnnn_mmmm_1000) { //iNimp("swap.b ,"); u32 m = GetM(op); u32 n = GetN(op); r[n] = (r[m] & 0xFFFF0000) | ((r[m]&0xFF)<<8) | ((r[m]>>8)&0xFF); } //swap.w , sh4op(i0110_nnnn_mmmm_1001) { u32 n = GetN(op); u32 m = GetM(op); u16 t = (u16)(r[m]>>16); r[n] = (r[m] << 16) | t; } //extu.b , sh4op(i0110_nnnn_mmmm_1100) { u32 n = GetN(op); u32 m = GetM(op); r[n] = (u32)(u8)r[m]; } //extu.w , sh4op(i0110_nnnn_mmmm_1101) { u32 n = GetN(op); u32 m = GetM(op); r[n] =(u32)(u16) r[m] & 0x0000FFFF; } //exts.b , sh4op(i0110_nnnn_mmmm_1110) { u32 n = GetN(op); u32 m = GetM(op); r[n] = (u32)(s32)(s8)(u8)(r[m]); } //exts.w , sh4op(i0110_nnnn_mmmm_1111) { u32 n = GetN(op); u32 m = GetM(op); r[n] = (u32)(s32)(s16)(u16)(r[m]); } //xtrct , sh4op(i0010_nnnn_mmmm_1101) { u32 n = GetN(op); u32 m = GetM(op); r[n] = ((r[n] >> 16) & 0xFFFF) | ((r[m] << 16) & 0xFFFF0000); } //************************ xxx.b #,@(R0,GBR) ************************ //tst.b #,@(R0,GBR) sh4op(i1100_1100_iiii_iiii) { u32 imm=GetImm8(op); u32 temp = (u8)ReadMem8(gbr+r[0]); temp &= imm; if (temp==0) sr.SetT(1); else sr.SetT(0); } //and.b #,@(R0,GBR) sh4op(i1100_1101_iiii_iiii) { u8 temp = (u8)ReadMem8(gbr+r[0]); temp &= GetImm8(op); WriteMem8(gbr +r[0], temp); } //xor.b #,@(R0,GBR) sh4op(i1100_1110_iiii_iiii) { u8 temp = (u8)ReadMem8(gbr+r[0]); temp ^= GetImm8(op); WriteMem8(gbr +r[0], temp); } //or.b #,@(R0,GBR) sh4op(i1100_1111_iiii_iiii) { u8 temp = (u8)ReadMem8(gbr+r[0]); temp |= GetImm8(op); WriteMem8(gbr+r[0], temp); } //tas.b @ sh4op(i0100_nnnn_0001_1011) { u32 n = GetN(op); u8 val; val=(u8)ReadMem8(r[n]); u32 srT; if (val == 0) srT = 1; else srT = 0; val |= 0x80; WriteMem8(r[n], val); sr.SetT(srT); } //************************ Opcodes that read/write the status registers ************************ //stc SR, sh4op(i0000_nnnn_0000_0010)//0002 { u32 n = GetN(op); r[n] = sr.GetFull(true); } //sts FPSCR, sh4op(i0000_nnnn_0110_1010) { u32 n = GetN(op); r[n] = fpscr.full; UpdateFPSCR(); } //sts.l FPSCR,@- sh4op(i0100_nnnn_0110_0010) { u32 n = GetN(op); WriteMemBOU32(r[n],(u32)-4,fpscr.full); r[n] -= 4; } //stc.l SR,@- sh4op(i0100_nnnn_0000_0011) { u32 n = GetN(op); WriteMemBOU32(r[n],(u32)-4, sr.GetFull(true)); r[n] -= 4; } //lds.l @+,FPSCR sh4op(i0100_nnnn_0110_0110) { u32 n = GetN(op); ReadMemU32(fpscr.full,r[n]); UpdateFPSCR(); r[n] += 4; } //ldc.l @+,SR sh4op(i0100_nnnn_0000_0111) { u32 n = GetN(op); u32 sr_t; ReadMemU32(sr_t,r[n]); sr.SetFull(sr_t,true); r[n] += 4; if (UpdateSR()) { //FIXME olny if interrupts got on .. :P pc+=2; UpdateINTC(); pc-=2; } } //lds ,FPSCR sh4op(i0100_nnnn_0110_1010) { u32 n = GetN(op); fpscr.full = r[n]; UpdateFPSCR(); } //ldc ,SR sh4op(i0100_nnnn_0000_1110) { u32 n = GetN(op); sr.SetFull(r[n],true); if (UpdateSR()) { //FIXME olny if interrupts got on .. :P pc+=2; UpdateINTC(); pc-=2; } } //bah //Not implt sh4op(iNotImplemented) { cpu_iNimp(op,"unknown opcode"); #ifndef NO_MMU if (sh4_exept_raised==false) { sh4_cpu->RaiseExeption(0x180,0x100); } #endif } sh4op(gdrom_hle_op) { EMUERROR("GDROM HLE NOT SUPPORTED"); }