From 3c762750a0def0c2591d0deb0ac7ba033aa2d7d3 Mon Sep 17 00:00:00 2001 From: Magn3s1um Date: Fri, 8 Nov 2013 17:17:44 -0800 Subject: [PATCH 1/3] -Added SPR registers -Implemented MTSPR --- rpcs3/Emu/Cell/SPUDisAsm.h | 2 +- rpcs3/Emu/Cell/SPUInterpreter.h | 14 ++++++++++-- rpcs3/Emu/Cell/SPUThread.h | 39 +++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUDisAsm.h b/rpcs3/Emu/Cell/SPUDisAsm.h index ac1008273f..6c4dc82cd9 100644 --- a/rpcs3/Emu/Cell/SPUDisAsm.h +++ b/rpcs3/Emu/Cell/SPUDisAsm.h @@ -94,7 +94,7 @@ private: } void MFSPR(u32 rt, u32 sa) { - DisAsm("mfspr", spu_reg_name[rt], spu_reg_name[sa]); // Are SPR mapped on the GPR or are there 128 additional registers ? + DisAsm("mfspr", spu_reg_name[rt], spu_reg_name[sa]); // Are SPR mapped on the GPR or are there 128 additional registers ? Yes, there are also 128 SPR making 256 registers total } void RDCH(u32 rt, u32 ra) { diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 0926dae80d..88e73ade2d 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -44,7 +44,17 @@ private: } void MFSPR(u32 rt, u32 sa) { - UNIMPLEMENTED(); + //If register is a dummy register (register labeled 0x0) + if(sa == 0) + { + CPU.GPR[rt]._u128.hi = 0x0; + CPU.GPR[rt]._u128.lo = 0x0; + } + else + { + CPU.GPR[rt]._u128.hi = CPU.SPR[sa]._u128.hi; + CPU.GPR[rt]._u128.lo = CPU.SPR[sa]._u128.lo; + } } void RDCH(u32 rt, u32 ra) { @@ -890,7 +900,7 @@ private: void MPYU(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2 + 1] * CPU.GPR[rb]._u16[w*2 + 1]; + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w]; } void CEQB(u32 rt, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 7f9d58c13c..40c14a09f1 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -22,6 +22,25 @@ static const wxString spu_reg_name[128] = "$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119", "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", }; +//SPU reg $0 is a dummy reg, and is used for certain instructions. +static const wxString spu_specialreg_name[129] = { + "$0", "$1", "$2", "$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", + "$32", "$33", "$34", "$35", "$36", "$37", "$38", "$39", + "$40", "$41", "$42", "$43", "$44", "$45", "$46", "$47", + "$48", "$49", "$50", "$51", "$52", "$53", "$54", "$55", + "$56", "$57", "$58", "$59", "$60", "$61", "$62", "$63", + "$64", "$65", "$66", "$67", "$68", "$69", "$70", "$71", + "$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79", + "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", + "$88", "$89", "$90", "$91", "$92", "$93", "$94", "$95", + "$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103", + "$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111", + "$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119", + "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", "$128", +}; static const wxString spu_ch_name[128] = { @@ -126,10 +145,30 @@ union SPU_GPR_hdr } }; +union SPU_SPR_hdr +{ + u128 _u128; + s128 _i128; + + + SPU_SPR_hdr() {} + + wxString ToString() const + { + return wxString::Format("%16%16", _u128.hi, _u128.lo); + } + + void Reset() + { + memset(this, 0, sizeof(*this)); + } +}; + class SPUThread : public PPCThread { public: SPU_GPR_hdr GPR[128]; //General-Purpose Register + SPU_SPR_hdr SPR[128]; //Special-Purpose Registers template class Channel From 1192d20295aa3171252bc99a0516bde90c4b5b1a Mon Sep 17 00:00:00 2001 From: Magn3s1um Date: Sat, 9 Nov 2013 07:41:56 -0800 Subject: [PATCH 2/3] -Partial Implementation of Floating-Point Status and Control Register (FPSCR) --- rpcs3/Emu/Cell/SPUDisAsm.h | 2 +- rpcs3/Emu/Cell/SPUInterpreter.h | 28 ++++++++--- rpcs3/Emu/Cell/SPUOpcodes.h | 2 +- rpcs3/Emu/Cell/SPUThread.h | 84 +++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUDisAsm.h b/rpcs3/Emu/Cell/SPUDisAsm.h index 6c4dc82cd9..c0eee0044a 100644 --- a/rpcs3/Emu/Cell/SPUDisAsm.h +++ b/rpcs3/Emu/Cell/SPUDisAsm.h @@ -428,7 +428,7 @@ private: { DisAsm("sumb", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb]); } - void HGT(u32 rt, u32 ra, u32 rb) + void HGT(u32 rt, s32 ra, s32 rb) { DisAsm("hgt", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb]); } diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 88e73ade2d..e123dfe48c 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -45,7 +45,7 @@ private: void MFSPR(u32 rt, u32 sa) { //If register is a dummy register (register labeled 0x0) - if(sa == 0) + if(sa == 0x0) { CPU.GPR[rt]._u128.hi = 0x0; CPU.GPR[rt]._u128.lo = 0x0; @@ -260,7 +260,11 @@ private: } void MTSPR(u32 rt, u32 sa) { - UNIMPLEMENTED(); + if(sa != 0) + { + CPU.SPR[sa]._u128.hi = CPU.GPR[rt]._u128.hi; + CPU.SPR[sa]._u128.lo = CPU.GPR[rt]._u128.lo; + } } void WRCH(u32 ra, u32 rt) { @@ -307,7 +311,7 @@ private: void IRET(u32 ra) { UNIMPLEMENTED(); - // SetBranch(SRR0); + //SetBranch(SRR0); } void BISLED(u32 rt, u32 ra) { @@ -628,9 +632,13 @@ private: CPU.GPR[rt]._u16[w*2 + 1] = CPU.GPR[rb]._u8[w*4] + CPU.GPR[rb]._u8[w*4 + 1] + CPU.GPR[rb]._u8[w*4 + 2] + CPU.GPR[rb]._u8[w*4 + 3]; } } - void HGT(u32 rt, u32 ra, u32 rb) + //HGT uses signed values. HLGT uses unsigned values + void HGT(u32 rt, s32 ra, s32 rb) { - UNIMPLEMENTED(); + if(CPU.GPR[ra]._i32[0] > CPU.GPR[rb]._i32[0]) + { + CPU.Stop(); + } } void CLZ(u32 rt, u32 ra) { @@ -757,7 +765,10 @@ private: } void HLGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + if(CPU.GPR[ra]._u32[0] > CPU.GPR[rb]._u32[0]) + { + CPU.Stop(); + } } void DFMA(u32 rt, u32 ra, u32 rb) { @@ -824,8 +835,13 @@ private: for (int w = 0; w < 4; w++) CPU.GPR[rt]._u32[w] += CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2]; } + //Forced bits to 0, hence the shift: + void FSCRRD(u32 rt) { + /*CPU.GPR[rt]._u128.lo = + CPU.FPSCR.Exception0 << 20 & + CPU.FPSCR.*/ UNIMPLEMENTED(); } void FESD(u32 rt, u32 ra) diff --git a/rpcs3/Emu/Cell/SPUOpcodes.h b/rpcs3/Emu/Cell/SPUOpcodes.h index 8356f962a5..2b0a48744c 100644 --- a/rpcs3/Emu/Cell/SPUOpcodes.h +++ b/rpcs3/Emu/Cell/SPUOpcodes.h @@ -323,7 +323,7 @@ public: virtual void EQV(u32 rt, u32 ra, u32 rb) = 0; virtual void CGTB(u32 rt, u32 ra, u32 rb) = 0; virtual void SUMB(u32 rt, u32 ra, u32 rb) = 0; - virtual void HGT(u32 rt, u32 ra, u32 rb) = 0; + virtual void HGT(u32 rt, s32 ra, s32 rb) = 0; virtual void CLZ(u32 rt, u32 ra) = 0; virtual void XSWD(u32 rt, u32 ra) = 0; virtual void XSHW(u32 rt, u32 ra) = 0; diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 40c14a09f1..89d1d45c45 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -117,6 +117,89 @@ enum SPU_STATUS_SINGLE_STEP = 0x10, }; +//Floating point status and control register. Unsure if this is one of the GPRs or SPRs +//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused +class FPSCR +{ +public: + u64 low; + u64 hi; + + FPSCR() {} + + wxString ToString() const + { + return "FPSCR writer not yet implemented"; //wxString::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]); + } + + void Reset() + { + memset(this, 0, sizeof(*this)); + } + //slice -> 0 - 1 (4 slices total, only two have rounding) + //0 -> round even + //1 -> round towards zero (truncate) + //2 -> round towards positive inf + //3 -> round towards neg inf + void setSliceRounding(u8 slice, u8 roundTo) + { + u64 mask = roundTo; + switch(slice) + { + case 0: + mask = mask << 20; + break; + case 1: + mask = mask << 22; + break; + } + + //rounding is located in the low end of the FPSCR + this->low = this->low & mask; + } + //Slice 0 or 1 + u8 checkSliceRounding(u8 slice) + { + switch(slice) + { + case 0: + return this->low >> 20 & 0x3; + + case 1: + return this->low >> 22 & 0x3; + } + } + + //Single Precision Exception Flags (all 3 slices) + //slice -> slice number (0-3) + //exception: 1 -> Overflow 2 -> Underflow 4-> Diff (could be IE^3 non compliant) + void setSinglePrecisionExceptionFlags(u8 slice, u8 exception) + { + u64 mask = exception; + switch(slice) + { + case 0: + mask = mask << 29; + this->low = this->low & mask; + break; + case 1: + mask = mask << 61; + this->low = this->low & mask; + break; + case 2: + mask = mask << 29; + this->hi = this->hi & mask; + break; + case 3: + mask = mask << 61; + this->hi = this->hi & mask; + break; + } + + } + +}; + union SPU_GPR_hdr { u128 _u128; @@ -169,6 +252,7 @@ class SPUThread : public PPCThread public: SPU_GPR_hdr GPR[128]; //General-Purpose Register SPU_SPR_hdr SPR[128]; //Special-Purpose Registers + FPSCR FPSCR; template class Channel From 63482dcfdcbd54fdcafe41ce1dd183ad3aeef0d3 Mon Sep 17 00:00:00 2001 From: Magn3s1um Date: Sat, 9 Nov 2013 07:51:26 -0800 Subject: [PATCH 3/3] -Fixed MPYU and special registers based on comments --- rpcs3/Emu/Cell/SPUInterpreter.h | 2 +- rpcs3/Emu/Cell/SPUThread.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index e123dfe48c..69eb99009b 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -916,7 +916,7 @@ private: void MPYU(u32 rt, u32 ra, u32 rb) { for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w]; + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2]; } void CEQB(u32 rt, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 89d1d45c45..2031805718 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -23,7 +23,7 @@ static const wxString spu_reg_name[128] = "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", }; //SPU reg $0 is a dummy reg, and is used for certain instructions. -static const wxString spu_specialreg_name[129] = { +static const wxString spu_specialreg_name[128] = { "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", @@ -39,7 +39,7 @@ static const wxString spu_specialreg_name[129] = { "$96", "$97", "$98", "$99", "$100", "$101", "$102", "$103", "$104", "$105", "$106", "$107", "$108", "$109", "$110", "$111", "$112", "$113", "$114", "$115", "$116", "$117", "$118", "$119", - "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", "$128", + "$120", "$121", "$122", "$123", "$124", "$125", "$126", "$127", }; static const wxString spu_ch_name[128] =