diff --git a/Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj b/Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj new file mode 100644 index 000000000..78e620912 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj @@ -0,0 +1,621 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 83C8B6AB18AF58080071B040 /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B65918AF58080071B040 /* audio.c */; }; + 83C8B6AC18AF58080071B040 /* audio.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B65A18AF58080071B040 /* audio.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6AD18AF58080071B040 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B65B18AF58080071B040 /* config.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6AE18AF58080071B040 /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B65C18AF58080071B040 /* cpu.c */; }; + 83C8B6AF18AF58080071B040 /* cpu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B65D18AF58080071B040 /* cpu.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6B018AF58080071B040 /* dma.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B65E18AF58080071B040 /* dma.c */; }; + 83C8B6B118AF58080071B040 /* dma.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B65F18AF58080071B040 /* dma.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6B218AF58080071B040 /* exception.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B66018AF58080071B040 /* exception.c */; }; + 83C8B6B318AF58080071B040 /* exception.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66118AF58080071B040 /* exception.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6B418AF58080071B040 /* interpreter_cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B66218AF58080071B040 /* interpreter_cpu.c */; }; + 83C8B6B518AF58080071B040 /* interpreter_cpu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66318AF58080071B040 /* interpreter_cpu.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6B618AF58080071B040 /* interpreter_ops.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B66418AF58080071B040 /* interpreter_ops.c */; }; + 83C8B6B718AF58080071B040 /* interpreter_ops.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66518AF58080071B040 /* interpreter_ops.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6B818AF58080071B040 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B66618AF58080071B040 /* main.c */; }; + 83C8B6B918AF58080071B040 /* main.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66718AF58080071B040 /* main.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6BA18AF58080071B040 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B66818AF58080071B040 /* memory.c */; }; + 83C8B6BB18AF58080071B040 /* memory.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66918AF58080071B040 /* memory.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6BC18AF58080071B040 /* opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66A18AF58080071B040 /* opcode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6BD18AF58080071B040 /* pif.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B66B18AF58080071B040 /* pif.c */; }; + 83C8B6BE18AF58080071B040 /* pif.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66C18AF58080071B040 /* pif.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6BF18AF58080071B040 /* registers.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B66D18AF58080071B040 /* registers.c */; }; + 83C8B6C018AF58080071B040 /* registers.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B66E18AF58080071B040 /* registers.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6C118AF58080071B040 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67018AF58080071B040 /* config.h */; }; + 83C8B6C218AF58080071B040 /* execute.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67118AF58080071B040 /* execute.h */; }; + 83C8B6C318AF58080071B040 /* rsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B67218AF58080071B040 /* rsp.c */; }; + 83C8B6C418AF58080071B040 /* rsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67318AF58080071B040 /* rsp.h */; }; + 83C8B6C518AF58080071B040 /* su.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67418AF58080071B040 /* su.h */; }; + 83C8B6C618AF58080071B040 /* cf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67618AF58080071B040 /* cf.h */; }; + 83C8B6C718AF58080071B040 /* clamp.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67718AF58080071B040 /* clamp.h */; }; + 83C8B6C818AF58080071B040 /* divrom.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67818AF58080071B040 /* divrom.h */; }; + 83C8B6C918AF58080071B040 /* shuffle.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67918AF58080071B040 /* shuffle.h */; }; + 83C8B6CA18AF58080071B040 /* vabs.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67A18AF58080071B040 /* vabs.h */; }; + 83C8B6CB18AF58080071B040 /* vadd.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67B18AF58080071B040 /* vadd.h */; }; + 83C8B6CC18AF58080071B040 /* vaddc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67C18AF58080071B040 /* vaddc.h */; }; + 83C8B6CD18AF58080071B040 /* vand.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67D18AF58080071B040 /* vand.h */; }; + 83C8B6CE18AF58080071B040 /* vch.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67E18AF58080071B040 /* vch.h */; }; + 83C8B6CF18AF58080071B040 /* vcl.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B67F18AF58080071B040 /* vcl.h */; }; + 83C8B6D018AF58080071B040 /* vcr.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68018AF58080071B040 /* vcr.h */; }; + 83C8B6D118AF58080071B040 /* veq.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68118AF58080071B040 /* veq.h */; }; + 83C8B6D218AF58080071B040 /* vge.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68218AF58080071B040 /* vge.h */; }; + 83C8B6D318AF58080071B040 /* vlt.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68318AF58080071B040 /* vlt.h */; }; + 83C8B6D418AF58080071B040 /* vmacf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68418AF58080071B040 /* vmacf.h */; }; + 83C8B6D518AF58080071B040 /* vmacq.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68518AF58080071B040 /* vmacq.h */; }; + 83C8B6D618AF58080071B040 /* vmacu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68618AF58080071B040 /* vmacu.h */; }; + 83C8B6D718AF58080071B040 /* vmadh.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68718AF58080071B040 /* vmadh.h */; }; + 83C8B6D818AF58080071B040 /* vmadl.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68818AF58080071B040 /* vmadl.h */; }; + 83C8B6D918AF58080071B040 /* vmadm.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68918AF58080071B040 /* vmadm.h */; }; + 83C8B6DA18AF58080071B040 /* vmadn.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68A18AF58080071B040 /* vmadn.h */; }; + 83C8B6DB18AF58080071B040 /* vmov.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68B18AF58080071B040 /* vmov.h */; }; + 83C8B6DC18AF58080071B040 /* vmrg.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68C18AF58080071B040 /* vmrg.h */; }; + 83C8B6DD18AF58080071B040 /* vmudh.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68D18AF58080071B040 /* vmudh.h */; }; + 83C8B6DE18AF58080071B040 /* vmudl.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68E18AF58080071B040 /* vmudl.h */; }; + 83C8B6DF18AF58080071B040 /* vmudm.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B68F18AF58080071B040 /* vmudm.h */; }; + 83C8B6E018AF58080071B040 /* vmudn.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69018AF58080071B040 /* vmudn.h */; }; + 83C8B6E118AF58080071B040 /* vmulf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69118AF58080071B040 /* vmulf.h */; }; + 83C8B6E218AF58080071B040 /* vmulu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69218AF58080071B040 /* vmulu.h */; }; + 83C8B6E318AF58080071B040 /* vnand.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69318AF58080071B040 /* vnand.h */; }; + 83C8B6E418AF58080071B040 /* vne.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69418AF58080071B040 /* vne.h */; }; + 83C8B6E518AF58080071B040 /* vnop.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69518AF58080071B040 /* vnop.h */; }; + 83C8B6E618AF58080071B040 /* vnor.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69618AF58080071B040 /* vnor.h */; }; + 83C8B6E718AF58080071B040 /* vnxor.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69718AF58080071B040 /* vnxor.h */; }; + 83C8B6E818AF58080071B040 /* vor.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69818AF58080071B040 /* vor.h */; }; + 83C8B6E918AF58080071B040 /* vrcp.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69918AF58080071B040 /* vrcp.h */; }; + 83C8B6EA18AF58090071B040 /* vrcph.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69A18AF58080071B040 /* vrcph.h */; }; + 83C8B6EB18AF58090071B040 /* vrcpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69B18AF58080071B040 /* vrcpl.h */; }; + 83C8B6EC18AF58090071B040 /* vrsq.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69C18AF58080071B040 /* vrsq.h */; }; + 83C8B6ED18AF58090071B040 /* vrsqh.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69D18AF58080071B040 /* vrsqh.h */; }; + 83C8B6EE18AF58090071B040 /* vrsql.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69E18AF58080071B040 /* vrsql.h */; }; + 83C8B6EF18AF58090071B040 /* vsaw.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B69F18AF58080071B040 /* vsaw.h */; }; + 83C8B6F018AF58090071B040 /* vsub.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A018AF58080071B040 /* vsub.h */; }; + 83C8B6F118AF58090071B040 /* vsubc.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A118AF58080071B040 /* vsubc.h */; }; + 83C8B6F218AF58090071B040 /* vu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A218AF58080071B040 /* vu.h */; }; + 83C8B6F318AF58090071B040 /* vxor.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A318AF58080071B040 /* vxor.h */; }; + 83C8B6F418AF58090071B040 /* rsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A418AF58080071B040 /* rsp.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6F518AF58090071B040 /* tlb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B6A518AF58080071B040 /* tlb.c */; }; + 83C8B6F618AF58090071B040 /* tlb.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A618AF58080071B040 /* tlb.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6F718AF58090071B040 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A718AF58080071B040 /* types.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 83C8B6F818AF58090071B040 /* usf_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6A818AF58080071B040 /* usf_internal.h */; }; + 83C8B6F918AF58090071B040 /* usf.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8B6A918AF58080071B040 /* usf.c */; }; + 83C8B6FA18AF58090071B040 /* usf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8B6AA18AF58080071B040 /* usf.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 83C8B6FE18AF59E70071B040 /* lazyusf-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 83C8B6FD18AF59E70071B040 /* lazyusf-Info.plist */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 83C8B62218AF57770071B040 /* lazyusf.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = lazyusf.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 83C8B65918AF58080071B040 /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audio.c; sourceTree = ""; }; + 83C8B65A18AF58080071B040 /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = ""; }; + 83C8B65B18AF58080071B040 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + 83C8B65C18AF58080071B040 /* cpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cpu.c; sourceTree = ""; }; + 83C8B65D18AF58080071B040 /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = ""; }; + 83C8B65E18AF58080071B040 /* dma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dma.c; sourceTree = ""; }; + 83C8B65F18AF58080071B040 /* dma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dma.h; sourceTree = ""; }; + 83C8B66018AF58080071B040 /* exception.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exception.c; sourceTree = ""; }; + 83C8B66118AF58080071B040 /* exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exception.h; sourceTree = ""; }; + 83C8B66218AF58080071B040 /* interpreter_cpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interpreter_cpu.c; sourceTree = ""; }; + 83C8B66318AF58080071B040 /* interpreter_cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_cpu.h; sourceTree = ""; }; + 83C8B66418AF58080071B040 /* interpreter_ops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interpreter_ops.c; sourceTree = ""; }; + 83C8B66518AF58080071B040 /* interpreter_ops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter_ops.h; sourceTree = ""; }; + 83C8B66618AF58080071B040 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 83C8B66718AF58080071B040 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = ""; }; + 83C8B66818AF58080071B040 /* memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = memory.c; sourceTree = ""; }; + 83C8B66918AF58080071B040 /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memory.h; sourceTree = ""; }; + 83C8B66A18AF58080071B040 /* opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opcode.h; sourceTree = ""; }; + 83C8B66B18AF58080071B040 /* pif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pif.c; sourceTree = ""; }; + 83C8B66C18AF58080071B040 /* pif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pif.h; sourceTree = ""; }; + 83C8B66D18AF58080071B040 /* registers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = registers.c; sourceTree = ""; }; + 83C8B66E18AF58080071B040 /* registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = registers.h; sourceTree = ""; }; + 83C8B67018AF58080071B040 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + 83C8B67118AF58080071B040 /* execute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = execute.h; sourceTree = ""; }; + 83C8B67218AF58080071B040 /* rsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rsp.c; sourceTree = ""; }; + 83C8B67318AF58080071B040 /* rsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rsp.h; sourceTree = ""; }; + 83C8B67418AF58080071B040 /* su.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = su.h; sourceTree = ""; }; + 83C8B67618AF58080071B040 /* cf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cf.h; sourceTree = ""; }; + 83C8B67718AF58080071B040 /* clamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = clamp.h; sourceTree = ""; }; + 83C8B67818AF58080071B040 /* divrom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = divrom.h; sourceTree = ""; }; + 83C8B67918AF58080071B040 /* shuffle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shuffle.h; sourceTree = ""; }; + 83C8B67A18AF58080071B040 /* vabs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vabs.h; sourceTree = ""; }; + 83C8B67B18AF58080071B040 /* vadd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vadd.h; sourceTree = ""; }; + 83C8B67C18AF58080071B040 /* vaddc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vaddc.h; sourceTree = ""; }; + 83C8B67D18AF58080071B040 /* vand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vand.h; sourceTree = ""; }; + 83C8B67E18AF58080071B040 /* vch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vch.h; sourceTree = ""; }; + 83C8B67F18AF58080071B040 /* vcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vcl.h; sourceTree = ""; }; + 83C8B68018AF58080071B040 /* vcr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vcr.h; sourceTree = ""; }; + 83C8B68118AF58080071B040 /* veq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = veq.h; sourceTree = ""; }; + 83C8B68218AF58080071B040 /* vge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vge.h; sourceTree = ""; }; + 83C8B68318AF58080071B040 /* vlt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vlt.h; sourceTree = ""; }; + 83C8B68418AF58080071B040 /* vmacf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmacf.h; sourceTree = ""; }; + 83C8B68518AF58080071B040 /* vmacq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmacq.h; sourceTree = ""; }; + 83C8B68618AF58080071B040 /* vmacu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmacu.h; sourceTree = ""; }; + 83C8B68718AF58080071B040 /* vmadh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmadh.h; sourceTree = ""; }; + 83C8B68818AF58080071B040 /* vmadl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmadl.h; sourceTree = ""; }; + 83C8B68918AF58080071B040 /* vmadm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmadm.h; sourceTree = ""; }; + 83C8B68A18AF58080071B040 /* vmadn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmadn.h; sourceTree = ""; }; + 83C8B68B18AF58080071B040 /* vmov.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmov.h; sourceTree = ""; }; + 83C8B68C18AF58080071B040 /* vmrg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmrg.h; sourceTree = ""; }; + 83C8B68D18AF58080071B040 /* vmudh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmudh.h; sourceTree = ""; }; + 83C8B68E18AF58080071B040 /* vmudl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmudl.h; sourceTree = ""; }; + 83C8B68F18AF58080071B040 /* vmudm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmudm.h; sourceTree = ""; }; + 83C8B69018AF58080071B040 /* vmudn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmudn.h; sourceTree = ""; }; + 83C8B69118AF58080071B040 /* vmulf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmulf.h; sourceTree = ""; }; + 83C8B69218AF58080071B040 /* vmulu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmulu.h; sourceTree = ""; }; + 83C8B69318AF58080071B040 /* vnand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vnand.h; sourceTree = ""; }; + 83C8B69418AF58080071B040 /* vne.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vne.h; sourceTree = ""; }; + 83C8B69518AF58080071B040 /* vnop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vnop.h; sourceTree = ""; }; + 83C8B69618AF58080071B040 /* vnor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vnor.h; sourceTree = ""; }; + 83C8B69718AF58080071B040 /* vnxor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vnxor.h; sourceTree = ""; }; + 83C8B69818AF58080071B040 /* vor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vor.h; sourceTree = ""; }; + 83C8B69918AF58080071B040 /* vrcp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrcp.h; sourceTree = ""; }; + 83C8B69A18AF58080071B040 /* vrcph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrcph.h; sourceTree = ""; }; + 83C8B69B18AF58080071B040 /* vrcpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrcpl.h; sourceTree = ""; }; + 83C8B69C18AF58080071B040 /* vrsq.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrsq.h; sourceTree = ""; }; + 83C8B69D18AF58080071B040 /* vrsqh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrsqh.h; sourceTree = ""; }; + 83C8B69E18AF58080071B040 /* vrsql.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrsql.h; sourceTree = ""; }; + 83C8B69F18AF58080071B040 /* vsaw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vsaw.h; sourceTree = ""; }; + 83C8B6A018AF58080071B040 /* vsub.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vsub.h; sourceTree = ""; }; + 83C8B6A118AF58080071B040 /* vsubc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vsubc.h; sourceTree = ""; }; + 83C8B6A218AF58080071B040 /* vu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vu.h; sourceTree = ""; }; + 83C8B6A318AF58080071B040 /* vxor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vxor.h; sourceTree = ""; }; + 83C8B6A418AF58080071B040 /* rsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rsp.h; sourceTree = ""; }; + 83C8B6A518AF58080071B040 /* tlb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tlb.c; sourceTree = ""; }; + 83C8B6A618AF58080071B040 /* tlb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tlb.h; sourceTree = ""; }; + 83C8B6A718AF58080071B040 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; + 83C8B6A818AF58080071B040 /* usf_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usf_internal.h; sourceTree = ""; }; + 83C8B6A918AF58080071B040 /* usf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = usf.c; sourceTree = ""; }; + 83C8B6AA18AF58080071B040 /* usf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = usf.h; sourceTree = ""; }; + 83C8B6FD18AF59E70071B040 /* lazyusf-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "lazyusf-Info.plist"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 83C8B61E18AF57770071B040 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 83C8B61818AF57770071B040 = { + isa = PBXGroup; + children = ( + 83C8B62B18AF57770071B040 /* lazyusf */, + 83C8B62418AF57770071B040 /* Frameworks */, + 83C8B62318AF57770071B040 /* Products */, + ); + sourceTree = ""; + }; + 83C8B62318AF57770071B040 /* Products */ = { + isa = PBXGroup; + children = ( + 83C8B62218AF57770071B040 /* lazyusf.framework */, + ); + name = Products; + sourceTree = ""; + }; + 83C8B62418AF57770071B040 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 83C8B62718AF57770071B040 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 83C8B62718AF57770071B040 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 83C8B62B18AF57770071B040 /* lazyusf */ = { + isa = PBXGroup; + children = ( + 83C8B6FD18AF59E70071B040 /* lazyusf-Info.plist */, + 83C8B65918AF58080071B040 /* audio.c */, + 83C8B65A18AF58080071B040 /* audio.h */, + 83C8B65B18AF58080071B040 /* config.h */, + 83C8B65C18AF58080071B040 /* cpu.c */, + 83C8B65D18AF58080071B040 /* cpu.h */, + 83C8B65E18AF58080071B040 /* dma.c */, + 83C8B65F18AF58080071B040 /* dma.h */, + 83C8B66018AF58080071B040 /* exception.c */, + 83C8B66118AF58080071B040 /* exception.h */, + 83C8B66218AF58080071B040 /* interpreter_cpu.c */, + 83C8B66318AF58080071B040 /* interpreter_cpu.h */, + 83C8B66418AF58080071B040 /* interpreter_ops.c */, + 83C8B66518AF58080071B040 /* interpreter_ops.h */, + 83C8B66618AF58080071B040 /* main.c */, + 83C8B66718AF58080071B040 /* main.h */, + 83C8B66818AF58080071B040 /* memory.c */, + 83C8B66918AF58080071B040 /* memory.h */, + 83C8B66A18AF58080071B040 /* opcode.h */, + 83C8B66B18AF58080071B040 /* pif.c */, + 83C8B66C18AF58080071B040 /* pif.h */, + 83C8B66D18AF58080071B040 /* registers.c */, + 83C8B66E18AF58080071B040 /* registers.h */, + 83C8B66F18AF58080071B040 /* rsp */, + 83C8B6A418AF58080071B040 /* rsp.h */, + 83C8B6A518AF58080071B040 /* tlb.c */, + 83C8B6A618AF58080071B040 /* tlb.h */, + 83C8B6A718AF58080071B040 /* types.h */, + 83C8B6A818AF58080071B040 /* usf_internal.h */, + 83C8B6A918AF58080071B040 /* usf.c */, + 83C8B6AA18AF58080071B040 /* usf.h */, + 83C8B62C18AF57770071B040 /* Supporting Files */, + ); + path = lazyusf; + sourceTree = ""; + }; + 83C8B62C18AF57770071B040 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 83C8B66F18AF58080071B040 /* rsp */ = { + isa = PBXGroup; + children = ( + 83C8B67018AF58080071B040 /* config.h */, + 83C8B67118AF58080071B040 /* execute.h */, + 83C8B67218AF58080071B040 /* rsp.c */, + 83C8B67318AF58080071B040 /* rsp.h */, + 83C8B67418AF58080071B040 /* su.h */, + 83C8B67518AF58080071B040 /* vu */, + ); + path = rsp; + sourceTree = ""; + }; + 83C8B67518AF58080071B040 /* vu */ = { + isa = PBXGroup; + children = ( + 83C8B67618AF58080071B040 /* cf.h */, + 83C8B67718AF58080071B040 /* clamp.h */, + 83C8B67818AF58080071B040 /* divrom.h */, + 83C8B67918AF58080071B040 /* shuffle.h */, + 83C8B67A18AF58080071B040 /* vabs.h */, + 83C8B67B18AF58080071B040 /* vadd.h */, + 83C8B67C18AF58080071B040 /* vaddc.h */, + 83C8B67D18AF58080071B040 /* vand.h */, + 83C8B67E18AF58080071B040 /* vch.h */, + 83C8B67F18AF58080071B040 /* vcl.h */, + 83C8B68018AF58080071B040 /* vcr.h */, + 83C8B68118AF58080071B040 /* veq.h */, + 83C8B68218AF58080071B040 /* vge.h */, + 83C8B68318AF58080071B040 /* vlt.h */, + 83C8B68418AF58080071B040 /* vmacf.h */, + 83C8B68518AF58080071B040 /* vmacq.h */, + 83C8B68618AF58080071B040 /* vmacu.h */, + 83C8B68718AF58080071B040 /* vmadh.h */, + 83C8B68818AF58080071B040 /* vmadl.h */, + 83C8B68918AF58080071B040 /* vmadm.h */, + 83C8B68A18AF58080071B040 /* vmadn.h */, + 83C8B68B18AF58080071B040 /* vmov.h */, + 83C8B68C18AF58080071B040 /* vmrg.h */, + 83C8B68D18AF58080071B040 /* vmudh.h */, + 83C8B68E18AF58080071B040 /* vmudl.h */, + 83C8B68F18AF58080071B040 /* vmudm.h */, + 83C8B69018AF58080071B040 /* vmudn.h */, + 83C8B69118AF58080071B040 /* vmulf.h */, + 83C8B69218AF58080071B040 /* vmulu.h */, + 83C8B69318AF58080071B040 /* vnand.h */, + 83C8B69418AF58080071B040 /* vne.h */, + 83C8B69518AF58080071B040 /* vnop.h */, + 83C8B69618AF58080071B040 /* vnor.h */, + 83C8B69718AF58080071B040 /* vnxor.h */, + 83C8B69818AF58080071B040 /* vor.h */, + 83C8B69918AF58080071B040 /* vrcp.h */, + 83C8B69A18AF58080071B040 /* vrcph.h */, + 83C8B69B18AF58080071B040 /* vrcpl.h */, + 83C8B69C18AF58080071B040 /* vrsq.h */, + 83C8B69D18AF58080071B040 /* vrsqh.h */, + 83C8B69E18AF58080071B040 /* vrsql.h */, + 83C8B69F18AF58080071B040 /* vsaw.h */, + 83C8B6A018AF58080071B040 /* vsub.h */, + 83C8B6A118AF58080071B040 /* vsubc.h */, + 83C8B6A218AF58080071B040 /* vu.h */, + 83C8B6A318AF58080071B040 /* vxor.h */, + ); + path = vu; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 83C8B61F18AF57770071B040 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 83C8B6FA18AF58090071B040 /* usf.h in Headers */, + 83C8B6AC18AF58080071B040 /* audio.h in Headers */, + 83C8B6B118AF58080071B040 /* dma.h in Headers */, + 83C8B6AD18AF58080071B040 /* config.h in Headers */, + 83C8B6B518AF58080071B040 /* interpreter_cpu.h in Headers */, + 83C8B6B918AF58080071B040 /* main.h in Headers */, + 83C8B6F418AF58090071B040 /* rsp.h in Headers */, + 83C8B6C018AF58080071B040 /* registers.h in Headers */, + 83C8B6BE18AF58080071B040 /* pif.h in Headers */, + 83C8B6F618AF58090071B040 /* tlb.h in Headers */, + 83C8B6F718AF58090071B040 /* types.h in Headers */, + 83C8B6BB18AF58080071B040 /* memory.h in Headers */, + 83C8B6BC18AF58080071B040 /* opcode.h in Headers */, + 83C8B6B718AF58080071B040 /* interpreter_ops.h in Headers */, + 83C8B6B318AF58080071B040 /* exception.h in Headers */, + 83C8B6AF18AF58080071B040 /* cpu.h in Headers */, + 83C8B6F118AF58090071B040 /* vsubc.h in Headers */, + 83C8B6F018AF58090071B040 /* vsub.h in Headers */, + 83C8B6E018AF58080071B040 /* vmudn.h in Headers */, + 83C8B6EF18AF58090071B040 /* vsaw.h in Headers */, + 83C8B6C918AF58080071B040 /* shuffle.h in Headers */, + 83C8B6DD18AF58080071B040 /* vmudh.h in Headers */, + 83C8B6E118AF58080071B040 /* vmulf.h in Headers */, + 83C8B6CE18AF58080071B040 /* vch.h in Headers */, + 83C8B6CB18AF58080071B040 /* vadd.h in Headers */, + 83C8B6D618AF58080071B040 /* vmacu.h in Headers */, + 83C8B6C618AF58080071B040 /* cf.h in Headers */, + 83C8B6E818AF58080071B040 /* vor.h in Headers */, + 83C8B6D918AF58080071B040 /* vmadm.h in Headers */, + 83C8B6E318AF58080071B040 /* vnand.h in Headers */, + 83C8B6D218AF58080071B040 /* vge.h in Headers */, + 83C8B6C518AF58080071B040 /* su.h in Headers */, + 83C8B6C218AF58080071B040 /* execute.h in Headers */, + 83C8B6E518AF58080071B040 /* vnop.h in Headers */, + 83C8B6E418AF58080071B040 /* vne.h in Headers */, + 83C8B6D418AF58080071B040 /* vmacf.h in Headers */, + 83C8B6DC18AF58080071B040 /* vmrg.h in Headers */, + 83C8B6C718AF58080071B040 /* clamp.h in Headers */, + 83C8B6D718AF58080071B040 /* vmadh.h in Headers */, + 83C8B6F318AF58090071B040 /* vxor.h in Headers */, + 83C8B6EC18AF58090071B040 /* vrsq.h in Headers */, + 83C8B6D018AF58080071B040 /* vcr.h in Headers */, + 83C8B6EA18AF58090071B040 /* vrcph.h in Headers */, + 83C8B6F818AF58090071B040 /* usf_internal.h in Headers */, + 83C8B6EE18AF58090071B040 /* vrsql.h in Headers */, + 83C8B6D118AF58080071B040 /* veq.h in Headers */, + 83C8B6CA18AF58080071B040 /* vabs.h in Headers */, + 83C8B6DB18AF58080071B040 /* vmov.h in Headers */, + 83C8B6ED18AF58090071B040 /* vrsqh.h in Headers */, + 83C8B6E618AF58080071B040 /* vnor.h in Headers */, + 83C8B6DE18AF58080071B040 /* vmudl.h in Headers */, + 83C8B6DA18AF58080071B040 /* vmadn.h in Headers */, + 83C8B6E218AF58080071B040 /* vmulu.h in Headers */, + 83C8B6CC18AF58080071B040 /* vaddc.h in Headers */, + 83C8B6D518AF58080071B040 /* vmacq.h in Headers */, + 83C8B6C418AF58080071B040 /* rsp.h in Headers */, + 83C8B6E918AF58080071B040 /* vrcp.h in Headers */, + 83C8B6D318AF58080071B040 /* vlt.h in Headers */, + 83C8B6C118AF58080071B040 /* config.h in Headers */, + 83C8B6DF18AF58080071B040 /* vmudm.h in Headers */, + 83C8B6D818AF58080071B040 /* vmadl.h in Headers */, + 83C8B6EB18AF58090071B040 /* vrcpl.h in Headers */, + 83C8B6CD18AF58080071B040 /* vand.h in Headers */, + 83C8B6CF18AF58080071B040 /* vcl.h in Headers */, + 83C8B6E718AF58080071B040 /* vnxor.h in Headers */, + 83C8B6C818AF58080071B040 /* divrom.h in Headers */, + 83C8B6F218AF58090071B040 /* vu.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 83C8B62118AF57770071B040 /* lazyusf */ = { + isa = PBXNativeTarget; + buildConfigurationList = 83C8B64A18AF57770071B040 /* Build configuration list for PBXNativeTarget "lazyusf" */; + buildPhases = ( + 83C8B61D18AF57770071B040 /* Sources */, + 83C8B61E18AF57770071B040 /* Frameworks */, + 83C8B61F18AF57770071B040 /* Headers */, + 83C8B62018AF57770071B040 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = lazyusf; + productName = lazyusf; + productReference = 83C8B62218AF57770071B040 /* lazyusf.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83C8B61918AF57770071B040 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Christopher Snowhill"; + }; + buildConfigurationList = 83C8B61C18AF57770071B040 /* Build configuration list for PBXProject "lazyusf" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 83C8B61818AF57770071B040; + productRefGroup = 83C8B62318AF57770071B040 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 83C8B62118AF57770071B040 /* lazyusf */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 83C8B62018AF57770071B040 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83C8B6FE18AF59E70071B040 /* lazyusf-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 83C8B61D18AF57770071B040 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 83C8B6F518AF58090071B040 /* tlb.c in Sources */, + 83C8B6C318AF58080071B040 /* rsp.c in Sources */, + 83C8B6BD18AF58080071B040 /* pif.c in Sources */, + 83C8B6B418AF58080071B040 /* interpreter_cpu.c in Sources */, + 83C8B6B618AF58080071B040 /* interpreter_ops.c in Sources */, + 83C8B6BA18AF58080071B040 /* memory.c in Sources */, + 83C8B6B018AF58080071B040 /* dma.c in Sources */, + 83C8B6AE18AF58080071B040 /* cpu.c in Sources */, + 83C8B6AB18AF58080071B040 /* audio.c in Sources */, + 83C8B6B218AF58080071B040 /* exception.c in Sources */, + 83C8B6BF18AF58080071B040 /* registers.c in Sources */, + 83C8B6F918AF58090071B040 /* usf.c in Sources */, + 83C8B6B818AF58080071B040 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 83C8B64818AF57770071B040 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 83C8B64918AF57770071B040 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SDKROOT = macosx; + }; + name = Release; + }; + 83C8B64B18AF57770071B040 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + ARCH_MIN_SSE2, + ); + INFOPLIST_FILE = "lazyusf/lazyusf-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + }; + name = Debug; + }; + 83C8B64C18AF57770071B040 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherit)", + ARCH_MIN_SSE2, + ); + INFOPLIST_FILE = "lazyusf/lazyusf-Info.plist"; + INSTALL_PATH = "@loader_path/../Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 83C8B61C18AF57770071B040 /* Build configuration list for PBXProject "lazyusf" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83C8B64818AF57770071B040 /* Debug */, + 83C8B64918AF57770071B040 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83C8B64A18AF57770071B040 /* Build configuration list for PBXNativeTarget "lazyusf" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83C8B64B18AF57770071B040 /* Debug */, + 83C8B64C18AF57770071B040 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83C8B61918AF57770071B040 /* Project object */; +} diff --git a/Frameworks/lazyusf/lazyusf/audio.c b/Frameworks/lazyusf/lazyusf/audio.c new file mode 100644 index 000000000..1b8d0b56a --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/audio.c @@ -0,0 +1,82 @@ +#include "usf.h" +#include "memory.h" +#include "audio.h" +#include +#include + +#include "usf_internal.h" + +void AddBuffer(usf_state_t *state, unsigned char *buf, unsigned int length) { + int32_t i, do_max; + int16_t * sample_buffer = state->sample_buffer; + + if(!state->cpu_running) + return; + + do_max = length >> 2; + if ( do_max > state->sample_buffer_count ) + do_max = state->sample_buffer_count; + + for (i = 0; i < do_max; ++i) + { + *sample_buffer++ = ((int16_t*)buf)[1]; + *sample_buffer++ = ((int16_t*)buf)[0]; + buf += 4; + } + + state->sample_buffer_count -= do_max; + state->sample_buffer = sample_buffer; + + length -= do_max << 2; + + if ( length ) + { + sample_buffer = state->samplebuf; + do_max = length >> 2; + for (i = 0; i < do_max; ++i) + { + *sample_buffer++ = ((int16_t*)buf)[1]; + *sample_buffer++ = ((int16_t*)buf)[0]; + buf += 4; + } + + state->samples_in_buffer = do_max; + state->cpu_running = 0; + } +} + +void AiLenChanged(usf_state_t * state) { + int32_t length = 0; + uint32_t address = (AI_DRAM_ADDR_REG & 0x00FFFFF8); + + length = AI_LEN_REG & 0x3FFF8; + + AddBuffer(state, state->RDRAM+address, length); + + if(length && !(AI_STATUS_REG&0x80000000)) { + const float VSyncTiming = 789000.0f; + double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4; + double CountsPerSecond = (double)((((double)VSyncTiming) * (double)60.0)) * 2.0; + double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond; + unsigned int IntScheduled = (unsigned int)((double)AI_LEN_REG * CountsPerByte); + + ChangeTimer(state,AiTimer,IntScheduled); + } + + if(state->enableFIFOfull) { + if(AI_STATUS_REG&0x40000000) + AI_STATUS_REG|=0x80000000; + } + + AI_STATUS_REG|=0x40000000; +} + +unsigned int AiReadLength(usf_state_t * state) { + AI_LEN_REG = 0; + return AI_LEN_REG; +} + +void AiDacrateChanged(usf_state_t * state, unsigned int value) { + AI_DACRATE_REG = value; + state->SampleRate = 48681812 / (AI_DACRATE_REG + 1); +} diff --git a/Frameworks/lazyusf/lazyusf/audio.h b/Frameworks/lazyusf/lazyusf/audio.h new file mode 100644 index 000000000..3721bab18 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/audio.h @@ -0,0 +1,12 @@ +#ifndef _AUDIO_H_ +#define _AUDIO_H_ + +#include "usf.h" +#include "cpu.h" +#include "memory.h" + +uint32_t AiReadLength(usf_state_t *); +void AiLenChanged(usf_state_t *); +void AiDacrateChanged(usf_state_t *, uint32_t value); + +#endif diff --git a/Frameworks/lazyusf/lazyusf/config.h b/Frameworks/lazyusf/lazyusf/config.h new file mode 100644 index 000000000..ab09878e1 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/config.h @@ -0,0 +1,63 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "lazyusf" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "lazyusf" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "lazyusf 1.0.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "lazyusf" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.0.0" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.0.0" + +/* Define to 1 if the X Window System is missing or not being used. */ +/* #undef X_DISPLAY_MISSING */ diff --git a/Frameworks/lazyusf/lazyusf/cpu.c b/Frameworks/lazyusf/lazyusf/cpu.c new file mode 100644 index 000000000..516bfd34a --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/cpu.c @@ -0,0 +1,551 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include "main.h" +#include "cpu.h" +#include "usf.h" +#include "audio.h" +#include "registers.h" +#include "rsp.h" + +#include "usf_internal.h" + +#include + +void ChangeCompareTimer(usf_state_t * state) { + uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER; + if ((NextCompare & 0x80000000) != 0) { NextCompare = 0x7FFFFFFF; } + if (NextCompare == 0) { NextCompare = 0x1; } + ChangeTimer(state,CompareTimer,NextCompare); +} + +void ChangeTimer(usf_state_t * state, int32_t Type, int32_t Value) { + if (Value == 0) { + state->Timers->NextTimer[Type] = 0; + state->Timers->Active[Type] = 0; + return; + } + state->Timers->NextTimer[Type] = Value - state->Timers->Timer; + state->Timers->Active[Type] = 1; + CheckTimer(state); +} + +void CheckTimer (usf_state_t * state) { + int32_t count; + + for (count = 0; count < MaxTimers; count++) { + if (!state->Timers->Active[count]) { continue; } + if (!(count == CompareTimer && state->Timers->NextTimer[count] == 0x7FFFFFFF)) { + state->Timers->NextTimer[count] += state->Timers->Timer; + } + } + state->Timers->CurrentTimerType = -1; + state->Timers->Timer = 0x7FFFFFFF; + for (count = 0; count < MaxTimers; count++) { + if (!state->Timers->Active[count]) { continue; } + if (state->Timers->NextTimer[count] >= state->Timers->Timer) { continue; } + state->Timers->Timer = state->Timers->NextTimer[count]; + state->Timers->CurrentTimerType = count; + } + if (state->Timers->CurrentTimerType == -1) { + DisplayError("No active timers ???\nEmulation Stoped"); + StopEmulation(state); + } + for (count = 0; count < MaxTimers; count++) { + if (!state->Timers->Active[count]) { continue; } + if (!(count == CompareTimer && state->Timers->NextTimer[count] == 0x7FFFFFFF)) { + state->Timers->NextTimer[count] -= state->Timers->Timer; + } + } + + if (state->Timers->NextTimer[CompareTimer] == 0x7FFFFFFF) { + uint32_t NextCompare = COMPARE_REGISTER - COUNT_REGISTER; + if ((NextCompare & 0x80000000) == 0 && NextCompare != 0x7FFFFFFF) { + ChangeCompareTimer(state); + } + } +} + + + +void CloseCpu (usf_state_t * state) { + uint32_t count = 0; + + if(!state->MemChunk) return; + if (!state->cpu_running) { return; } + + state->cpu_running = 0; + + for (count = 0; count < 3; count ++ ) { + state->CPU_Action->CloseCPU = 1; + state->CPU_Action->DoSomething = 1; + } + + state->CPURunning = 0; +} + +int32_t DelaySlotEffectsCompare (usf_state_t * state, uint32_t PC, uint32_t Reg1, uint32_t Reg2) { + OPCODE Command; + + if (!r4300i_LW_VAddr(state, PC + 4, (uint32_t*)&Command.Hex)) { + return 1; + } + + switch (Command.op) { + case R4300i_SPECIAL: + switch (Command.funct) { + case R4300i_SPECIAL_SLL: + case R4300i_SPECIAL_SRL: + case R4300i_SPECIAL_SRA: + case R4300i_SPECIAL_SLLV: + case R4300i_SPECIAL_SRLV: + case R4300i_SPECIAL_SRAV: + case R4300i_SPECIAL_MFHI: + case R4300i_SPECIAL_MTHI: + case R4300i_SPECIAL_MFLO: + case R4300i_SPECIAL_MTLO: + case R4300i_SPECIAL_DSLLV: + case R4300i_SPECIAL_DSRLV: + case R4300i_SPECIAL_DSRAV: + case R4300i_SPECIAL_ADD: + case R4300i_SPECIAL_ADDU: + case R4300i_SPECIAL_SUB: + case R4300i_SPECIAL_SUBU: + case R4300i_SPECIAL_AND: + case R4300i_SPECIAL_OR: + case R4300i_SPECIAL_XOR: + case R4300i_SPECIAL_NOR: + case R4300i_SPECIAL_SLT: + case R4300i_SPECIAL_SLTU: + case R4300i_SPECIAL_DADD: + case R4300i_SPECIAL_DADDU: + case R4300i_SPECIAL_DSUB: + case R4300i_SPECIAL_DSUBU: + case R4300i_SPECIAL_DSLL: + case R4300i_SPECIAL_DSRL: + case R4300i_SPECIAL_DSRA: + case R4300i_SPECIAL_DSLL32: + case R4300i_SPECIAL_DSRL32: + case R4300i_SPECIAL_DSRA32: + if (Command.rd == 0) { return 0; } + if (Command.rd == Reg1) { return 1; } + if (Command.rd == Reg2) { return 1; } + break; + case R4300i_SPECIAL_MULT: + case R4300i_SPECIAL_MULTU: + case R4300i_SPECIAL_DIV: + case R4300i_SPECIAL_DIVU: + case R4300i_SPECIAL_DMULT: + case R4300i_SPECIAL_DMULTU: + case R4300i_SPECIAL_DDIV: + case R4300i_SPECIAL_DDIVU: + break; + default: + return 1; + } + break; + case R4300i_CP0: + switch (Command.rs) { + case R4300i_COP0_MT: break; + case R4300i_COP0_MF: + if (Command.rt == 0) { return 0; } + if (Command.rt == Reg1) { return 1; } + if (Command.rt == Reg2) { return 1; } + break; + default: + if ( (Command.rs & 0x10 ) != 0 ) { + switch( state->Opcode.funct ) { + case R4300i_COP0_CO_TLBR: break; + case R4300i_COP0_CO_TLBWI: break; + case R4300i_COP0_CO_TLBWR: break; + case R4300i_COP0_CO_TLBP: break; + default: + return 1; + } + return 1; + } + } + break; + case R4300i_CP1: + switch (Command.fmt) { + case R4300i_COP1_MF: + if (Command.rt == 0) { return 0; } + if (Command.rt == Reg1) { return 1; } + if (Command.rt == Reg2) { return 1; } + break; + case R4300i_COP1_CF: break; + case R4300i_COP1_MT: break; + case R4300i_COP1_CT: break; + case R4300i_COP1_S: break; + case R4300i_COP1_D: break; + case R4300i_COP1_W: break; + case R4300i_COP1_L: break; + return 1; + } + break; + case R4300i_ANDI: + case R4300i_ORI: + case R4300i_XORI: + case R4300i_LUI: + case R4300i_ADDI: + case R4300i_ADDIU: + case R4300i_SLTI: + case R4300i_SLTIU: + case R4300i_DADDI: + case R4300i_DADDIU: + case R4300i_LB: + case R4300i_LH: + case R4300i_LW: + case R4300i_LWL: + case R4300i_LWR: + case R4300i_LDL: + case R4300i_LDR: + case R4300i_LBU: + case R4300i_LHU: + case R4300i_LD: + case R4300i_LWC1: + case R4300i_LDC1: + if (Command.rt == 0) { return 0; } + if (Command.rt == Reg1) { return 1; } + if (Command.rt == Reg2) { return 1; } + break; + case R4300i_CACHE: break; + case R4300i_SB: break; + case R4300i_SH: break; + case R4300i_SW: break; + case R4300i_SWR: break; + case R4300i_SWL: break; + case R4300i_SWC1: break; + case R4300i_SDC1: break; + case R4300i_SD: break; + default: + + return 1; + } + return 0; +} + +int32_t DelaySlotEffectsJump (usf_state_t * state, uint32_t JumpPC) { + OPCODE Command; + + if (!r4300i_LW_VAddr(state, JumpPC, &Command.Hex)) { return 1; } + + switch (Command.op) { + case R4300i_SPECIAL: + switch (Command.funct) { + case R4300i_SPECIAL_JR: return DelaySlotEffectsCompare(state,JumpPC,Command.rs,0); + case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,Command.rs,31); + } + break; + case R4300i_REGIMM: + switch (Command.rt) { + case R4300i_REGIMM_BLTZ: + case R4300i_REGIMM_BGEZ: + case R4300i_REGIMM_BLTZL: + case R4300i_REGIMM_BGEZL: + case R4300i_REGIMM_BLTZAL: + case R4300i_REGIMM_BGEZAL: + return DelaySlotEffectsCompare(state,JumpPC,Command.rs,0); + } + break; + case R4300i_JAL: + case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,31,0); break; + case R4300i_J: return 0; + case R4300i_BEQ: + case R4300i_BNE: + case R4300i_BLEZ: + case R4300i_BGTZ: + return DelaySlotEffectsCompare(state,JumpPC,Command.rs,Command.rt); + case R4300i_CP1: + switch (Command.fmt) { + case R4300i_COP1_BC: + switch (Command.ft) { + case R4300i_COP1_BC_BCF: + case R4300i_COP1_BC_BCT: + case R4300i_COP1_BC_BCFL: + case R4300i_COP1_BC_BCTL: + { + int32_t EffectDelaySlot; + OPCODE NewCommand; + + if (!r4300i_LW_VAddr(state, JumpPC + 4, &NewCommand.Hex)) { return 1; } + + EffectDelaySlot = 0; + if (NewCommand.op == R4300i_CP1) { + if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30 ) { + EffectDelaySlot = 1; + } + if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30 ) { + EffectDelaySlot = 1; + } + } + return EffectDelaySlot; + } + break; + } + break; + } + break; + case R4300i_BEQL: + case R4300i_BNEL: + case R4300i_BLEZL: + case R4300i_BGTZL: + return DelaySlotEffectsCompare(state,JumpPC,Command.rs,Command.rt); + } + return 1; +} + +void DoSomething ( usf_state_t * state ) { + if (state->CPU_Action->CloseCPU) { + //StopEmulation(); + state->cpu_running = 0; + //printf("Stopping?\n"); + } + if (state->CPU_Action->CheckInterrupts) { + state->CPU_Action->CheckInterrupts = 0; + CheckInterrupts(state); + } + if (state->CPU_Action->DoInterrupt) { + state->CPU_Action->DoInterrupt = 0; + DoIntrException(state, 0); + } + + + state->CPU_Action->DoSomething = 0; + + if (state->CPU_Action->DoInterrupt) { state->CPU_Action->DoSomething = 1; } +} + +void InPermLoop ( usf_state_t * state ) { + // *** Changed ***/ + if (state->CPU_Action->DoInterrupt) { return; } + + /* Interrupts enabled */ + if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { goto InterruptsDisabled; } + if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { goto InterruptsDisabled; } + if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { goto InterruptsDisabled; } + if (( STATUS_REGISTER & 0xFF00) == 0) { goto InterruptsDisabled; } + + /* check sound playing */ + + /* check RSP running */ + /* check RDP running */ + if (state->Timers->Timer >= 0) { + COUNT_REGISTER += state->Timers->Timer + 1; + state->Timers->Timer = -1; + } + return; + +InterruptsDisabled: + DisplayError("Stuck in Permanent Loop"); + StopEmulation(state); +} + +void ReadFromMem(const void * source, void * target, uint32_t length, uint32_t *offset) { + memcpy((uint8_t*)target,((uint8_t*)source)+*offset,length); + *offset+=length; +} + + +uint32_t Machine_LoadStateFromRAM(usf_state_t * state, void * savestatespace) { + uint8_t LoadHeader[0x40]; + uint32_t Value, count, SaveRDRAMSize, offset=0; + + ReadFromMem( savestatespace,&Value,sizeof(Value),&offset); + if (Value != 0x23D8A6C8) { return 0; } + ReadFromMem( savestatespace,&SaveRDRAMSize,sizeof(SaveRDRAMSize),&offset); + ReadFromMem( savestatespace,&LoadHeader,0x40,&offset); + + state->Timers->CurrentTimerType = -1; + state->Timers->Timer = 0; + for (count = 0; count < MaxTimers; count ++) { state->Timers->Active[count] = 0; } + + //fix rdram size + if (SaveRDRAMSize != state->RdramSize) { + // dothis :) + } + + state->RdramSize = SaveRDRAMSize; + + ReadFromMem( savestatespace,&Value,sizeof(Value),&offset); + ChangeTimer(state,ViTimer,Value); + ReadFromMem( savestatespace,&state->PROGRAM_COUNTER,sizeof(state->PROGRAM_COUNTER),&offset); + ReadFromMem( savestatespace,state->GPR,sizeof(int64_t)*32,&offset); + ReadFromMem( savestatespace,state->FPR,sizeof(int64_t)*32,&offset); + ReadFromMem( savestatespace,state->CP0,sizeof(uint32_t)*32,&offset); + ReadFromMem( savestatespace,state->FPCR,sizeof(uint32_t)*32,&offset); + ReadFromMem( savestatespace,&state->HI,sizeof(int64_t),&offset); + ReadFromMem( savestatespace,&state->LO,sizeof(int64_t),&offset); + ReadFromMem( savestatespace,state->RegRDRAM,sizeof(uint32_t)*10,&offset); + ReadFromMem( savestatespace,state->RegSP,sizeof(uint32_t)*10,&offset); + ReadFromMem( savestatespace,state->RegDPC,sizeof(uint32_t)*10,&offset); + ReadFromMem( savestatespace,state->RegMI,sizeof(uint32_t)*4,&offset); + ReadFromMem( savestatespace,state->RegVI,sizeof(uint32_t)*14,&offset); + ReadFromMem( savestatespace,state->RegAI,sizeof(uint32_t)*6,&offset); + ReadFromMem( savestatespace,state->RegPI,sizeof(uint32_t)*13,&offset); + ReadFromMem( savestatespace,state->RegRI,sizeof(uint32_t)*8,&offset); + ReadFromMem( savestatespace,state->RegSI,sizeof(uint32_t)*4,&offset); + ReadFromMem( savestatespace,state->tlb,sizeof(TLB)*32,&offset); + ReadFromMem( savestatespace,(uint8_t*)state->PIF_Ram,0x40,&offset); + ReadFromMem( savestatespace,state->RDRAM,SaveRDRAMSize,&offset); + ReadFromMem( savestatespace,state->DMEM,0x1000,&offset); + ReadFromMem( savestatespace,state->IMEM,0x1000,&offset); + + state->CP0[32] = 0; + + SetupTLB(state); + ChangeCompareTimer(state); + AI_STATUS_REG = 0; + AiDacrateChanged(state, AI_DACRATE_REG); + +// StartAiInterrupt(state); + + SetFpuLocations(state); // important if FR=1 + + return 1; +} + +void StartEmulationFromSave ( usf_state_t * state, void * savestate ) { + uint32_t count = 0; + + //printf("Starting generic Cpu\n"); + + //CloseCpu(); + memset(state->N64MEM, 0, state->RdramSize); + + memset(state->DMEM, 0, 0x1000); + memset(state->IMEM, 0, 0x1000); + memset(state->TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000); + + memset(state->CPU_Action,0,sizeof(state->CPU_Action)); + state->WrittenToRom = 0; + + InitilizeTLB(state); + + SetupRegisters(state, state->Registers); + + BuildInterpreter(state); + + state->Timers->CurrentTimerType = -1; + state->Timers->Timer = 0; + + for (count = 0; count < MaxTimers; count ++) { state->Timers->Active[count] = 0; } + ChangeTimer(state,ViTimer,5000); + ChangeCompareTimer(state); + state->ViFieldNumber = 0; + state->CPURunning = 1; + *state->WaitMode = 0; + + init_rsp(state); + + Machine_LoadStateFromRAM(state, savestate); + + state->SampleRate = 48681812 / (AI_DACRATE_REG + 1); + + if(state->enableFIFOfull) { + const float VSyncTiming = 789000.0f; + double BytesPerSecond = 48681812.0 / (AI_DACRATE_REG + 1) * 4; + double CountsPerSecond = (double)(((double)VSyncTiming) * (double)60.0); + double CountsPerByte = (double)CountsPerSecond / (double)BytesPerSecond; + uint32_t IntScheduled = (uint32_t)((double)AI_LEN_REG * CountsPerByte); + + ChangeTimer(state,AiTimer,IntScheduled); + AI_STATUS_REG|=0x40000000; + } +} + + +void RefreshScreen (usf_state_t * state){ + ChangeTimer(state, ViTimer, 300000); + +} + +void RunRsp (usf_state_t * state) { + if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0) { + if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 ) { + + uint32_t Task = *( uint32_t *)(state->DMEM + 0xFC0); + + switch (Task) { + case 1: { + MI_INTR_REG |= 0x20; + + SP_STATUS_REG |= (0x0203 ); + if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) + MI_INTR_REG |= 1; + + CheckInterrupts(state); + + DPC_STATUS_REG &= ~0x0002; + return; + + } + break; + case 2: { + + break; + } + break; + default: + + break; + } + + real_run_rsp(state, 100); + SP_STATUS_REG |= (0x0203 ); + if ((SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) { + MI_INTR_REG |= 1; + CheckInterrupts(state); + } + + } + } +} + +void TimerDone (usf_state_t * state) { + switch (state->Timers->CurrentTimerType) { + case CompareTimer: + if(state->enablecompare) + FAKE_CAUSE_REGISTER |= CAUSE_IP7; + //CheckInterrupts(); + ChangeCompareTimer(state); + break; + case ViTimer: + RefreshScreen(state); + MI_INTR_REG |= MI_INTR_VI; + CheckInterrupts(state); + *state->WaitMode=0; + break; + case AiTimer: + ChangeTimer(state,AiTimer,0); + AI_STATUS_REG=0; + state->AudioIntrReg|=4; + //CheckInterrupts(state); + break; + } + CheckTimer(state); +} diff --git a/Frameworks/lazyusf/lazyusf/cpu.h b/Frameworks/lazyusf/lazyusf/cpu.h new file mode 100644 index 000000000..0d7052df6 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/cpu.h @@ -0,0 +1,93 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#ifndef _CPU_H_ +#define _CPU_H_ + +#include "interpreter_cpu.h" +#include "interpreter_ops.h" +#include "registers.h" +#include "tlb.h" +#include "memory.h" +#include "dma.h" +#include "exception.h" +#include "pif.h" +#include "opcode.h" +#include "usf.h" + +typedef struct { + int32_t DoSomething; + int32_t CloseCPU; + int32_t CheckInterrupts; + int32_t DoInterrupt; +} CPU_ACTION; + +#define MaxTimers 3 +#define CompareTimer 0 +#define ViTimer 1 +#define AiTimer 2 + +typedef struct { + int32_t NextTimer[MaxTimers]; + int32_t Active[MaxTimers]; + int32_t CurrentTimerType; + int32_t Timer; +} SYSTEM_TIMERS; + +void ChangeCompareTimer ( usf_state_t * ); +void ChangeTimer ( usf_state_t *, int32_t Type, int32_t Value ); +void CheckTimer ( usf_state_t * ); +void CloseCpu ( usf_state_t * ); +int32_t DelaySlotEffectsCompare ( usf_state_t *, uint32_t PC, uint32_t Reg1, uint32_t Reg2 ); +int32_t DelaySlotEffectsJump ( usf_state_t *, uint32_t JumpPC); +void DoSomething ( usf_state_t * ); +void InPermLoop ( usf_state_t * ); +void InitiliazeCPUFlags ( usf_state_t * ); +void RefreshScreen ( usf_state_t * ); +void RunRsp ( usf_state_t * ); +void StartEmulation ( usf_state_t * ); +void TimerDone ( usf_state_t * ); +void RecompileTimerDone ( usf_state_t * ); + +#define NORMAL 0 +#define DO_DELAY_SLOT 1 +#define DO_END_DELAY_SLOT 2 +#define DELAY_SLOT 3 +#define END_DELAY_SLOT 4 +#define LIKELY_DELAY_SLOT 5 +#define JUMP 6 +#define DELAY_SLOT_DONE 7 +#define LIKELY_DELAY_SLOT_DONE 8 +#define END_BLOCK 9 + +enum SaveType { + Auto, + Eeprom_4K, + Eeprom_16K, + Sram, + FlashRam +}; + +#endif diff --git a/Frameworks/lazyusf/lazyusf/dma.c b/Frameworks/lazyusf/lazyusf/dma.c new file mode 100644 index 000000000..2c279069c --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/dma.c @@ -0,0 +1,177 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#include "main.h" +#include "cpu.h" + +#include "usf.h" +#include "usf_internal.h" + +void PI_DMA_READ (usf_state_t * state) { + + PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; + MI_INTR_REG |= MI_INTR_PI; + CheckInterrupts(state); + return; +} + +void PI_DMA_WRITE (usf_state_t * state) { + uint32_t i; + PI_STATUS_REG |= PI_STATUS_DMA_BUSY; + if ( PI_DRAM_ADDR_REG + PI_WR_LEN_REG + 1 > state->RdramSize) { + PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; + MI_INTR_REG |= MI_INTR_PI; + CheckInterrupts(state); + return; + } + + if ( PI_CART_ADDR_REG >= 0x08000000 && PI_CART_ADDR_REG <= 0x08010000) { + return; + } + + if ( PI_CART_ADDR_REG >= 0x10000000 && PI_CART_ADDR_REG <= 0x1FBFFFFF) { + PI_CART_ADDR_REG -= 0x10000000; + for (i = 0; i < PI_WR_LEN_REG + 1; i ++) { + *(state->N64MEM+((PI_DRAM_ADDR_REG + i) ^ 3)) = *PageROM(state, (PI_CART_ADDR_REG + i) ^ 3); + } + PI_CART_ADDR_REG += 0x10000000; + + PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; + MI_INTR_REG |= MI_INTR_PI; + CheckInterrupts(state); + CheckTimer(state); + return; + } + + PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY; + MI_INTR_REG |= MI_INTR_PI; + CheckInterrupts(state); +} + + +void SI_DMA_READ (usf_state_t * state) { + + if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)state->RdramSize) { + return; + } + + PifRamRead(state); + SI_DRAM_ADDR_REG &= 0xFFFFFFF8; + if ((int32_t)SI_DRAM_ADDR_REG < 0) { + int32_t count, RdramPos; + + RdramPos = (int32_t)SI_DRAM_ADDR_REG; + for (count = 0; count < 0x40; count++, RdramPos++) { + if (RdramPos < 0) { continue; } + state->N64MEM[RdramPos ^3] = state->PIF_Ram[count]; + } + } else { + int32_t count, RdramPos; + + RdramPos = (uint32_t)SI_DRAM_ADDR_REG; + for (count = 0; count < 0x40; count++, RdramPos++) { + if (RdramPos < 0) { continue; } + state->N64MEM[RdramPos ^3] = state->PIF_Ram[count]; + } + } + + MI_INTR_REG |= MI_INTR_SI; + SI_STATUS_REG |= SI_STATUS_INTERRUPT; + CheckInterrupts(state); +} + + +void SI_DMA_WRITE (usf_state_t * state) { + + if ((int32_t)SI_DRAM_ADDR_REG > (int32_t)state->RdramSize) { + return; + } + + SI_DRAM_ADDR_REG &= 0xFFFFFFF8; + if ((int32_t)SI_DRAM_ADDR_REG < 0) { + int32_t count, RdramPos; + + RdramPos = (int32_t)SI_DRAM_ADDR_REG; + for (count = 0; count < 0x40; count++, RdramPos++) { + if (RdramPos < 0) { state->PIF_Ram[count] = 0; continue; } + state->PIF_Ram[count] = state->N64MEM[RdramPos ^3]; + } + } else { + int32_t count, RdramPos; + + RdramPos = (int32_t)SI_DRAM_ADDR_REG; + for (count = 0; count < 0x40; count++, RdramPos++) { + if (RdramPos < 0) { state->PIF_Ram[count] = 0; continue; } + state->PIF_Ram[count] = state->N64MEM[RdramPos ^3]; + } + } + + PifRamWrite(state); + + MI_INTR_REG |= MI_INTR_SI; + SI_STATUS_REG |= SI_STATUS_INTERRUPT; + CheckInterrupts(state); + +} + +void SP_DMA_READ (usf_state_t * state) { + SP_DRAM_ADDR_REG &= 0x1FFFFFFF; + + if (SP_DRAM_ADDR_REG > state->RdramSize) { + SP_DMA_BUSY_REG = 0; + SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; + return; + } + + if (SP_RD_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) { + return; + } + + memcpy( state->DMEM + (SP_MEM_ADDR_REG & 0x1FFF), state->N64MEM + SP_DRAM_ADDR_REG, + SP_RD_LEN_REG + 1 ); + + SP_DMA_BUSY_REG = 0; + SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; + MI_INTR_REG &= ~MI_INTR_SP; + CheckInterrupts(state); + CheckTimer(state); +} + +void SP_DMA_WRITE (usf_state_t * state) { + if (SP_DRAM_ADDR_REG > state->RdramSize) { + return; + } + + if (SP_WR_LEN_REG + 1 + (SP_MEM_ADDR_REG & 0xFFF) > 0x1000) { + return; + } + + memcpy( state->N64MEM + SP_DRAM_ADDR_REG, state->DMEM + (SP_MEM_ADDR_REG & 0x1FFF), + SP_WR_LEN_REG + 1); + + SP_DMA_BUSY_REG = 0; + SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; +} + diff --git a/Frameworks/lazyusf/lazyusf/dma.h b/Frameworks/lazyusf/lazyusf/dma.h new file mode 100644 index 000000000..8d9adb223 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/dma.h @@ -0,0 +1,34 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +void PI_DMA_READ ( usf_state_t * ); +void PI_DMA_WRITE ( usf_state_t * ); +void SI_DMA_READ ( usf_state_t * ); +void SI_DMA_WRITE ( usf_state_t * ); +void SP_DMA_READ ( usf_state_t * ); +void SP_DMA_WRITE ( usf_state_t * ); + + + diff --git a/Frameworks/lazyusf/lazyusf/exception.c b/Frameworks/lazyusf/lazyusf/exception.c new file mode 100644 index 000000000..01eaf9bb7 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/exception.c @@ -0,0 +1,147 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include "main.h" +#include "cpu.h" + +#include "usf_internal.h" + +void CheckInterrupts ( usf_state_t * state ) { + + MI_INTR_REG &= ~MI_INTR_AI; + MI_INTR_REG |= (state->AudioIntrReg & MI_INTR_AI); + if ((MI_INTR_MASK_REG & MI_INTR_REG) != 0) { + FAKE_CAUSE_REGISTER |= CAUSE_IP2; + } else { + FAKE_CAUSE_REGISTER &= ~CAUSE_IP2; + } + + if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; } + if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; } + if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; } + + if (( STATUS_REGISTER & FAKE_CAUSE_REGISTER & 0xFF00) != 0) { + if (!state->CPU_Action->DoInterrupt) { + state->CPU_Action->DoSomething = 1; + state->CPU_Action->DoInterrupt = 1; + } + } +} + +void DoAddressError ( usf_state_t * state, uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead) { + if (FromRead) { + CAUSE_REGISTER = EXC_RADE; + } else { + CAUSE_REGISTER = EXC_WADE; + } + BAD_VADDR_REGISTER = BadVaddr; + if (DelaySlot) { + CAUSE_REGISTER |= CAUSE_BD; + EPC_REGISTER = state->PROGRAM_COUNTER - 4; + } else { + EPC_REGISTER = state->PROGRAM_COUNTER; + } + STATUS_REGISTER |= STATUS_EXL; + state->PROGRAM_COUNTER = 0x80000180; +} + +void DoBreakException ( usf_state_t * state, uint32_t DelaySlot) { + CAUSE_REGISTER = EXC_BREAK; + if (DelaySlot) { + CAUSE_REGISTER |= CAUSE_BD; + EPC_REGISTER = state->PROGRAM_COUNTER - 4; + } else { + EPC_REGISTER = state->PROGRAM_COUNTER; + } + STATUS_REGISTER |= STATUS_EXL; + state->PROGRAM_COUNTER = 0x80000180; +} + +void DoCopUnusableException ( usf_state_t * state, uint32_t DelaySlot, uint32_t Coprocessor ) { + CAUSE_REGISTER = EXC_CPU; + if (Coprocessor == 1) { CAUSE_REGISTER |= 0x10000000; } + if (DelaySlot) { + CAUSE_REGISTER |= CAUSE_BD; + EPC_REGISTER = state->PROGRAM_COUNTER - 4; + } else { + EPC_REGISTER = state->PROGRAM_COUNTER; + } + STATUS_REGISTER |= STATUS_EXL; + state->PROGRAM_COUNTER = 0x80000180; +} + +void DoIntrException ( usf_state_t * state, uint32_t DelaySlot ) { + + if (( STATUS_REGISTER & STATUS_IE ) == 0 ) { return; } + if (( STATUS_REGISTER & STATUS_EXL ) != 0 ) { return; } + if (( STATUS_REGISTER & STATUS_ERL ) != 0 ) { return; } + CAUSE_REGISTER = FAKE_CAUSE_REGISTER; + CAUSE_REGISTER |= EXC_INT; + EPC_REGISTER = state->PROGRAM_COUNTER; + if (DelaySlot) { + CAUSE_REGISTER |= CAUSE_BD; + EPC_REGISTER -= 4; + } + STATUS_REGISTER |= STATUS_EXL; + state->PROGRAM_COUNTER = 0x80000180; +} + +void DoTLBMiss ( usf_state_t * state, uint32_t DelaySlot, uint32_t BadVaddr ) { + + CAUSE_REGISTER = EXC_RMISS; + BAD_VADDR_REGISTER = BadVaddr; + CONTEXT_REGISTER &= 0xFF80000F; + CONTEXT_REGISTER |= (BadVaddr >> 9) & 0x007FFFF0; + ENTRYHI_REGISTER = (BadVaddr & 0xFFFFE000); + if ((STATUS_REGISTER & STATUS_EXL) == 0) { + if (DelaySlot) { + CAUSE_REGISTER |= CAUSE_BD; + EPC_REGISTER = state->PROGRAM_COUNTER - 4; + } else { + EPC_REGISTER = state->PROGRAM_COUNTER; + } + if (AddressDefined(state, BadVaddr)) { + state->PROGRAM_COUNTER = 0x80000180; + } else { + state->PROGRAM_COUNTER = 0x80000000; + } + STATUS_REGISTER |= STATUS_EXL; + } else { + state->PROGRAM_COUNTER = 0x80000180; + } +} + +void DoSysCallException ( usf_state_t * state, uint32_t DelaySlot) { + CAUSE_REGISTER = EXC_SYSCALL; + if (DelaySlot) { + CAUSE_REGISTER |= CAUSE_BD; + EPC_REGISTER = state->PROGRAM_COUNTER - 4; + } else { + EPC_REGISTER = state->PROGRAM_COUNTER; + } + STATUS_REGISTER |= STATUS_EXL; + state->PROGRAM_COUNTER = 0x80000180; +} diff --git a/Frameworks/lazyusf/lazyusf/exception.h b/Frameworks/lazyusf/lazyusf/exception.h new file mode 100644 index 000000000..7ee97d58e --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/exception.h @@ -0,0 +1,75 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#define EXC_CODE(x) ((x)<<2) +#define EXC_INT EXC_CODE(0) /* interrupt */ +#define EXC_MOD EXC_CODE(1) /* TLB mod */ +#define EXC_RMISS EXC_CODE(2) /* Read TLB Miss */ +#define EXC_WMISS EXC_CODE(3) /* Write TLB Miss */ +#define EXC_RADE EXC_CODE(4) /* Read Address Error */ +#define EXC_WADE EXC_CODE(5) /* Write Address Error */ +#define EXC_IBE EXC_CODE(6) /* Instruction Bus Error */ +#define EXC_DBE EXC_CODE(7) /* Data Bus Error */ +#define EXC_SYSCALL EXC_CODE(8) /* SYSCALL */ +#define EXC_BREAK EXC_CODE(9) /* BREAKpoint */ +#define EXC_II EXC_CODE(10)/* Illegal Instruction */ +#define EXC_CPU EXC_CODE(11)/* CoProcessor Unusable */ +#define EXC_OV EXC_CODE(12)/* OVerflow */ +#define EXC_TRAP EXC_CODE(13)/* Trap exception */ +#define EXC_VCEI EXC_CODE(14)/* Virt. Coherency on Inst. fetch */ +#define EXC_FPE EXC_CODE(15)/* Floating Point Exception */ +#define EXC_WATCH EXC_CODE(23)/* Watchpoint reference */ +#define EXC_VCED EXC_CODE(31)/* Virt. Coherency on data read */ + +#define Exception_Name(Except)\ + (Except) == EXC_INT ? "interrupt" :\ + (Except) == EXC_MOD ? "TLB mod" :\ + (Except) == EXC_RMISS ? "Read TLB Miss" :\ + (Except) == EXC_WMISS ? "Write TLB Miss" :\ + (Except) == EXC_RADE ? "Read Address Error" :\ + (Except) == EXC_WADE ? "Write Address Error" :\ + (Except) == EXC_IBE ? "Instruction Bus Error" :\ + (Except) == EXC_DBE ? "Data Bus Error" :\ + (Except) == EXC_SYSCALL ? "SYSCALL" :\ + (Except) == EXC_BREAK ? "Break" :\ + (Except) == EXC_II ? "Illegal Instruction" :\ + (Except) == EXC_CPU ? "CoProcessor Unusable" :\ + (Except) == EXC_OV ? "OVerflow" :\ + (Except) == EXC_TRAP ? "Trap exception" :\ + (Except) == EXC_VCEI ? "Virt. Coherency on Inst. fetch" :\ + (Except) == EXC_FPE ? "Floating Point Exception" :\ + (Except) == EXC_WATCH ? "Watchpoint reference" :\ + (Except) == EXC_VCED ? "Virt. Coherency on data read" :\ + "Unkown" + +void AiCheckInterrupts ( usf_state_t * ); +void CheckInterrupts ( usf_state_t * ); +void DoAddressError ( usf_state_t *, uint32_t DelaySlot, uint32_t BadVaddr, uint32_t FromRead ); +void DoBreakException ( usf_state_t *, uint32_t DelaySlot ); +void DoCopUnusableException ( usf_state_t *, uint32_t DelaySlot, uint32_t Coprocessor ); +void DoIntrException ( usf_state_t *, uint32_t DelaySlot ); +void DoTLBMiss ( usf_state_t *, uint32_t DelaySlot, uint32_t BadVaddr ); +void DoSysCallException ( usf_state_t *, uint32_t DelaySlot); + diff --git a/Frameworks/lazyusf/lazyusf/interpreter_cpu.c b/Frameworks/lazyusf/lazyusf/interpreter_cpu.c new file mode 100644 index 000000000..c0ad8f28d --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/interpreter_cpu.c @@ -0,0 +1,738 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#include +#include "main.h" +#include "cpu.h" +#include "usf.h" +#include "memory.h" + +#include "usf_internal.h" + +#include + +void (* R4300i_Opcode[64])(usf_state_t *); +void (* R4300i_Special[64])(usf_state_t *); +void (* R4300i_Regimm[32])(usf_state_t *); +void (* R4300i_CoP0[32])(usf_state_t *); +void (* R4300i_CoP0_Function[64])(usf_state_t *); +void (* R4300i_CoP1[32])(usf_state_t *); +void (* R4300i_CoP1_BC[32])(usf_state_t *); +void (* R4300i_CoP1_S[64])(usf_state_t *); +void (* R4300i_CoP1_D[64])(usf_state_t *); +void (* R4300i_CoP1_W[64])(usf_state_t *); +void (* R4300i_CoP1_L[64])(usf_state_t *); + +void R4300i_opcode_SPECIAL (usf_state_t * state) { + ((void (*)()) R4300i_Special[ state->Opcode.funct ])(state); +} + +void R4300i_opcode_REGIMM (usf_state_t * state) { + ((void (*)()) R4300i_Regimm[ state->Opcode.rt ])(state); +} + +void R4300i_opcode_COP0 (usf_state_t * state) { + ((void (*)()) R4300i_CoP0[ state->Opcode.rs ])(state); +} + +void R4300i_opcode_COP0_CO (usf_state_t * state) { + ((void (*)()) R4300i_CoP0_Function[ state->Opcode.funct ])(state); +} + +void R4300i_opcode_COP1 (usf_state_t * state) { + ((void (*)()) R4300i_CoP1[ state->Opcode.fmt ])(state); +} + +void R4300i_opcode_COP1_BC (usf_state_t * state) { + ((void (*)()) R4300i_CoP1_BC[ state->Opcode.ft ])(state); +} + +void R4300i_opcode_COP1_S (usf_state_t * state) { + // controlfp(RoundingModel); + ((void (*)()) R4300i_CoP1_S[ state->Opcode.funct ])(state); +} + +void R4300i_opcode_COP1_D (usf_state_t * state) { + // controlfp(RoundingModel); + ((void (*)()) R4300i_CoP1_D[ state->Opcode.funct ])(state); +} + +void R4300i_opcode_COP1_W (usf_state_t * state) { + ((void (*)()) R4300i_CoP1_W[ state->Opcode.funct ])(state); +} + +void R4300i_opcode_COP1_L (usf_state_t * state) { + ((void (*)()) R4300i_CoP1_L[ state->Opcode.funct ])(state); +} + + +void BuildInterpreter (usf_state_t * state) { + R4300i_Opcode[ 0] = R4300i_opcode_SPECIAL; + R4300i_Opcode[ 1] = R4300i_opcode_REGIMM; + R4300i_Opcode[ 2] = r4300i_J; + R4300i_Opcode[ 3] = r4300i_JAL; + R4300i_Opcode[ 4] = r4300i_BEQ; + R4300i_Opcode[ 5] = r4300i_BNE; + R4300i_Opcode[ 6] = r4300i_BLEZ; + R4300i_Opcode[ 7] = r4300i_BGTZ; + R4300i_Opcode[ 8] = r4300i_ADDI; + R4300i_Opcode[ 9] = r4300i_ADDIU; + R4300i_Opcode[10] = r4300i_SLTI; + R4300i_Opcode[11] = r4300i_SLTIU; + R4300i_Opcode[12] = r4300i_ANDI; + R4300i_Opcode[13] = r4300i_ORI; + R4300i_Opcode[14] = r4300i_XORI; + R4300i_Opcode[15] = r4300i_LUI; + R4300i_Opcode[16] = R4300i_opcode_COP0; + R4300i_Opcode[17] = R4300i_opcode_COP1; + R4300i_Opcode[18] = R4300i_UnknownOpcode; + R4300i_Opcode[19] = R4300i_UnknownOpcode; + R4300i_Opcode[20] = r4300i_BEQL; + R4300i_Opcode[21] = r4300i_BNEL; + R4300i_Opcode[22] = r4300i_BLEZL; + R4300i_Opcode[23] = r4300i_BGTZL; + R4300i_Opcode[24] = R4300i_UnknownOpcode; + R4300i_Opcode[25] = r4300i_DADDIU; + R4300i_Opcode[26] = r4300i_LDL; + R4300i_Opcode[27] = r4300i_LDR; + R4300i_Opcode[28] = R4300i_UnknownOpcode; + R4300i_Opcode[29] = R4300i_UnknownOpcode; + R4300i_Opcode[30] = R4300i_UnknownOpcode; + R4300i_Opcode[31] = R4300i_UnknownOpcode; + R4300i_Opcode[32] = r4300i_LB; + R4300i_Opcode[33] = r4300i_LH; + R4300i_Opcode[34] = r4300i_LWL; + R4300i_Opcode[35] = r4300i_LW; + R4300i_Opcode[36] = r4300i_LBU; + R4300i_Opcode[37] = r4300i_LHU; + R4300i_Opcode[38] = r4300i_LWR; + R4300i_Opcode[39] = r4300i_LWU; + R4300i_Opcode[40] = r4300i_SB; + R4300i_Opcode[41] = r4300i_SH; + R4300i_Opcode[42] = r4300i_SWL; + R4300i_Opcode[43] = r4300i_SW; + R4300i_Opcode[44] = r4300i_SDL; + R4300i_Opcode[45] = r4300i_SDR; + R4300i_Opcode[46] = r4300i_SWR; + R4300i_Opcode[47] = r4300i_CACHE; + R4300i_Opcode[48] = r4300i_LL; + R4300i_Opcode[49] = r4300i_LWC1; + R4300i_Opcode[50] = R4300i_UnknownOpcode; + R4300i_Opcode[51] = R4300i_UnknownOpcode; + R4300i_Opcode[52] = R4300i_UnknownOpcode; + R4300i_Opcode[53] = r4300i_LDC1; + R4300i_Opcode[54] = R4300i_UnknownOpcode; + R4300i_Opcode[55] = r4300i_LD; + R4300i_Opcode[56] = r4300i_SC; + R4300i_Opcode[57] = r4300i_SWC1; + R4300i_Opcode[58] = R4300i_UnknownOpcode; + R4300i_Opcode[59] = R4300i_UnknownOpcode; + R4300i_Opcode[60] = R4300i_UnknownOpcode; + R4300i_Opcode[61] = r4300i_SDC1; + R4300i_Opcode[62] = R4300i_UnknownOpcode; + R4300i_Opcode[63] = r4300i_SD; + + R4300i_Special[ 0] = r4300i_SPECIAL_SLL; + R4300i_Special[ 1] = R4300i_UnknownOpcode; + R4300i_Special[ 2] = r4300i_SPECIAL_SRL; + R4300i_Special[ 3] = r4300i_SPECIAL_SRA; + R4300i_Special[ 4] = r4300i_SPECIAL_SLLV; + R4300i_Special[ 5] = R4300i_UnknownOpcode; + R4300i_Special[ 6] = r4300i_SPECIAL_SRLV; + R4300i_Special[ 7] = r4300i_SPECIAL_SRAV; + R4300i_Special[ 8] = r4300i_SPECIAL_JR; + R4300i_Special[ 9] = r4300i_SPECIAL_JALR; + R4300i_Special[10] = R4300i_UnknownOpcode; + R4300i_Special[11] = R4300i_UnknownOpcode; + R4300i_Special[12] = r4300i_SPECIAL_SYSCALL; + R4300i_Special[13] = r4300i_SPECIAL_BREAK; + R4300i_Special[14] = R4300i_UnknownOpcode; + R4300i_Special[15] = r4300i_SPECIAL_SYNC; + R4300i_Special[16] = r4300i_SPECIAL_MFHI; + R4300i_Special[17] = r4300i_SPECIAL_MTHI; + R4300i_Special[18] = r4300i_SPECIAL_MFLO; + R4300i_Special[19] = r4300i_SPECIAL_MTLO; + R4300i_Special[20] = r4300i_SPECIAL_DSLLV; + R4300i_Special[21] = R4300i_UnknownOpcode; + R4300i_Special[22] = r4300i_SPECIAL_DSRLV; + R4300i_Special[23] = r4300i_SPECIAL_DSRAV; + R4300i_Special[24] = r4300i_SPECIAL_MULT; + R4300i_Special[25] = r4300i_SPECIAL_MULTU; + R4300i_Special[26] = r4300i_SPECIAL_DIV; + R4300i_Special[27] = r4300i_SPECIAL_DIVU; + R4300i_Special[28] = r4300i_SPECIAL_DMULT; + R4300i_Special[29] = r4300i_SPECIAL_DMULTU; + R4300i_Special[30] = r4300i_SPECIAL_DDIV; + R4300i_Special[31] = r4300i_SPECIAL_DDIVU; + R4300i_Special[32] = r4300i_SPECIAL_ADD; + R4300i_Special[33] = r4300i_SPECIAL_ADDU; + R4300i_Special[34] = r4300i_SPECIAL_SUB; + R4300i_Special[35] = r4300i_SPECIAL_SUBU; + R4300i_Special[36] = r4300i_SPECIAL_AND; + R4300i_Special[37] = r4300i_SPECIAL_OR; + R4300i_Special[38] = r4300i_SPECIAL_XOR; + R4300i_Special[39] = r4300i_SPECIAL_NOR; + R4300i_Special[40] = R4300i_UnknownOpcode; + R4300i_Special[41] = R4300i_UnknownOpcode; + R4300i_Special[42] = r4300i_SPECIAL_SLT; + R4300i_Special[43] = r4300i_SPECIAL_SLTU; + R4300i_Special[44] = r4300i_SPECIAL_DADD; + R4300i_Special[45] = r4300i_SPECIAL_DADDU; + R4300i_Special[46] = r4300i_SPECIAL_DSUB; + R4300i_Special[47] = r4300i_SPECIAL_DSUBU; + R4300i_Special[48] = R4300i_UnknownOpcode; + R4300i_Special[49] = R4300i_UnknownOpcode; + R4300i_Special[50] = R4300i_UnknownOpcode; + R4300i_Special[51] = R4300i_UnknownOpcode; + R4300i_Special[52] = r4300i_SPECIAL_TEQ; + R4300i_Special[53] = R4300i_UnknownOpcode; + R4300i_Special[54] = R4300i_UnknownOpcode; + R4300i_Special[55] = R4300i_UnknownOpcode; + R4300i_Special[56] = r4300i_SPECIAL_DSLL; + R4300i_Special[57] = R4300i_UnknownOpcode; + R4300i_Special[58] = r4300i_SPECIAL_DSRL; + R4300i_Special[59] = r4300i_SPECIAL_DSRA; + R4300i_Special[60] = r4300i_SPECIAL_DSLL32; + R4300i_Special[61] = R4300i_UnknownOpcode; + R4300i_Special[62] = r4300i_SPECIAL_DSRL32; + R4300i_Special[63] = r4300i_SPECIAL_DSRA32; + + R4300i_Regimm[ 0] = r4300i_REGIMM_BLTZ; + R4300i_Regimm[ 1] = r4300i_REGIMM_BGEZ; + R4300i_Regimm[ 2] = r4300i_REGIMM_BLTZL; + R4300i_Regimm[ 3] = r4300i_REGIMM_BGEZL; + R4300i_Regimm[ 4] = R4300i_UnknownOpcode; + R4300i_Regimm[ 5] = R4300i_UnknownOpcode; + R4300i_Regimm[ 6] = R4300i_UnknownOpcode; + R4300i_Regimm[ 7] = R4300i_UnknownOpcode; + R4300i_Regimm[ 8] = R4300i_UnknownOpcode; + R4300i_Regimm[ 9] = R4300i_UnknownOpcode; + R4300i_Regimm[10] = R4300i_UnknownOpcode; + R4300i_Regimm[11] = R4300i_UnknownOpcode; + R4300i_Regimm[12] = R4300i_UnknownOpcode; + R4300i_Regimm[13] = R4300i_UnknownOpcode; + R4300i_Regimm[14] = R4300i_UnknownOpcode; + R4300i_Regimm[15] = R4300i_UnknownOpcode; + R4300i_Regimm[16] = r4300i_REGIMM_BLTZAL; + R4300i_Regimm[17] = r4300i_REGIMM_BGEZAL; + R4300i_Regimm[18] = R4300i_UnknownOpcode; + R4300i_Regimm[19] = R4300i_UnknownOpcode; + R4300i_Regimm[20] = R4300i_UnknownOpcode; + R4300i_Regimm[21] = R4300i_UnknownOpcode; + R4300i_Regimm[22] = R4300i_UnknownOpcode; + R4300i_Regimm[23] = R4300i_UnknownOpcode; + R4300i_Regimm[24] = R4300i_UnknownOpcode; + R4300i_Regimm[25] = R4300i_UnknownOpcode; + R4300i_Regimm[26] = R4300i_UnknownOpcode; + R4300i_Regimm[27] = R4300i_UnknownOpcode; + R4300i_Regimm[28] = R4300i_UnknownOpcode; + R4300i_Regimm[29] = R4300i_UnknownOpcode; + R4300i_Regimm[30] = R4300i_UnknownOpcode; + R4300i_Regimm[31] = R4300i_UnknownOpcode; + + R4300i_CoP0[ 0] = r4300i_COP0_MF; + R4300i_CoP0[ 1] = R4300i_UnknownOpcode; + R4300i_CoP0[ 2] = R4300i_UnknownOpcode; + R4300i_CoP0[ 3] = R4300i_UnknownOpcode; + R4300i_CoP0[ 4] = r4300i_COP0_MT; + R4300i_CoP0[ 5] = R4300i_UnknownOpcode; + R4300i_CoP0[ 6] = R4300i_UnknownOpcode; + R4300i_CoP0[ 7] = R4300i_UnknownOpcode; + R4300i_CoP0[ 8] = R4300i_UnknownOpcode; + R4300i_CoP0[ 9] = R4300i_UnknownOpcode; + R4300i_CoP0[10] = R4300i_UnknownOpcode; + R4300i_CoP0[11] = R4300i_UnknownOpcode; + R4300i_CoP0[12] = R4300i_UnknownOpcode; + R4300i_CoP0[13] = R4300i_UnknownOpcode; + R4300i_CoP0[14] = R4300i_UnknownOpcode; + R4300i_CoP0[15] = R4300i_UnknownOpcode; + R4300i_CoP0[16] = R4300i_opcode_COP0_CO; + R4300i_CoP0[17] = R4300i_opcode_COP0_CO; + R4300i_CoP0[18] = R4300i_opcode_COP0_CO; + R4300i_CoP0[19] = R4300i_opcode_COP0_CO; + R4300i_CoP0[20] = R4300i_opcode_COP0_CO; + R4300i_CoP0[21] = R4300i_opcode_COP0_CO; + R4300i_CoP0[22] = R4300i_opcode_COP0_CO; + R4300i_CoP0[23] = R4300i_opcode_COP0_CO; + R4300i_CoP0[24] = R4300i_opcode_COP0_CO; + R4300i_CoP0[25] = R4300i_opcode_COP0_CO; + R4300i_CoP0[26] = R4300i_opcode_COP0_CO; + R4300i_CoP0[27] = R4300i_opcode_COP0_CO; + R4300i_CoP0[28] = R4300i_opcode_COP0_CO; + R4300i_CoP0[29] = R4300i_opcode_COP0_CO; + R4300i_CoP0[30] = R4300i_opcode_COP0_CO; + R4300i_CoP0[31] = R4300i_opcode_COP0_CO; + + R4300i_CoP0_Function[ 0] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[ 1] = r4300i_COP0_CO_TLBR; + R4300i_CoP0_Function[ 2] = r4300i_COP0_CO_TLBWI; + R4300i_CoP0_Function[ 3] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[ 4] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[ 5] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[ 6] = r4300i_COP0_CO_TLBWR; + R4300i_CoP0_Function[ 7] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[ 8] = r4300i_COP0_CO_TLBP; + R4300i_CoP0_Function[ 9] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[10] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[11] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[12] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[13] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[14] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[15] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[16] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[17] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[18] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[19] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[20] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[21] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[22] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[23] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[24] = r4300i_COP0_CO_ERET; + R4300i_CoP0_Function[25] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[26] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[27] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[28] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[29] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[30] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[31] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[32] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[33] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[34] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[35] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[36] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[37] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[38] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[39] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[40] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[41] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[42] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[43] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[44] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[45] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[46] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[47] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[48] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[49] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[50] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[51] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[52] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[53] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[54] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[55] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[56] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[57] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[58] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[59] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[60] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[61] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[62] = R4300i_UnknownOpcode; + R4300i_CoP0_Function[63] = R4300i_UnknownOpcode; + + R4300i_CoP1[ 0] = r4300i_COP1_MF; + R4300i_CoP1[ 1] = r4300i_COP1_DMF; + R4300i_CoP1[ 2] = r4300i_COP1_CF; + R4300i_CoP1[ 3] = R4300i_UnknownOpcode; + R4300i_CoP1[ 4] = r4300i_COP1_MT; + R4300i_CoP1[ 5] = r4300i_COP1_DMT; + R4300i_CoP1[ 6] = r4300i_COP1_CT; + R4300i_CoP1[ 7] = R4300i_UnknownOpcode; + R4300i_CoP1[ 8] = R4300i_opcode_COP1_BC; + R4300i_CoP1[ 9] = R4300i_UnknownOpcode; + R4300i_CoP1[10] = R4300i_UnknownOpcode; + R4300i_CoP1[11] = R4300i_UnknownOpcode; + R4300i_CoP1[12] = R4300i_UnknownOpcode; + R4300i_CoP1[13] = R4300i_UnknownOpcode; + R4300i_CoP1[14] = R4300i_UnknownOpcode; + R4300i_CoP1[15] = R4300i_UnknownOpcode; + R4300i_CoP1[16] = R4300i_opcode_COP1_S; + R4300i_CoP1[17] = R4300i_opcode_COP1_D; + R4300i_CoP1[18] = R4300i_UnknownOpcode; + R4300i_CoP1[19] = R4300i_UnknownOpcode; + R4300i_CoP1[20] = R4300i_opcode_COP1_W; + R4300i_CoP1[21] = R4300i_opcode_COP1_L; + R4300i_CoP1[22] = R4300i_UnknownOpcode; + R4300i_CoP1[23] = R4300i_UnknownOpcode; + R4300i_CoP1[24] = R4300i_UnknownOpcode; + R4300i_CoP1[25] = R4300i_UnknownOpcode; + R4300i_CoP1[26] = R4300i_UnknownOpcode; + R4300i_CoP1[27] = R4300i_UnknownOpcode; + R4300i_CoP1[28] = R4300i_UnknownOpcode; + R4300i_CoP1[29] = R4300i_UnknownOpcode; + R4300i_CoP1[30] = R4300i_UnknownOpcode; + R4300i_CoP1[31] = R4300i_UnknownOpcode; + + R4300i_CoP1_BC[ 0] = r4300i_COP1_BCF; + R4300i_CoP1_BC[ 1] = r4300i_COP1_BCT; + R4300i_CoP1_BC[ 2] = r4300i_COP1_BCFL; + R4300i_CoP1_BC[ 3] = r4300i_COP1_BCTL; + R4300i_CoP1_BC[ 4] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[ 5] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[ 6] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[ 7] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[ 8] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[ 9] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[10] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[11] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[12] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[13] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[14] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[15] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[16] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[17] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[18] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[19] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[20] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[21] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[22] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[23] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[24] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[25] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[26] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[27] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[28] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[29] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[30] = R4300i_UnknownOpcode; + R4300i_CoP1_BC[31] = R4300i_UnknownOpcode; + + R4300i_CoP1_S[ 0] = r4300i_COP1_S_ADD; + R4300i_CoP1_S[ 1] = r4300i_COP1_S_SUB; + R4300i_CoP1_S[ 2] = r4300i_COP1_S_MUL; + R4300i_CoP1_S[ 3] = r4300i_COP1_S_DIV; + R4300i_CoP1_S[ 4] = r4300i_COP1_S_SQRT; + R4300i_CoP1_S[ 5] = r4300i_COP1_S_ABS; + R4300i_CoP1_S[ 6] = r4300i_COP1_S_MOV; + R4300i_CoP1_S[ 7] = r4300i_COP1_S_NEG; + R4300i_CoP1_S[ 8] = R4300i_UnknownOpcode; + R4300i_CoP1_S[ 9] = r4300i_COP1_S_TRUNC_L; + R4300i_CoP1_S[10] = r4300i_COP1_S_CEIL_L; //added by Witten + R4300i_CoP1_S[11] = r4300i_COP1_S_FLOOR_L; //added by Witten + R4300i_CoP1_S[12] = r4300i_COP1_S_ROUND_W; + R4300i_CoP1_S[13] = r4300i_COP1_S_TRUNC_W; + R4300i_CoP1_S[14] = r4300i_COP1_S_CEIL_W; //added by Witten + R4300i_CoP1_S[15] = r4300i_COP1_S_FLOOR_W; + R4300i_CoP1_S[16] = R4300i_UnknownOpcode; + R4300i_CoP1_S[17] = R4300i_UnknownOpcode; + R4300i_CoP1_S[18] = R4300i_UnknownOpcode; + R4300i_CoP1_S[19] = R4300i_UnknownOpcode; + R4300i_CoP1_S[20] = R4300i_UnknownOpcode; + R4300i_CoP1_S[21] = R4300i_UnknownOpcode; + R4300i_CoP1_S[22] = R4300i_UnknownOpcode; + R4300i_CoP1_S[23] = R4300i_UnknownOpcode; + R4300i_CoP1_S[24] = R4300i_UnknownOpcode; + R4300i_CoP1_S[25] = R4300i_UnknownOpcode; + R4300i_CoP1_S[26] = R4300i_UnknownOpcode; + R4300i_CoP1_S[27] = R4300i_UnknownOpcode; + R4300i_CoP1_S[28] = R4300i_UnknownOpcode; + R4300i_CoP1_S[29] = R4300i_UnknownOpcode; + R4300i_CoP1_S[30] = R4300i_UnknownOpcode; + R4300i_CoP1_S[31] = R4300i_UnknownOpcode; + R4300i_CoP1_S[32] = R4300i_UnknownOpcode; + R4300i_CoP1_S[33] = r4300i_COP1_S_CVT_D; + R4300i_CoP1_S[34] = R4300i_UnknownOpcode; + R4300i_CoP1_S[35] = R4300i_UnknownOpcode; + R4300i_CoP1_S[36] = r4300i_COP1_S_CVT_W; + R4300i_CoP1_S[37] = r4300i_COP1_S_CVT_L; + R4300i_CoP1_S[38] = R4300i_UnknownOpcode; + R4300i_CoP1_S[39] = R4300i_UnknownOpcode; + R4300i_CoP1_S[40] = R4300i_UnknownOpcode; + R4300i_CoP1_S[41] = R4300i_UnknownOpcode; + R4300i_CoP1_S[42] = R4300i_UnknownOpcode; + R4300i_CoP1_S[43] = R4300i_UnknownOpcode; + R4300i_CoP1_S[44] = R4300i_UnknownOpcode; + R4300i_CoP1_S[45] = R4300i_UnknownOpcode; + R4300i_CoP1_S[46] = R4300i_UnknownOpcode; + R4300i_CoP1_S[47] = R4300i_UnknownOpcode; + R4300i_CoP1_S[48] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[49] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[50] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[51] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[52] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[53] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[54] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[55] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[56] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[57] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[58] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[59] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[60] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[61] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[62] = r4300i_COP1_S_CMP; + R4300i_CoP1_S[63] = r4300i_COP1_S_CMP; + + R4300i_CoP1_D[ 0] = r4300i_COP1_D_ADD; + R4300i_CoP1_D[ 1] = r4300i_COP1_D_SUB; + R4300i_CoP1_D[ 2] = r4300i_COP1_D_MUL; + R4300i_CoP1_D[ 3] = r4300i_COP1_D_DIV; + R4300i_CoP1_D[ 4] = r4300i_COP1_D_SQRT; + R4300i_CoP1_D[ 5] = r4300i_COP1_D_ABS; + R4300i_CoP1_D[ 6] = r4300i_COP1_D_MOV; + R4300i_CoP1_D[ 7] = r4300i_COP1_D_NEG; + R4300i_CoP1_D[ 8] = R4300i_UnknownOpcode; + R4300i_CoP1_D[ 9] = r4300i_COP1_D_TRUNC_L; //added by Witten + R4300i_CoP1_D[10] = r4300i_COP1_D_CEIL_L; //added by Witten + R4300i_CoP1_D[11] = r4300i_COP1_D_FLOOR_L; //added by Witten + R4300i_CoP1_D[12] = r4300i_COP1_D_ROUND_W; + R4300i_CoP1_D[13] = r4300i_COP1_D_TRUNC_W; + R4300i_CoP1_D[14] = r4300i_COP1_D_CEIL_W; //added by Witten + R4300i_CoP1_D[15] = r4300i_COP1_D_FLOOR_W; //added by Witten + R4300i_CoP1_D[16] = R4300i_UnknownOpcode; + R4300i_CoP1_D[17] = R4300i_UnknownOpcode; + R4300i_CoP1_D[18] = R4300i_UnknownOpcode; + R4300i_CoP1_D[19] = R4300i_UnknownOpcode; + R4300i_CoP1_D[20] = R4300i_UnknownOpcode; + R4300i_CoP1_D[21] = R4300i_UnknownOpcode; + R4300i_CoP1_D[22] = R4300i_UnknownOpcode; + R4300i_CoP1_D[23] = R4300i_UnknownOpcode; + R4300i_CoP1_D[24] = R4300i_UnknownOpcode; + R4300i_CoP1_D[25] = R4300i_UnknownOpcode; + R4300i_CoP1_D[26] = R4300i_UnknownOpcode; + R4300i_CoP1_D[27] = R4300i_UnknownOpcode; + R4300i_CoP1_D[28] = R4300i_UnknownOpcode; + R4300i_CoP1_D[29] = R4300i_UnknownOpcode; + R4300i_CoP1_D[30] = R4300i_UnknownOpcode; + R4300i_CoP1_D[31] = R4300i_UnknownOpcode; + R4300i_CoP1_D[32] = r4300i_COP1_D_CVT_S; + R4300i_CoP1_D[33] = R4300i_UnknownOpcode; + R4300i_CoP1_D[34] = R4300i_UnknownOpcode; + R4300i_CoP1_D[35] = R4300i_UnknownOpcode; + R4300i_CoP1_D[36] = r4300i_COP1_D_CVT_W; + R4300i_CoP1_D[37] = r4300i_COP1_D_CVT_L; + R4300i_CoP1_D[38] = R4300i_UnknownOpcode; + R4300i_CoP1_D[39] = R4300i_UnknownOpcode; + R4300i_CoP1_D[40] = R4300i_UnknownOpcode; + R4300i_CoP1_D[41] = R4300i_UnknownOpcode; + R4300i_CoP1_D[42] = R4300i_UnknownOpcode; + R4300i_CoP1_D[43] = R4300i_UnknownOpcode; + R4300i_CoP1_D[44] = R4300i_UnknownOpcode; + R4300i_CoP1_D[45] = R4300i_UnknownOpcode; + R4300i_CoP1_D[46] = R4300i_UnknownOpcode; + R4300i_CoP1_D[47] = R4300i_UnknownOpcode; + R4300i_CoP1_D[48] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[49] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[50] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[51] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[52] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[53] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[54] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[55] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[56] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[57] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[58] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[59] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[60] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[61] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[62] = r4300i_COP1_D_CMP; + R4300i_CoP1_D[63] = r4300i_COP1_D_CMP; + + R4300i_CoP1_W[ 0] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 1] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 2] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 3] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 4] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 5] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 6] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 7] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 8] = R4300i_UnknownOpcode; + R4300i_CoP1_W[ 9] = R4300i_UnknownOpcode; + R4300i_CoP1_W[10] = R4300i_UnknownOpcode; + R4300i_CoP1_W[11] = R4300i_UnknownOpcode; + R4300i_CoP1_W[12] = R4300i_UnknownOpcode; + R4300i_CoP1_W[13] = R4300i_UnknownOpcode; + R4300i_CoP1_W[14] = R4300i_UnknownOpcode; + R4300i_CoP1_W[15] = R4300i_UnknownOpcode; + R4300i_CoP1_W[16] = R4300i_UnknownOpcode; + R4300i_CoP1_W[17] = R4300i_UnknownOpcode; + R4300i_CoP1_W[18] = R4300i_UnknownOpcode; + R4300i_CoP1_W[19] = R4300i_UnknownOpcode; + R4300i_CoP1_W[20] = R4300i_UnknownOpcode; + R4300i_CoP1_W[21] = R4300i_UnknownOpcode; + R4300i_CoP1_W[22] = R4300i_UnknownOpcode; + R4300i_CoP1_W[23] = R4300i_UnknownOpcode; + R4300i_CoP1_W[24] = R4300i_UnknownOpcode; + R4300i_CoP1_W[25] = R4300i_UnknownOpcode; + R4300i_CoP1_W[26] = R4300i_UnknownOpcode; + R4300i_CoP1_W[27] = R4300i_UnknownOpcode; + R4300i_CoP1_W[28] = R4300i_UnknownOpcode; + R4300i_CoP1_W[29] = R4300i_UnknownOpcode; + R4300i_CoP1_W[30] = R4300i_UnknownOpcode; + R4300i_CoP1_W[31] = R4300i_UnknownOpcode; + R4300i_CoP1_W[32] = r4300i_COP1_W_CVT_S; + R4300i_CoP1_W[33] = r4300i_COP1_W_CVT_D; + R4300i_CoP1_W[34] = R4300i_UnknownOpcode; + R4300i_CoP1_W[35] = R4300i_UnknownOpcode; + R4300i_CoP1_W[36] = R4300i_UnknownOpcode; + R4300i_CoP1_W[37] = R4300i_UnknownOpcode; + R4300i_CoP1_W[38] = R4300i_UnknownOpcode; + R4300i_CoP1_W[39] = R4300i_UnknownOpcode; + R4300i_CoP1_W[40] = R4300i_UnknownOpcode; + R4300i_CoP1_W[41] = R4300i_UnknownOpcode; + R4300i_CoP1_W[42] = R4300i_UnknownOpcode; + R4300i_CoP1_W[43] = R4300i_UnknownOpcode; + R4300i_CoP1_W[44] = R4300i_UnknownOpcode; + R4300i_CoP1_W[45] = R4300i_UnknownOpcode; + R4300i_CoP1_W[46] = R4300i_UnknownOpcode; + R4300i_CoP1_W[47] = R4300i_UnknownOpcode; + R4300i_CoP1_W[48] = R4300i_UnknownOpcode; + R4300i_CoP1_W[49] = R4300i_UnknownOpcode; + R4300i_CoP1_W[50] = R4300i_UnknownOpcode; + R4300i_CoP1_W[51] = R4300i_UnknownOpcode; + R4300i_CoP1_W[52] = R4300i_UnknownOpcode; + R4300i_CoP1_W[53] = R4300i_UnknownOpcode; + R4300i_CoP1_W[54] = R4300i_UnknownOpcode; + R4300i_CoP1_W[55] = R4300i_UnknownOpcode; + R4300i_CoP1_W[56] = R4300i_UnknownOpcode; + R4300i_CoP1_W[57] = R4300i_UnknownOpcode; + R4300i_CoP1_W[58] = R4300i_UnknownOpcode; + R4300i_CoP1_W[59] = R4300i_UnknownOpcode; + R4300i_CoP1_W[60] = R4300i_UnknownOpcode; + R4300i_CoP1_W[61] = R4300i_UnknownOpcode; + R4300i_CoP1_W[62] = R4300i_UnknownOpcode; + R4300i_CoP1_W[63] = R4300i_UnknownOpcode; + + R4300i_CoP1_L[ 0] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 1] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 2] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 3] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 4] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 5] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 6] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 7] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 8] = R4300i_UnknownOpcode; + R4300i_CoP1_L[ 9] = R4300i_UnknownOpcode; + R4300i_CoP1_L[10] = R4300i_UnknownOpcode; + R4300i_CoP1_L[11] = R4300i_UnknownOpcode; + R4300i_CoP1_L[12] = R4300i_UnknownOpcode; + R4300i_CoP1_L[13] = R4300i_UnknownOpcode; + R4300i_CoP1_L[14] = R4300i_UnknownOpcode; + R4300i_CoP1_L[15] = R4300i_UnknownOpcode; + R4300i_CoP1_L[16] = R4300i_UnknownOpcode; + R4300i_CoP1_L[17] = R4300i_UnknownOpcode; + R4300i_CoP1_L[18] = R4300i_UnknownOpcode; + R4300i_CoP1_L[19] = R4300i_UnknownOpcode; + R4300i_CoP1_L[20] = R4300i_UnknownOpcode; + R4300i_CoP1_L[21] = R4300i_UnknownOpcode; + R4300i_CoP1_L[22] = R4300i_UnknownOpcode; + R4300i_CoP1_L[23] = R4300i_UnknownOpcode; + R4300i_CoP1_L[24] = R4300i_UnknownOpcode; + R4300i_CoP1_L[25] = R4300i_UnknownOpcode; + R4300i_CoP1_L[26] = R4300i_UnknownOpcode; + R4300i_CoP1_L[27] = R4300i_UnknownOpcode; + R4300i_CoP1_L[28] = R4300i_UnknownOpcode; + R4300i_CoP1_L[29] = R4300i_UnknownOpcode; + R4300i_CoP1_L[30] = R4300i_UnknownOpcode; + R4300i_CoP1_L[31] = R4300i_UnknownOpcode; + R4300i_CoP1_L[32] = r4300i_COP1_L_CVT_S; + R4300i_CoP1_L[33] = r4300i_COP1_L_CVT_D; + R4300i_CoP1_L[34] = R4300i_UnknownOpcode; + R4300i_CoP1_L[35] = R4300i_UnknownOpcode; + R4300i_CoP1_L[36] = R4300i_UnknownOpcode; + R4300i_CoP1_L[37] = R4300i_UnknownOpcode; + R4300i_CoP1_L[38] = R4300i_UnknownOpcode; + R4300i_CoP1_L[39] = R4300i_UnknownOpcode; + R4300i_CoP1_L[40] = R4300i_UnknownOpcode; + R4300i_CoP1_L[41] = R4300i_UnknownOpcode; + R4300i_CoP1_L[42] = R4300i_UnknownOpcode; + R4300i_CoP1_L[43] = R4300i_UnknownOpcode; + R4300i_CoP1_L[44] = R4300i_UnknownOpcode; + R4300i_CoP1_L[45] = R4300i_UnknownOpcode; + R4300i_CoP1_L[46] = R4300i_UnknownOpcode; + R4300i_CoP1_L[47] = R4300i_UnknownOpcode; + R4300i_CoP1_L[48] = R4300i_UnknownOpcode; + R4300i_CoP1_L[49] = R4300i_UnknownOpcode; + R4300i_CoP1_L[50] = R4300i_UnknownOpcode; + R4300i_CoP1_L[51] = R4300i_UnknownOpcode; + R4300i_CoP1_L[52] = R4300i_UnknownOpcode; + R4300i_CoP1_L[53] = R4300i_UnknownOpcode; + R4300i_CoP1_L[54] = R4300i_UnknownOpcode; + R4300i_CoP1_L[55] = R4300i_UnknownOpcode; + R4300i_CoP1_L[56] = R4300i_UnknownOpcode; + R4300i_CoP1_L[57] = R4300i_UnknownOpcode; + R4300i_CoP1_L[58] = R4300i_UnknownOpcode; + R4300i_CoP1_L[59] = R4300i_UnknownOpcode; + R4300i_CoP1_L[60] = R4300i_UnknownOpcode; + R4300i_CoP1_L[61] = R4300i_UnknownOpcode; + R4300i_CoP1_L[62] = R4300i_UnknownOpcode; + R4300i_CoP1_L[63] = R4300i_UnknownOpcode; +} + + +void ExecuteInterpreterOpCode (usf_state_t * state) { + + + if (*state->WaitMode) state->Timers->Timer = -1; + + if (!r4300i_LW_VAddr(state, state->PROGRAM_COUNTER, &state->Opcode.Hex)) { + DoTLBMiss(state, state->NextInstruction == JUMP,state->PROGRAM_COUNTER); + state->NextInstruction = NORMAL; + return; + } + + COUNT_REGISTER += 2; + state->Timers->Timer -= 2; + + RANDOM_REGISTER -= 1; + if ((int32_t)RANDOM_REGISTER < (int32_t)WIRED_REGISTER) { + RANDOM_REGISTER = 31; + } + + R4300i_Opcode[ state->Opcode.op ](state); + + if (state->GPR[0].DW != 0) { + state->GPR[0].DW = 0; + } + + switch (state->NextInstruction) { + case NORMAL: + state->PROGRAM_COUNTER += 4; + break; + case DELAY_SLOT: + state->NextInstruction = JUMP; + state->PROGRAM_COUNTER += 4; + break; + case JUMP: + state->PROGRAM_COUNTER = state->JumpToLocation; + state->NextInstruction = NORMAL; + if ((int32_t)state->Timers->Timer < 0) { TimerDone(state); } + if (state->CPU_Action->DoSomething) { DoSomething(state); } + + } +} + +void StartInterpreterCPU (usf_state_t * state) { + state->NextInstruction = NORMAL; + + while(state->cpu_running) { + ExecuteInterpreterOpCode(state); + } + + state->cpu_stopped = 1; + +} + +void TestInterpreterJump (usf_state_t * state, uint32_t PC, uint32_t TargetPC, int32_t Reg1, int32_t Reg2) { + if (PC != TargetPC) { return; } + if (DelaySlotEffectsCompare(state,PC,Reg1,Reg2)) { return; } + InPermLoop(state); +} diff --git a/Frameworks/lazyusf/lazyusf/interpreter_cpu.h b/Frameworks/lazyusf/lazyusf/interpreter_cpu.h new file mode 100644 index 000000000..70d9301bb --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/interpreter_cpu.h @@ -0,0 +1,37 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#include + +void BuildInterpreter ( usf_state_t * ); +void ExecuteInterpreterOpCode ( usf_state_t * ); +void StartInterpreterCPU ( usf_state_t * ); +void TestInterpreterJump ( usf_state_t *, uint32_t PC, uint32_t TargetPC, int32_t Reg1, int32_t Reg2 ); + + + + + +extern void (* R4300i_Opcode[64])(usf_state_t *); diff --git a/Frameworks/lazyusf/lazyusf/interpreter_ops.c b/Frameworks/lazyusf/lazyusf/interpreter_ops.c new file mode 100644 index 000000000..2c76ee1f7 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/interpreter_ops.c @@ -0,0 +1,1335 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include +#include "main.h" +#include "cpu.h" +#include "usf.h" + +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE __attribute__((forceinline)) +#endif + +#include "usf_internal.h" + +#define ADDRESS_ERROR_EXCEPTION(Address,FromRead) \ + DoAddressError(state,state->NextInstruction == JUMP,Address,FromRead);\ + state->NextInstruction = JUMP;\ + state->JumpToLocation = state->PROGRAM_COUNTER;\ + return; + +//#define TEST_COP1_USABLE_EXCEPTION +#define TEST_COP1_USABLE_EXCEPTION \ + if ((STATUS_REGISTER & STATUS_CU1) == 0) {\ + DoCopUnusableException(state,state->NextInstruction == JUMP,1);\ + state->NextInstruction = JUMP;\ + state->JumpToLocation = state->PROGRAM_COUNTER;\ + return;\ + } + +#define TLB_READ_EXCEPTION(Address) \ + DoTLBMiss(state,state->NextInstruction == JUMP,Address);\ + state->NextInstruction = JUMP;\ + state->JumpToLocation = state->PROGRAM_COUNTER;\ + return; + +/************************* OpCode functions *************************/ +void r4300i_J (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = (state->PROGRAM_COUNTER & 0xF0000000) + (state->Opcode.target << 2); + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,0,0); +} + +void r4300i_JAL (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = (state->PROGRAM_COUNTER & 0xF0000000) + (state->Opcode.target << 2); + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,0,0); + state->GPR[31].DW= (int32_t)(state->PROGRAM_COUNTER + 8); +} + +void r4300i_BEQ (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW == state->GPR[state->Opcode.rt].DW) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,state->Opcode.rt); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_BNE (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW != state->GPR[state->Opcode.rt].DW) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,state->Opcode.rt); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_BLEZ (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW <= 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_BGTZ (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW > 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_ADDI (usf_state_t * state) { + if (state->Opcode.rt == 0) { return; } + state->GPR[state->Opcode.rt].DW = (state->GPR[state->Opcode.rs].W[0] + ((int16_t)state->Opcode.immediate)); +} + +void r4300i_ADDIU (usf_state_t * state) { + state->GPR[state->Opcode.rt].DW = (state->GPR[state->Opcode.rs].W[0] + ((int16_t)state->Opcode.immediate)); +} + +void r4300i_SLTI (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW < (int64_t)((int16_t)state->Opcode.immediate)) { + state->GPR[state->Opcode.rt].DW = 1; + } else { + state->GPR[state->Opcode.rt].DW = 0; + } +} + +void r4300i_SLTIU (usf_state_t * state) { + int32_t imm32 = (int16_t)state->Opcode.immediate; + int64_t imm64; + + imm64 = imm32; + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rs].UDW < (uint64_t)imm64?1:0; +} + +void r4300i_ANDI (usf_state_t * state) { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rs].DW & state->Opcode.immediate; +} + +void r4300i_ORI (usf_state_t * state) { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rs].DW | state->Opcode.immediate; +} + +void r4300i_XORI (usf_state_t * state) { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rs].DW ^ state->Opcode.immediate; +} + +void r4300i_LUI (usf_state_t * state) { + if (state->Opcode.rt == 0) { return; } + state->GPR[state->Opcode.rt].DW = (int32_t)((int16_t)state->Opcode.offset << 16); +} + +void r4300i_BEQL (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW == state->GPR[state->Opcode.rt].DW) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,state->Opcode.rt); + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_BNEL (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW != state->GPR[state->Opcode.rt].DW) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,state->Opcode.rt); + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_BLEZL (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW <= 0) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_BGTZL (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW > 0) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_DADDIU (usf_state_t * state) { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rs].DW + (int64_t)((int16_t)state->Opcode.immediate); +} + +uint64_t LDL_MASK[8] = { 0ULL,0xFFULL,0xFFFFULL,0xFFFFFFULL,0xFFFFFFFFULL,0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL }; +int32_t LDL_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void r4300i_LDL (usf_state_t * state) { + uint32_t Offset, Address; + uint64_t Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 7; + + if (!r4300i_LD_VAddr(state,(Address & ~7),&Value)) { + return; + } + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rt].DW & LDL_MASK[Offset]; + state->GPR[state->Opcode.rt].DW += Value << LDL_SHIFT[Offset]; +} + +uint64_t LDR_MASK[8] = { 0xFFFFFFFFFFFFFF00ULL, 0xFFFFFFFFFFFF0000ULL, + 0xFFFFFFFFFF000000ULL, 0xFFFFFFFF00000000ULL, + 0xFFFFFF0000000000ULL, 0xFFFF000000000000ULL, + 0xFF00000000000000ULL, 0 }; +int32_t LDR_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; + +void r4300i_LDR (usf_state_t * state) { + uint32_t Offset, Address; + uint64_t Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 7; + + if (!r4300i_LD_VAddr(state,(Address & ~7),&Value)) { + return; + } + + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rt].DW & LDR_MASK[Offset]; + state->GPR[state->Opcode.rt].DW += Value >> LDR_SHIFT[Offset]; + +} + +void r4300i_LB (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if (state->Opcode.rt == 0) { return; } + if (!r4300i_LB_VAddr(state,Address,&state->GPR[state->Opcode.rt].UB[0])) { + TLB_READ_EXCEPTION(Address); + } else { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rt].B[0]; + } +} + +void r4300i_LH (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + if (!r4300i_LH_VAddr(state,Address,&state->GPR[state->Opcode.rt].UHW[0])) { + //if (ShowTLBMisses) { + DisplayError("LH TLB: %X",Address); + //} + TLB_READ_EXCEPTION(Address); + } else { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rt].HW[0]; + } +} + +uint32_t LWL_MASK[4] = { 0,0xFF,0xFFFF,0xFFFFFF }; +int32_t LWL_SHIFT[4] = { 0, 8, 16, 24}; + +void r4300i_LWL (usf_state_t * state) { + uint32_t Offset, Address, Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 3; + + if (!r4300i_LW_VAddr(state,(Address & ~3),&Value)) { + return; + } + + state->GPR[state->Opcode.rt].DW = (int32_t)(state->GPR[state->Opcode.rt].W[0] & LWL_MASK[Offset]); + state->GPR[state->Opcode.rt].DW += (int32_t)(Value << LWL_SHIFT[Offset]); +} + +void r4300i_LW (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + + +// if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + + if (state->Opcode.rt == 0) { return; } + + + if (!r4300i_LW_VAddr(state,Address,&state->GPR[state->Opcode.rt].UW[0])) { + //if (ShowTLBMisses) { + //printf("LW TLB: %X",Address); + //} + TLB_READ_EXCEPTION(Address); + } else { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rt].W[0]; + } +} + +void r4300i_LBU (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if (!r4300i_LB_VAddr(state,Address,&state->GPR[state->Opcode.rt].UB[0])) { + //if (ShowTLBMisses) { + DisplayError("LBU TLB: %X",Address); + //} + TLB_READ_EXCEPTION(Address); + } else { + state->GPR[state->Opcode.rt].UDW = state->GPR[state->Opcode.rt].UB[0]; + } +} + +void r4300i_LHU (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + if (!r4300i_LH_VAddr(state,Address,&state->GPR[state->Opcode.rt].UHW[0])) { + //if (ShowTLBMisses) { + DisplayError("LHU TLB: %X",Address); + //} + TLB_READ_EXCEPTION(Address); + } else { + state->GPR[state->Opcode.rt].UDW = state->GPR[state->Opcode.rt].UHW[0]; + } +} + +uint32_t LWR_MASK[4] = { 0xFFFFFF00, 0xFFFF0000, 0xFF000000, 0 }; +int32_t LWR_SHIFT[4] = { 24, 16 ,8, 0 }; + +void r4300i_LWR (usf_state_t * state) { + uint32_t Offset, Address, Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 3; + + if (!r4300i_LW_VAddr(state,(Address & ~3),&Value)) { + return; + } + + state->GPR[state->Opcode.rt].DW = (int32_t)(state->GPR[state->Opcode.rt].W[0] & LWR_MASK[Offset]); + state->GPR[state->Opcode.rt].DW += (int32_t)(Value >> LWR_SHIFT[Offset]); +} + +void r4300i_LWU (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + if (state->Opcode.rt == 0) { return; } + + if (!r4300i_LW_VAddr(state,Address,&state->GPR[state->Opcode.rt].UW[0])) { + //if (ShowTLBMisses) { + DisplayError("LWU TLB: %X",Address); + //} + TLB_READ_EXCEPTION(Address); + } else { + state->GPR[state->Opcode.rt].UDW = state->GPR[state->Opcode.rt].UW[0]; + } +} + +void r4300i_SB (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if (!r4300i_SB_VAddr(state,Address,state->GPR[state->Opcode.rt].UB[0])) { + } +} + +void r4300i_SH (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); } + if (!r4300i_SH_VAddr(state,Address,state->GPR[state->Opcode.rt].UHW[0])) { + } +} + +uint32_t SWL_MASK[4] = { 0,0xFF000000,0xFFFF0000,0xFFFFFF00 }; +int32_t SWL_SHIFT[4] = { 0, 8, 16, 24 }; + +void r4300i_SWL (usf_state_t * state) { + uint32_t Offset, Address, Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 3; + + if (!r4300i_LW_VAddr(state,(Address & ~3),&Value)) { + return; + } + + Value &= SWL_MASK[Offset]; + Value += state->GPR[state->Opcode.rt].UW[0] >> SWL_SHIFT[Offset]; + + if (!r4300i_SW_VAddr(state,(Address & ~0x03),Value)) { + } +} + + +void r4300i_SW (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); } + if (!r4300i_SW_VAddr(state,Address,state->GPR[state->Opcode.rt].UW[0])) { + } + //TranslateVaddr(&Address); + //if (Address == 0x00090AA0) { + // LogMessage("%X: Write %X to %X",state->PROGRAM_COUNTER,state->GPR[state->Opcode.rt].UW[0],state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset); + //} +} + +uint64_t SDL_MASK[8] = { 0,0xFF00000000000000ULL, + 0xFFFF000000000000ULL, + 0xFFFFFF0000000000ULL, + 0xFFFFFFFF00000000ULL, + 0xFFFFFFFFFF000000ULL, + 0xFFFFFFFFFFFF0000ULL, + 0xFFFFFFFFFFFFFF00ULL + }; +int32_t SDL_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; + +void r4300i_SDL (usf_state_t * state) { + uint32_t Offset, Address; + uint64_t Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 7; + + if (!r4300i_LD_VAddr(state,(Address & ~7),&Value)) { + return; + } + + Value &= SDL_MASK[Offset]; + Value += state->GPR[state->Opcode.rt].UDW >> SDL_SHIFT[Offset]; + + if (!r4300i_SD_VAddr(state,(Address & ~7),Value)) { + } +} + +uint64_t SDR_MASK[8] = { 0x00FFFFFFFFFFFFFFULL, + 0x0000FFFFFFFFFFFFULL, + 0x000000FFFFFFFFFFULL, + 0x00000000FFFFFFFFULL, + 0x0000000000FFFFFFULL, + 0x000000000000FFFFULL, + 0x00000000000000FFULL, + 0x0000000000000000ULL + }; +int32_t SDR_SHIFT[8] = { 56,48,40,32,24,16,8,0 }; + +void r4300i_SDR (usf_state_t * state) { + uint32_t Offset, Address; + uint64_t Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 7; + + if (!r4300i_LD_VAddr(state,(Address & ~7),&Value)) { + return; + } + + Value &= SDR_MASK[Offset]; + Value += state->GPR[state->Opcode.rt].UDW << SDR_SHIFT[Offset]; + + if (!r4300i_SD_VAddr(state,(Address & ~7),Value)) { + } +} + +uint32_t SWR_MASK[4] = { 0x00FFFFFF,0x0000FFFF,0x000000FF,0x00000000 }; +int32_t SWR_SHIFT[4] = { 24, 16 , 8, 0 }; + +void r4300i_SWR (usf_state_t * state) { + uint32_t Offset, Address, Value; + + Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + Offset = Address & 3; + + if (!r4300i_LW_VAddr(state,(Address & ~3),&Value)) { + return; + } + + Value &= SWR_MASK[Offset]; + Value += state->GPR[state->Opcode.rt].UW[0] << SWR_SHIFT[Offset]; + + if (!r4300i_SW_VAddr(state,(Address & ~0x03),Value)) { + } +} + +void r4300i_CACHE (usf_state_t * state) { +} + +void r4300i_LL (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + uintptr_t ll = 0; + if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + + if (state->Opcode.rt == 0) { return; } + + if (!r4300i_LW_VAddr(state,Address,&state->GPR[state->Opcode.rt].UW[0])) { + //if (ShowTLBMisses) { + DisplayError("LW TLB: %X",Address); + //} + TLB_READ_EXCEPTION(Address); + } else { + state->GPR[state->Opcode.rt].DW = state->GPR[state->Opcode.rt].W[0]; + } + state->LLBit = 1; + state->LLAddr = Address; + ll = state->LLAddr; + TranslateVaddr(state, &ll); + state->LLAddr = ll; + +} + +void r4300i_LWC1 (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (uint32_t)((int16_t)state->Opcode.offset); + TEST_COP1_USABLE_EXCEPTION + if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + if (!r4300i_LW_VAddr(state,Address,&*(uint32_t *)state->FPRFloatLocation[state->Opcode.ft])) { + //if (ShowTLBMisses) { + DisplayError("LWC1 TLB: %X",Address); + //} + TLB_READ_EXCEPTION(Address); + } +} + +void r4300i_SC (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); } + if (state->LLBit == 1) { + if (!r4300i_SW_VAddr(state,Address,state->GPR[state->Opcode.rt].UW[0])) { + DisplayError("SW TLB: %X",Address); + } + } + state->GPR[state->Opcode.rt].UW[0] = state->LLBit; +} + +void r4300i_LD (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + if (!r4300i_LD_VAddr(state,Address,&state->GPR[state->Opcode.rt].UDW)) { + } +} + + +void r4300i_LDC1 (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + + TEST_COP1_USABLE_EXCEPTION + if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } + if (!r4300i_LD_VAddr(state,Address,&*(uint64_t *)state->FPRDoubleLocation[state->Opcode.ft])) { + } +} + +void r4300i_SWC1 (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + TEST_COP1_USABLE_EXCEPTION + if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); } + + if (!r4300i_SW_VAddr(state,Address,*(uint32_t *)state->FPRFloatLocation[state->Opcode.ft])) { + } +} + +void r4300i_SDC1 (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + + TEST_COP1_USABLE_EXCEPTION + if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); } + if (!r4300i_SD_VAddr(state,Address,*(int64_t *)state->FPRDoubleLocation[state->Opcode.ft])) { + } +} + +void r4300i_SD (usf_state_t * state) { + uint32_t Address = state->GPR[state->Opcode.base].UW[0] + (int16_t)state->Opcode.offset; + if ((Address & 7) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); } + if (!r4300i_SD_VAddr(state,Address,state->GPR[state->Opcode.rt].UDW)) { + } +} +/********************** R4300i state->Opcodes: Special **********************/ +void r4300i_SPECIAL_SLL (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].W[0] << state->Opcode.sa); +} + +void r4300i_SPECIAL_SRL (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (int32_t)(state->GPR[state->Opcode.rt].UW[0] >> state->Opcode.sa); +} + +void r4300i_SPECIAL_SRA (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].W[0] >> state->Opcode.sa); +} + +void r4300i_SPECIAL_SLLV (usf_state_t * state) { + if (state->Opcode.rd == 0) { return; } + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].W[0] << (state->GPR[state->Opcode.rs].UW[0] & 0x1F)); +} + +void r4300i_SPECIAL_SRLV (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (int32_t)(state->GPR[state->Opcode.rt].UW[0] >> (state->GPR[state->Opcode.rs].UW[0] & 0x1F)); +} + +void r4300i_SPECIAL_SRAV (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].W[0] >> (state->GPR[state->Opcode.rs].UW[0] & 0x1F)); +} + +void r4300i_SPECIAL_JR (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->GPR[state->Opcode.rs].UW[0]; +} + +void r4300i_SPECIAL_JALR (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->GPR[state->Opcode.rs].UW[0]; + state->GPR[state->Opcode.rd].DW = (int32_t)(state->PROGRAM_COUNTER + 8); +} + +void r4300i_SPECIAL_SYSCALL (usf_state_t * state) { + DoSysCallException(state, state->NextInstruction == JUMP); + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER; +} + +void r4300i_SPECIAL_BREAK (usf_state_t * state) { + *state->WaitMode=1; +} + +void r4300i_SPECIAL_SYNC (usf_state_t * state) { +} + +void r4300i_SPECIAL_MFHI (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->HI.DW; +} + +void r4300i_SPECIAL_MTHI (usf_state_t * state) { + state->HI.DW = state->GPR[state->Opcode.rs].DW; +} + +void r4300i_SPECIAL_MFLO (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->LO.DW; +} + +void r4300i_SPECIAL_MTLO (usf_state_t * state) { + state->LO.DW = state->GPR[state->Opcode.rs].DW; +} + +void r4300i_SPECIAL_DSLLV (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rt].DW << (state->GPR[state->Opcode.rs].UW[0] & 0x3F); +} + +void r4300i_SPECIAL_DSRLV (usf_state_t * state) { + state->GPR[state->Opcode.rd].UDW = state->GPR[state->Opcode.rt].UDW >> (state->GPR[state->Opcode.rs].UW[0] & 0x3F); +} + +void r4300i_SPECIAL_DSRAV (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rt].DW >> (state->GPR[state->Opcode.rs].UW[0] & 0x3F); +} + +void r4300i_SPECIAL_MULT (usf_state_t * state) { + state->HI.DW = (int64_t)(state->GPR[state->Opcode.rs].W[0]) * (int64_t)(state->GPR[state->Opcode.rt].W[0]); + state->LO.DW = state->HI.W[0]; + state->HI.DW = state->HI.W[1]; +} + +void r4300i_SPECIAL_MULTU (usf_state_t * state) { + state->HI.DW = (uint64_t)(state->GPR[state->Opcode.rs].UW[0]) * (uint64_t)(state->GPR[state->Opcode.rt].UW[0]); + state->LO.DW = state->HI.W[0]; + state->HI.DW = state->HI.W[1]; +} + +void r4300i_SPECIAL_DIV (usf_state_t * state) { + if ( state->GPR[state->Opcode.rt].UDW != 0 ) { + state->LO.DW = state->GPR[state->Opcode.rs].W[0] / state->GPR[state->Opcode.rt].W[0]; + state->HI.DW = state->GPR[state->Opcode.rs].W[0] % state->GPR[state->Opcode.rt].W[0]; + } else { + } +} + +void r4300i_SPECIAL_DIVU (usf_state_t * state) { + if ( state->GPR[state->Opcode.rt].UDW != 0 ) { + state->LO.DW = (int32_t)(state->GPR[state->Opcode.rs].UW[0] / state->GPR[state->Opcode.rt].UW[0]); + state->HI.DW = (int32_t)(state->GPR[state->Opcode.rs].UW[0] % state->GPR[state->Opcode.rt].UW[0]); + } else { + } +} + +void r4300i_SPECIAL_DMULT (usf_state_t * state) { + MIPS_DWORD Tmp[3]; + + state->LO.UDW = (uint64_t)state->GPR[state->Opcode.rs].UW[0] * (uint64_t)state->GPR[state->Opcode.rt].UW[0]; + Tmp[0].UDW = (int64_t)state->GPR[state->Opcode.rs].W[1] * (int64_t)(uint64_t)state->GPR[state->Opcode.rt].UW[0]; + Tmp[1].UDW = (int64_t)(uint64_t)state->GPR[state->Opcode.rs].UW[0] * (int64_t)state->GPR[state->Opcode.rt].W[1]; + state->HI.UDW = (int64_t)state->GPR[state->Opcode.rs].W[1] * (int64_t)state->GPR[state->Opcode.rt].W[1]; + + Tmp[2].UDW = (uint64_t)state->LO.UW[1] + (uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0]; + state->LO.UDW += ((uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0]) << 32; + state->HI.UDW += (uint64_t)Tmp[0].W[1] + (uint64_t)Tmp[1].W[1] + Tmp[2].UW[1]; +} + +void r4300i_SPECIAL_DMULTU (usf_state_t * state) { + MIPS_DWORD Tmp[3]; + + state->LO.UDW = (uint64_t)state->GPR[state->Opcode.rs].UW[0] * (uint64_t)state->GPR[state->Opcode.rt].UW[0]; + Tmp[0].UDW = (uint64_t)state->GPR[state->Opcode.rs].UW[1] * (uint64_t)state->GPR[state->Opcode.rt].UW[0]; + Tmp[1].UDW = (uint64_t)state->GPR[state->Opcode.rs].UW[0] * (uint64_t)state->GPR[state->Opcode.rt].UW[1]; + state->HI.UDW = (uint64_t)state->GPR[state->Opcode.rs].UW[1] * (uint64_t)state->GPR[state->Opcode.rt].UW[1]; + + Tmp[2].UDW = (uint64_t)state->LO.UW[1] + (uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0]; + state->LO.UDW += ((uint64_t)Tmp[0].UW[0] + (uint64_t)Tmp[1].UW[0]) << 32; + state->HI.UDW += (uint64_t)Tmp[0].UW[1] + (uint64_t)Tmp[1].UW[1] + Tmp[2].UW[1]; +} + +void r4300i_SPECIAL_DDIV (usf_state_t * state) { + if ( state->GPR[state->Opcode.rt].UDW != 0 ) { + state->LO.DW = state->GPR[state->Opcode.rs].DW / state->GPR[state->Opcode.rt].DW; + state->HI.DW = state->GPR[state->Opcode.rs].DW % state->GPR[state->Opcode.rt].DW; + } else { + } +} + +void r4300i_SPECIAL_DDIVU (usf_state_t * state) { + if ( state->GPR[state->Opcode.rt].UDW != 0 ) { + state->LO.UDW = state->GPR[state->Opcode.rs].UDW / state->GPR[state->Opcode.rt].UDW; + state->HI.UDW = state->GPR[state->Opcode.rs].UDW % state->GPR[state->Opcode.rt].UDW; + } else { + } +} + +void r4300i_SPECIAL_ADD (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].W[0] + state->GPR[state->Opcode.rt].W[0]; +} + +void r4300i_SPECIAL_ADDU (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].W[0] + state->GPR[state->Opcode.rt].W[0]; +} + +void r4300i_SPECIAL_SUB (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].W[0] - state->GPR[state->Opcode.rt].W[0]; +} + +void r4300i_SPECIAL_SUBU (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].W[0] - state->GPR[state->Opcode.rt].W[0]; +} + +void r4300i_SPECIAL_AND (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].DW & state->GPR[state->Opcode.rt].DW; +} + +void r4300i_SPECIAL_OR (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].DW | state->GPR[state->Opcode.rt].DW; +} + +void r4300i_SPECIAL_XOR (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].DW ^ state->GPR[state->Opcode.rt].DW; +} + +void r4300i_SPECIAL_NOR (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = ~(state->GPR[state->Opcode.rs].DW | state->GPR[state->Opcode.rt].DW); +} + +void r4300i_SPECIAL_SLT (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW < state->GPR[state->Opcode.rt].DW) { + state->GPR[state->Opcode.rd].DW = 1; + } else { + state->GPR[state->Opcode.rd].DW = 0; + } +} + +void r4300i_SPECIAL_SLTU (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].UDW < state->GPR[state->Opcode.rt].UDW) { + state->GPR[state->Opcode.rd].DW = 1; + } else { + state->GPR[state->Opcode.rd].DW = 0; + } +} + +void r4300i_SPECIAL_DADD (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].DW + state->GPR[state->Opcode.rt].DW; +} + +void r4300i_SPECIAL_DADDU (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].DW + state->GPR[state->Opcode.rt].DW; +} + +void r4300i_SPECIAL_DSUB (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].DW - state->GPR[state->Opcode.rt].DW; +} + +void r4300i_SPECIAL_DSUBU (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = state->GPR[state->Opcode.rs].DW - state->GPR[state->Opcode.rt].DW; +} + +void r4300i_SPECIAL_TEQ (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW == state->GPR[state->Opcode.rt].DW) { + } +} + +void r4300i_SPECIAL_DSLL (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].DW << state->Opcode.sa); +} + +void r4300i_SPECIAL_DSRL (usf_state_t * state) { + state->GPR[state->Opcode.rd].UDW = (state->GPR[state->Opcode.rt].UDW >> state->Opcode.sa); +} + +void r4300i_SPECIAL_DSRA (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].DW >> state->Opcode.sa); +} + +void r4300i_SPECIAL_DSLL32 (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].DW << (state->Opcode.sa + 32)); +} + +void r4300i_SPECIAL_DSRL32 (usf_state_t * state) { + state->GPR[state->Opcode.rd].UDW = (state->GPR[state->Opcode.rt].UDW >> (state->Opcode.sa + 32)); +} + +void r4300i_SPECIAL_DSRA32 (usf_state_t * state) { + state->GPR[state->Opcode.rd].DW = (state->GPR[state->Opcode.rt].DW >> (state->Opcode.sa + 32)); +} + +/********************** R4300i state->Opcodes: RegImm **********************/ +void r4300i_REGIMM_BLTZ (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW < 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_REGIMM_BGEZ (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW >= 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_REGIMM_BLTZL (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW < 0) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_REGIMM_BGEZL (usf_state_t * state) { + if (state->GPR[state->Opcode.rs].DW >= 0) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_REGIMM_BLTZAL (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW < 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } + state->GPR[31].DW= (int32_t)(state->PROGRAM_COUNTER + 8); +} + +void r4300i_REGIMM_BGEZAL (usf_state_t * state) { + state->NextInstruction = DELAY_SLOT; + if (state->GPR[state->Opcode.rs].DW >= 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + TestInterpreterJump(state,state->PROGRAM_COUNTER,state->JumpToLocation,state->Opcode.rs,0); + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } + state->GPR[31].DW = (int32_t)(state->PROGRAM_COUNTER + 8); +} +/************************** COP0 functions **************************/ +void r4300i_COP0_MF (usf_state_t * state) { + state->GPR[state->Opcode.rt].DW = (int32_t)state->CP0[state->Opcode.rd]; +} + +void r4300i_COP0_MT (usf_state_t * state) { + switch (state->Opcode.rd) { + case 0: //Index + case 2: //EntryLo0 + case 3: //EntryLo1 + case 5: //PageMask + case 6: //Wired + case 10: //Entry Hi + case 14: //EPC + case 16: //Config + case 18: //WatchLo + case 19: //WatchHi + case 28: //Tag lo + case 29: //Tag Hi + case 30: //ErrEPC + state->CP0[state->Opcode.rd] = state->GPR[state->Opcode.rt].UW[0]; + break; + case 4: //Context + state->CP0[state->Opcode.rd] = state->GPR[state->Opcode.rt].UW[0] & 0xFF800000; + break; + case 9: //Count + state->CP0[state->Opcode.rd]= state->GPR[state->Opcode.rt].UW[0]; + ChangeCompareTimer(state); + break; + case 11: //Compare + state->CP0[state->Opcode.rd] = state->GPR[state->Opcode.rt].UW[0]; + FAKE_CAUSE_REGISTER &= ~CAUSE_IP7; + ChangeCompareTimer(state); + break; + case 12: //Status + if ((state->CP0[state->Opcode.rd] ^ state->GPR[state->Opcode.rt].UW[0]) != 0) { + state->CP0[state->Opcode.rd] = state->GPR[state->Opcode.rt].UW[0]; + SetFpuLocations(state); + } else { + state->CP0[state->Opcode.rd] = state->GPR[state->Opcode.rt].UW[0]; + } + if ((state->CP0[state->Opcode.rd] & 0x18) != 0) { + } + CheckInterrupts(state); + break; + case 13: //cause + state->CP0[state->Opcode.rd] &= 0xFFFFCFF; + break; + default: + R4300i_UnknownOpcode(state); + } + +} + +/************************** COP0 CO functions ***********************/ +void r4300i_COP0_CO_TLBR (usf_state_t * state) { + TLB_Read(state); +} + +void r4300i_COP0_CO_TLBWI (usf_state_t * state) { + WriteTLBEntry(state, INDEX_REGISTER & 0x1F); +} + +void r4300i_COP0_CO_TLBWR (usf_state_t * state) { + WriteTLBEntry(state, RANDOM_REGISTER & 0x1F); +} + +void r4300i_COP0_CO_TLBP (usf_state_t * state) { + TLB_Probe(state); +} + +void r4300i_COP0_CO_ERET (usf_state_t * state) { + state->NextInstruction = JUMP; + if ((STATUS_REGISTER & STATUS_ERL) != 0) { + state->JumpToLocation = ERROREPC_REGISTER; + STATUS_REGISTER &= ~STATUS_ERL; + } else { + state->JumpToLocation = EPC_REGISTER; + STATUS_REGISTER &= ~STATUS_EXL; + } + state->LLBit = 0; + CheckInterrupts(state); +} + +/************************** COP1 functions **************************/ +void r4300i_COP1_MF (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + state->GPR[state->Opcode.rt].DW = *(int32_t *)state->FPRFloatLocation[state->Opcode.fs]; +} + +void r4300i_COP1_DMF (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + state->GPR[state->Opcode.rt].DW = *(int64_t *)state->FPRDoubleLocation[state->Opcode.fs]; +} + +void r4300i_COP1_CF (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + if (state->Opcode.fs != 31 && state->Opcode.fs != 0) { + return; + } + state->GPR[state->Opcode.rt].DW = (int32_t)state->FPCR[state->Opcode.fs]; +} + +void r4300i_COP1_MT (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(int32_t *)state->FPRFloatLocation[state->Opcode.fs] = state->GPR[state->Opcode.rt].W[0]; +} + +void r4300i_COP1_DMT (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(int64_t *)state->FPRDoubleLocation[state->Opcode.fs] = state->GPR[state->Opcode.rt].DW; +} + +void r4300i_COP1_CT (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + if (state->Opcode.fs == 31) { + state->FPCR[state->Opcode.fs] = state->GPR[state->Opcode.rt].W[0]; + return; + } +} + +/************************* COP1: BC1 functions ***********************/ +void r4300i_COP1_BCF (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + state->NextInstruction = DELAY_SLOT; + if ((state->FPCR[31] & FPCSR_C) == 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_COP1_BCT (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + state->NextInstruction = DELAY_SLOT; + if ((state->FPCR[31] & FPCSR_C) != 0) { + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + } else { + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_COP1_BCFL (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + if ((state->FPCR[31] & FPCSR_C) == 0) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} + +void r4300i_COP1_BCTL (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + if ((state->FPCR[31] & FPCSR_C) != 0) { + state->NextInstruction = DELAY_SLOT; + state->JumpToLocation = state->PROGRAM_COUNTER + ((int16_t)state->Opcode.offset << 2) + 4; + } else { + state->NextInstruction = JUMP; + state->JumpToLocation = state->PROGRAM_COUNTER + 8; + } +} +/************************** COP1: S functions ************************/ +INLINE void Float_RoundToInteger32( int32_t * Dest, float * Source ) { + *Dest = (int32_t)*Source; +} + +INLINE void Float_RoundToInteger64( int64_t * Dest, float * Source ) { + *Dest = (int64_t)*Source; +} + +void r4300i_COP1_S_ADD (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (*(float *)state->FPRFloatLocation[state->Opcode.fs] + *(float *)state->FPRFloatLocation[state->Opcode.ft]); +} + +void r4300i_COP1_S_SUB (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (*(float *)state->FPRFloatLocation[state->Opcode.fs] - *(float *)state->FPRFloatLocation[state->Opcode.ft]); +} + +void r4300i_COP1_S_MUL (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (*(float *)state->FPRFloatLocation[state->Opcode.fs] * *(float *)state->FPRFloatLocation[state->Opcode.ft]); +} + +void r4300i_COP1_S_DIV (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (*(float *)state->FPRFloatLocation[state->Opcode.fs] / *(float *)state->FPRFloatLocation[state->Opcode.ft]); +} + +void r4300i_COP1_S_SQRT (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (float)sqrt(*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_ABS (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (float)fabs(*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_MOV (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = *(float *)state->FPRFloatLocation[state->Opcode.fs]; +} + +void r4300i_COP1_S_NEG (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (*(float *)state->FPRFloatLocation[state->Opcode.fs] * -1.0f); +} + +void r4300i_COP1_S_TRUNC_L (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + //_controlfp(_RC_CHOP,_MCW_RC); + Float_RoundToInteger64(&*(int64_t *)state->FPRDoubleLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_CEIL_L (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + //_controlfp(_RC_UP,_MCW_RC); + Float_RoundToInteger64(&*(int64_t *)state->FPRDoubleLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_FLOOR_L (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + Float_RoundToInteger64(&*(int64_t *)state->FPRDoubleLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_ROUND_W (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Float_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_TRUNC_W (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + //_controlfp(_RC_CHOP,_MCW_RC); + Float_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_CEIL_W (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + //_controlfp(_RC_UP,_MCW_RC); + Float_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_FLOOR_W (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Float_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_CVT_D (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = (double)(*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_CVT_W (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Float_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_CVT_L (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Float_RoundToInteger64(&*(int64_t *)state->FPRDoubleLocation[state->Opcode.fd],&*(float *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_S_CMP (usf_state_t * state) { + int32_t less, equal, unorded, condition; + float Temp0, Temp1; + + TEST_COP1_USABLE_EXCEPTION + + Temp0 = *(float *)state->FPRFloatLocation[state->Opcode.fs]; + Temp1 = *(float *)state->FPRFloatLocation[state->Opcode.ft]; + + if(0) { + //if (_isnan(Temp0) || _isnan(Temp1)) { + less = 0; + equal = 0; + unorded = 1; + if ((state->Opcode.funct & 8) != 0) { + } + } else { + less = Temp0 < Temp1; + equal = Temp0 == Temp1; + unorded = 0; + } + + condition = ((state->Opcode.funct & 4) && less) | ((state->Opcode.funct & 2) && equal) | + ((state->Opcode.funct & 1) && unorded); + + if (condition) { + state->FPCR[31] |= FPCSR_C; + } else { + state->FPCR[31] &= ~FPCSR_C; + } + +} + +/************************** COP1: D functions ************************/ +INLINE void Double_RoundToInteger32( int32_t * Dest, double * Source ) { + *Dest = (int32_t)*Source; +} + +INLINE void Double_RoundToInteger64( int64_t * Dest, double * Source ) { + *Dest = (int64_t)*Source; +} + +void r4300i_COP1_D_ADD (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = *(double *)state->FPRDoubleLocation[state->Opcode.fs] + *(double *)state->FPRDoubleLocation[state->Opcode.ft]; +} + +void r4300i_COP1_D_SUB (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = *(double *)state->FPRDoubleLocation[state->Opcode.fs] - *(double *)state->FPRDoubleLocation[state->Opcode.ft]; +} + +void r4300i_COP1_D_MUL (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = *(double *)state->FPRDoubleLocation[state->Opcode.fs] * *(double *)state->FPRDoubleLocation[state->Opcode.ft]; +} + +void r4300i_COP1_D_DIV (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = *(double *)state->FPRDoubleLocation[state->Opcode.fs] / *(double *)state->FPRDoubleLocation[state->Opcode.ft]; +} + +void r4300i_COP1_D_SQRT (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = (double)sqrt(*(double *)state->FPRDoubleLocation[state->Opcode.fs]); +} + +void r4300i_COP1_D_ABS (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = fabs(*(double *)state->FPRDoubleLocation[state->Opcode.fs]); +} + +void r4300i_COP1_D_MOV (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(int64_t *)state->FPRDoubleLocation[state->Opcode.fd] = *(int64_t *)state->FPRDoubleLocation[state->Opcode.fs]; +} + +void r4300i_COP1_D_NEG (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = (*(double *)state->FPRDoubleLocation[state->Opcode.fs] * -1.0); +} + +void r4300i_COP1_D_TRUNC_L (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger64(&*(int64_t *)state->FPRFloatLocation[state->Opcode.fd],&*(double *)state->FPRDoubleLocation[state->Opcode.fs] ); +} + +void r4300i_COP1_D_CEIL_L (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger64(&*(int64_t *)state->FPRFloatLocation[state->Opcode.fd],&*(double *)state->FPRDoubleLocation[state->Opcode.fs] ); +} + +void r4300i_COP1_D_FLOOR_L (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger64(&*(int64_t *)state->FPRDoubleLocation[state->Opcode.fd],&*(double *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_D_ROUND_W (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(double *)state->FPRDoubleLocation[state->Opcode.fs] ); +} + +void r4300i_COP1_D_TRUNC_W (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(double *)state->FPRDoubleLocation[state->Opcode.fs] ); +} + +void r4300i_COP1_D_CEIL_W (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(double *)state->FPRDoubleLocation[state->Opcode.fs] ); +} + +void r4300i_COP1_D_FLOOR_W (usf_state_t * state) { //added by Witten + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger32(&*(int32_t *)state->FPRDoubleLocation[state->Opcode.fd],&*(double *)state->FPRFloatLocation[state->Opcode.fs]); +} + +void r4300i_COP1_D_CVT_S (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (float)*(double *)state->FPRDoubleLocation[state->Opcode.fs]; +} + +void r4300i_COP1_D_CVT_W (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger32(&*(int32_t *)state->FPRFloatLocation[state->Opcode.fd],&*(double *)state->FPRDoubleLocation[state->Opcode.fs] ); +} + +void r4300i_COP1_D_CVT_L (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + Double_RoundToInteger64(&*(int64_t *)state->FPRDoubleLocation[state->Opcode.fd],&*(double *)state->FPRDoubleLocation[state->Opcode.fs]); +} + +void r4300i_COP1_D_CMP (usf_state_t * state) { + int32_t less, equal, unorded, condition; + MIPS_DWORD Temp0, Temp1; + + TEST_COP1_USABLE_EXCEPTION + + Temp0.DW = *(int64_t *)state->FPRDoubleLocation[state->Opcode.fs]; + Temp1.DW = *(int64_t *)state->FPRDoubleLocation[state->Opcode.ft]; + + if(0) { + //if (_isnan(Temp0.D) || _isnan(Temp1.D)) { + less = 0; + equal = 0; + unorded = 1; + if ((state->Opcode.funct & 8) != 0) { + } + } else { + less = Temp0.D < Temp1.D; + equal = Temp0.D == Temp1.D; + unorded = 0; + } + + condition = ((state->Opcode.funct & 4) && less) | ((state->Opcode.funct & 2) && equal) | + ((state->Opcode.funct & 1) && unorded); + + if (condition) { + state->FPCR[31] |= FPCSR_C; + } else { + state->FPCR[31] &= ~FPCSR_C; + } +} + +/************************** COP1: W functions ************************/ +void r4300i_COP1_W_CVT_S (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (float)*(int32_t *)state->FPRFloatLocation[state->Opcode.fs]; +} + +void r4300i_COP1_W_CVT_D (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = (double)*(int32_t *)state->FPRFloatLocation[state->Opcode.fs]; +} + +/************************** COP1: L functions ************************/ +void r4300i_COP1_L_CVT_S (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(float *)state->FPRFloatLocation[state->Opcode.fd] = (float)*(int64_t *)state->FPRDoubleLocation[state->Opcode.fs]; +} + +void r4300i_COP1_L_CVT_D (usf_state_t * state) { + TEST_COP1_USABLE_EXCEPTION + *(double *)state->FPRDoubleLocation[state->Opcode.fd] = (double)*(int64_t *)state->FPRDoubleLocation[state->Opcode.fs]; +} + +/************************** Other functions **************************/ +void R4300i_UnknownOpcode (usf_state_t * state) { + DisplayError("Unkniown X86 Opcode.\tPC:%08x\tOp:%08x\n", state->PROGRAM_COUNTER,state->Opcode.Hex); + StopEmulation(state); +} diff --git a/Frameworks/lazyusf/lazyusf/interpreter_ops.h b/Frameworks/lazyusf/lazyusf/interpreter_ops.h new file mode 100644 index 000000000..d8cc8fcaf --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/interpreter_ops.h @@ -0,0 +1,206 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +/************************* OpCode functions *************************/ +void r4300i_J ( usf_state_t * ); +void r4300i_JAL ( usf_state_t * ); +void r4300i_BNE ( usf_state_t * ); +void r4300i_BEQ ( usf_state_t * ); +void r4300i_BLEZ ( usf_state_t * ); +void r4300i_BGTZ ( usf_state_t * ); +void r4300i_ADDI ( usf_state_t * ); +void r4300i_ADDIU ( usf_state_t * ); +void r4300i_SLTI ( usf_state_t * ); +void r4300i_SLTIU ( usf_state_t * ); +void r4300i_ANDI ( usf_state_t * ); +void r4300i_ORI ( usf_state_t * ); +void r4300i_XORI ( usf_state_t * ); +void r4300i_LUI ( usf_state_t * ); +void r4300i_BEQL ( usf_state_t * ); +void r4300i_BNEL ( usf_state_t * ); +void r4300i_BLEZL ( usf_state_t * ); +void r4300i_BGTZL ( usf_state_t * ); +void r4300i_DADDIU ( usf_state_t * ); +void r4300i_LDL ( usf_state_t * ); +void r4300i_LDR ( usf_state_t * ); +void r4300i_LB ( usf_state_t * ); +void r4300i_LH ( usf_state_t * ); +void r4300i_LWL ( usf_state_t * ); +void r4300i_LW ( usf_state_t * ); +void r4300i_LBU ( usf_state_t * ); +void r4300i_LHU ( usf_state_t * ); +void r4300i_LWR ( usf_state_t * ); +void r4300i_LWU ( usf_state_t * ); +void r4300i_SB ( usf_state_t * ); +void r4300i_SH ( usf_state_t * ); +void r4300i_SWL ( usf_state_t * ); +void r4300i_SW ( usf_state_t * ); +void r4300i_SDL ( usf_state_t * ); +void r4300i_SDR ( usf_state_t * ); +void r4300i_SWR ( usf_state_t * ); +void r4300i_CACHE ( usf_state_t * ); +void r4300i_LL ( usf_state_t * ); +void r4300i_LWC1 ( usf_state_t * ); +void r4300i_LDC1 ( usf_state_t * ); +void r4300i_LD ( usf_state_t * ); +void r4300i_SC ( usf_state_t * ); +void r4300i_SWC1 ( usf_state_t * ); +void r4300i_SDC1 ( usf_state_t * ); +void r4300i_SD ( usf_state_t * ); + +/********************** R4300i OpCodes: Special **********************/ +void r4300i_SPECIAL_SLL ( usf_state_t * ); +void r4300i_SPECIAL_SRL ( usf_state_t * ); +void r4300i_SPECIAL_SRA ( usf_state_t * ); +void r4300i_SPECIAL_SLLV ( usf_state_t * ); +void r4300i_SPECIAL_SRLV ( usf_state_t * ); +void r4300i_SPECIAL_SRAV ( usf_state_t * ); +void r4300i_SPECIAL_JR ( usf_state_t * ); +void r4300i_SPECIAL_JALR ( usf_state_t * ); +void r4300i_SPECIAL_SYSCALL ( usf_state_t * ); +void r4300i_SPECIAL_BREAK ( usf_state_t * ); +void r4300i_SPECIAL_SYNC ( usf_state_t * ); +void r4300i_SPECIAL_MFHI ( usf_state_t * ); +void r4300i_SPECIAL_MTHI ( usf_state_t * ); +void r4300i_SPECIAL_MFLO ( usf_state_t * ); +void r4300i_SPECIAL_MTLO ( usf_state_t * ); +void r4300i_SPECIAL_DSLLV ( usf_state_t * ); +void r4300i_SPECIAL_DSRLV ( usf_state_t * ); +void r4300i_SPECIAL_DSRAV ( usf_state_t * ); +void r4300i_SPECIAL_MULT ( usf_state_t * ); +void r4300i_SPECIAL_MULTU ( usf_state_t * ); +void r4300i_SPECIAL_DIV ( usf_state_t * ); +void r4300i_SPECIAL_DIVU ( usf_state_t * ); +void r4300i_SPECIAL_DMULT ( usf_state_t * ); +void r4300i_SPECIAL_DMULTU ( usf_state_t * ); +void r4300i_SPECIAL_DDIV ( usf_state_t * ); +void r4300i_SPECIAL_DDIVU ( usf_state_t * ); +void r4300i_SPECIAL_ADD ( usf_state_t * ); +void r4300i_SPECIAL_ADDU ( usf_state_t * ); +void r4300i_SPECIAL_SUB ( usf_state_t * ); +void r4300i_SPECIAL_SUBU ( usf_state_t * ); +void r4300i_SPECIAL_AND ( usf_state_t * ); +void r4300i_SPECIAL_OR ( usf_state_t * ); +void r4300i_SPECIAL_XOR ( usf_state_t * ); +void r4300i_SPECIAL_NOR ( usf_state_t * ); +void r4300i_SPECIAL_SLT ( usf_state_t * ); +void r4300i_SPECIAL_SLTU ( usf_state_t * ); +void r4300i_SPECIAL_DADD ( usf_state_t * ); +void r4300i_SPECIAL_DADDU ( usf_state_t * ); +void r4300i_SPECIAL_DSUB ( usf_state_t * ); +void r4300i_SPECIAL_DSUBU ( usf_state_t * ); +void r4300i_SPECIAL_TEQ ( usf_state_t * ); +void r4300i_SPECIAL_DSLL ( usf_state_t * ); +void r4300i_SPECIAL_DSRL ( usf_state_t * ); +void r4300i_SPECIAL_DSRA ( usf_state_t * ); +void r4300i_SPECIAL_DSLL32 ( usf_state_t * ); +void r4300i_SPECIAL_DSRL32 ( usf_state_t * ); +void r4300i_SPECIAL_DSRA32 ( usf_state_t * ); + +/********************** R4300i OpCodes: RegImm **********************/ +void r4300i_REGIMM_BLTZ ( usf_state_t * ); +void r4300i_REGIMM_BGEZ ( usf_state_t * ); +void r4300i_REGIMM_BLTZL ( usf_state_t * ); +void r4300i_REGIMM_BGEZL ( usf_state_t * ); +void r4300i_REGIMM_BLTZAL ( usf_state_t * ); +void r4300i_REGIMM_BGEZAL ( usf_state_t * ); + +/************************** COP0 functions **************************/ +void r4300i_COP0_MF ( usf_state_t * ); +void r4300i_COP0_MT ( usf_state_t * ); + +/************************** COP0 CO functions ***********************/ +void r4300i_COP0_CO_TLBR ( usf_state_t * ); +void r4300i_COP0_CO_TLBWI ( usf_state_t * ); +void r4300i_COP0_CO_TLBWR ( usf_state_t * ); +void r4300i_COP0_CO_TLBP ( usf_state_t * ); +void r4300i_COP0_CO_ERET ( usf_state_t * ); + +/************************** COP1 functions **************************/ +void r4300i_COP1_MF ( usf_state_t * ); +void r4300i_COP1_DMF ( usf_state_t * ); +void r4300i_COP1_CF ( usf_state_t * ); +void r4300i_COP1_MT ( usf_state_t * ); +void r4300i_COP1_DMT ( usf_state_t * ); +void r4300i_COP1_CT ( usf_state_t * ); + +/************************* COP1: BC1 functions ***********************/ +void r4300i_COP1_BCF ( usf_state_t * ); +void r4300i_COP1_BCT ( usf_state_t * ); +void r4300i_COP1_BCFL ( usf_state_t * ); +void r4300i_COP1_BCTL ( usf_state_t * ); + +/************************** COP1: S functions ************************/ +void r4300i_COP1_S_ADD ( usf_state_t * ); +void r4300i_COP1_S_SUB ( usf_state_t * ); +void r4300i_COP1_S_MUL ( usf_state_t * ); +void r4300i_COP1_S_DIV ( usf_state_t * ); +void r4300i_COP1_S_SQRT ( usf_state_t * ); +void r4300i_COP1_S_ABS ( usf_state_t * ); +void r4300i_COP1_S_MOV ( usf_state_t * ); +void r4300i_COP1_S_NEG ( usf_state_t * ); +void r4300i_COP1_S_TRUNC_L ( usf_state_t * ); +void r4300i_COP1_S_CEIL_L ( usf_state_t * ); //added by Witten +void r4300i_COP1_S_FLOOR_L ( usf_state_t * ); //added by Witten +void r4300i_COP1_S_ROUND_W ( usf_state_t * ); +void r4300i_COP1_S_TRUNC_W ( usf_state_t * ); +void r4300i_COP1_S_CEIL_W ( usf_state_t * ); //added by Witten +void r4300i_COP1_S_FLOOR_W ( usf_state_t * ); +void r4300i_COP1_S_CVT_D ( usf_state_t * ); +void r4300i_COP1_S_CVT_W ( usf_state_t * ); +void r4300i_COP1_S_CVT_L ( usf_state_t * ); +void r4300i_COP1_S_CMP ( usf_state_t * ); + +/************************** COP1: D functions ************************/ +void r4300i_COP1_D_ADD ( usf_state_t * ); +void r4300i_COP1_D_SUB ( usf_state_t * ); +void r4300i_COP1_D_MUL ( usf_state_t * ); +void r4300i_COP1_D_DIV ( usf_state_t * ); +void r4300i_COP1_D_SQRT ( usf_state_t * ); +void r4300i_COP1_D_ABS ( usf_state_t * ); +void r4300i_COP1_D_MOV ( usf_state_t * ); +void r4300i_COP1_D_NEG ( usf_state_t * ); +void r4300i_COP1_D_TRUNC_L ( usf_state_t * ); //added by Witten +void r4300i_COP1_D_CEIL_L ( usf_state_t * ); //added by Witten +void r4300i_COP1_D_FLOOR_L ( usf_state_t * ); //added by Witten +void r4300i_COP1_D_ROUND_W ( usf_state_t * ); +void r4300i_COP1_D_TRUNC_W ( usf_state_t * ); +void r4300i_COP1_D_CEIL_W ( usf_state_t * ); //added by Witten +void r4300i_COP1_D_FLOOR_W ( usf_state_t * ); //added by Witten +void r4300i_COP1_D_CVT_S ( usf_state_t * ); +void r4300i_COP1_D_CVT_W ( usf_state_t * ); +void r4300i_COP1_D_CVT_L ( usf_state_t * ); +void r4300i_COP1_D_CMP ( usf_state_t * ); + +/************************** COP1: W functions ************************/ +void r4300i_COP1_W_CVT_S ( usf_state_t * ); +void r4300i_COP1_W_CVT_D ( usf_state_t * ); + +/************************** COP1: L functions ************************/ +void r4300i_COP1_L_CVT_S ( usf_state_t * ); +void r4300i_COP1_L_CVT_D ( usf_state_t * ); + +/************************** Other functions **************************/ +void R4300i_UnknownOpcode ( usf_state_t * ); diff --git a/Frameworks/lazyusf/lazyusf/lazyusf-Info.plist b/Frameworks/lazyusf/lazyusf/lazyusf-Info.plist new file mode 100644 index 000000000..8bf5f6920 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/lazyusf-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + net.kode54.lazyusf + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2014 Christopher Snowhill. All rights reserved. + NSPrincipalClass + + + diff --git a/Frameworks/lazyusf/lazyusf/main.c b/Frameworks/lazyusf/lazyusf/main.c new file mode 100644 index 000000000..ba840fe2d --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/main.c @@ -0,0 +1,31 @@ + +#include +#include +#include +#include +#include +#include "usf.h" +#include "cpu.h" +#include "memory.h" + +#include "usf_internal.h" + +void StopEmulation(usf_state_t * state) +{ + //asm("int $3"); + //printf("Arrivederci!\n\n"); + //Release_Memory(); + //exit(0); + state->cpu_running = 0; +} + +void DisplayError (char * Message, ...) { + //char Msg[1000]; + //va_list ap; + + //va_start( ap, Message ); + //vsprintf( Msg, Message, ap ); + //va_end( ap ); + + //printf("Error: %s\n", Msg); +} diff --git a/Frameworks/lazyusf/lazyusf/main.h b/Frameworks/lazyusf/lazyusf/main.h new file mode 100644 index 000000000..62aec0390 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/main.h @@ -0,0 +1,10 @@ +#include + +#include "usf.h" + +#define CPU_Default -1 +#define CPU_Interpreter 0 +#define CPU_Recompiler 1 + +void DisplayError (char * Message, ...); +void StopEmulation(usf_state_t *); diff --git a/Frameworks/lazyusf/lazyusf/memory.c b/Frameworks/lazyusf/lazyusf/memory.c new file mode 100644 index 000000000..df63f6083 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/memory.c @@ -0,0 +1,748 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#include +#include +#include +#include +#include + +#include "usf.h" +#include "main.h" +#include "cpu.h" +#include "audio.h" +#include "rsp.h" + +#include "usf_internal.h" + +uint8_t * PageROM(usf_state_t * state, uint32_t addr) { + return (state->ROMPages[addr/0x10000])?state->ROMPages[addr/0x10000]+(addr%0x10000):&state->EmptySpace; +} + +int32_t Allocate_Memory ( void * state ) { + uint32_t i = 0; + //RdramSize = 0x800000; + + // Allocate the N64MEM and TLB_Map so that they are in each others 4GB range + // Also put the registers there :) + + + // the mmap technique works craptacular when the regions don't overlay + + USF_STATE->MemChunk = mmap(NULL, 0x100000 * sizeof(uintptr_t) + 0x1D000 + USF_STATE->RdramSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0); + + USF_STATE->TLB_Map = (uintptr_t*)USF_STATE->MemChunk; + if (USF_STATE->TLB_Map == NULL) { + return 0; + } + + memset(USF_STATE->TLB_Map, 0, 0x100000 * sizeof(uintptr_t) + 0x10000); + + USF_STATE->N64MEM = mmap((uintptr_t)USF_STATE->MemChunk + 0x100000 * sizeof(uintptr_t) + 0x10000, 0xD000 + USF_STATE->RdramSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, 0, 0); + if(USF_STATE->N64MEM == NULL) { + DisplayError("Failed to allocate N64MEM"); + return 0; + } + + //memset(state->N64MEM, 0, state->RdramSize); + + USF_STATE->NOMEM = mmap((uintptr_t)USF_STATE->N64MEM + USF_STATE->RdramSize, 0xD000, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, 0, 0); + + if(USF_STATE->RdramSize == 0x400000) + { + // munmap(N64MEM + 0x400000, 0x400000); + } + + USF_STATE->Registers = (N64_REGISTERS *)((uintptr_t)USF_STATE->MemChunk + 0x100000 * sizeof(uintptr_t)); + //USF_STATE->TLBLoadAddress = (uint32_t *)((uintptr_t)USF_STATE->Registers + 0x500); + //USF_STATE->Timers = (SYSTEM_TIMERS*)(USF_STATE->TLBLoadAddress + 4); + USF_STATE->Timers = (SYSTEM_TIMERS*)((uintptr_t)USF_STATE->Registers + 0x500); + USF_STATE->WaitMode = (uint32_t *)(USF_STATE->Timers + sizeof(SYSTEM_TIMERS)); + USF_STATE->CPU_Action = (CPU_ACTION *)(USF_STATE->WaitMode + 4); + //USF_STATE->RSP_GPR = (struct RSP_GPR_TYPE *)(USF_STATE->CPU_Action + sizeof(CPU_ACTION)); + //USF_STATE->DMEM = (uint8_t *)(USF_STATE->RSP_GPR + (32 * 16)); + USF_STATE->DMEM = (uint8_t *)(USF_STATE->CPU_Action + sizeof(CPU_ACTION)); + //state->RSP_ACCUM = (struct RSP_ACCUM_TYPE *)(USF_STATE->DMEM + 0x2000); + + USF_STATE->RDRAM = (uint8_t *)(USF_STATE->N64MEM); + USF_STATE->IMEM = USF_STATE->DMEM + 0x1000; + + USF_STATE->MemoryState = 1; + + return 1; +} + +int PreAllocate_Memory(usf_state_t * state) { + int i = 0; + + // Moved the savestate allocation here :) (for better management later) + state->savestatespace = malloc(0x80275C); + + if(state->savestatespace == 0) + return 0; + + memset(state->savestatespace, 0, 0x80275C); + + for (i = 0; i < 0x400; i++) { + state->ROMPages[i] = 0; + } + + return 1; +} + +void Release_Memory ( usf_state_t * state ) { + uint32_t i; + + for (i = 0; i < 0x400; i++) { + if (state->ROMPages[i]) { + free(state->ROMPages[i]); state->ROMPages[i] = 0; + } + } + //printf("Freeing memory\n"); + + state->MemoryState = 0; + + if (state->MemChunk != 0) {munmap(state->MemChunk, 0x100000 * sizeof(uintptr_t) + 0x10000); state->MemChunk=0;} + if (state->N64MEM != 0) {munmap(state->N64MEM, state->RdramSize); state->N64MEM=0;} + if (state->NOMEM != 0) {munmap(state->NOMEM, 0xD000); state->NOMEM=0;} + + if(state->savestatespace) + free(state->savestatespace); + state->savestatespace = NULL; +} + + +int32_t r4300i_LB_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value, uint32_t SignExtend ) { + if (PAddr >= 0x10000000 && PAddr < 0x16000000) { + if (state->WrittenToRom) { return 0; } + if ((PAddr & 2) == 0) { PAddr = (PAddr + 4) ^ 2; } + if ((PAddr - 0x10000000) < state->RomFileSize) { + if (SignExtend) { + *Value = (char)*PageROM(state, (PAddr - 0x10000000)^3); + + } else { + *Value = *PageROM(state, (PAddr - 0x10000000)^3); + } + return 1; + } else { + *Value = 0; + return 0; + } + } + + switch (PAddr & 0xFFF00000) { + default: + * Value = 0; + return 0; + break; + } + return 1; +} + +uint32_t r4300i_LB_VAddr ( usf_state_t * state, uint32_t VAddr, uint8_t * Value ) { + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + *Value = *(uint8_t *)(state->TLB_Map[VAddr >> 12] + (VAddr ^ 3)); + return 1; +} + +uint32_t r4300i_LD_VAddr ( usf_state_t * state, uint32_t VAddr, uint64_t * Value ) { + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + *((uint32_t *)(Value) + 1) = *(uint32_t *)(state->TLB_Map[VAddr >> 12] + VAddr); + *((uint32_t *)(Value)) = *(uint32_t *)(state->TLB_Map[VAddr >> 12] + VAddr + 4); + return 1; +} + +int32_t r4300i_LH_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value, int32_t SignExtend ) { + switch (PAddr & 0xFFF00000) { + default: + * Value = 0; + return 0; + break; + } + return 1; +} + +uint32_t r4300i_LH_VAddr ( usf_state_t * state, uint32_t VAddr, uint16_t * Value ) { + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + *Value = *(uint16_t *)(state->TLB_Map[VAddr >> 12] + (VAddr ^ 2)); + return 1; +} + +int32_t r4300i_LW_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t * Value ) { + if (PAddr >= 0x10000000 && PAddr < 0x16000000) { + if (state->WrittenToRom) { + *Value = state->WroteToRom; + //LogMessage("%X: Read crap from Rom %X from %X",PROGRAM_COUNTER,*Value,PAddr); + state->WrittenToRom = 0; + return 1; + } + if ((PAddr - 0x10000000) < state->RomFileSize) { + *Value = *(uint32_t *)PageROM(state, (PAddr - 0x10000000)); + return 1; + } else { + *Value = PAddr & 0xFFFF; + *Value = (*Value << 16) | *Value; + return 0; + } + } + + switch (PAddr & 0xFFF00000) { + case 0x03F00000: + switch (PAddr) { + case 0x03F00000: * Value = RDRAM_CONFIG_REG; break; + case 0x03F00004: * Value = RDRAM_DEVICE_ID_REG; break; + case 0x03F00008: * Value = RDRAM_DELAY_REG; break; + case 0x03F0000C: * Value = RDRAM_MODE_REG; break; + case 0x03F00010: * Value = RDRAM_REF_INTERVAL_REG; break; + case 0x03F00014: * Value = RDRAM_REF_ROW_REG; break; + case 0x03F00018: * Value = RDRAM_RAS_INTERVAL_REG; break; + case 0x03F0001C: * Value = RDRAM_MIN_INTERVAL_REG; break; + case 0x03F00020: * Value = RDRAM_ADDR_SELECT_REG; break; + case 0x03F00024: * Value = RDRAM_DEVICE_MANUF_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04000000: + switch (PAddr) { + case 0x04040010: *Value = SP_STATUS_REG; break; + case 0x04040014: *Value = SP_DMA_FULL_REG; break; + case 0x04040018: *Value = SP_DMA_BUSY_REG; break; + case 0x04080000: *Value = SP_PC_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04100000: + switch (PAddr) { + case 0x0410000C: *Value = DPC_STATUS_REG; break; + case 0x04100010: *Value = DPC_CLOCK_REG; break; + case 0x04100014: *Value = DPC_BUFBUSY_REG; break; + case 0x04100018: *Value = DPC_PIPEBUSY_REG; break; + case 0x0410001C: *Value = DPC_TMEM_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04300000: + switch (PAddr) { + case 0x04300000: * Value = MI_MODE_REG; break; + case 0x04300004: * Value = MI_VERSION_REG; break; + case 0x04300008: * Value = MI_INTR_REG; break; + case 0x0430000C: * Value = MI_INTR_MASK_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04400000: + switch (PAddr) { + case 0x04400000: *Value = VI_STATUS_REG; break; + case 0x04400004: *Value = VI_ORIGIN_REG; break; + case 0x04400008: *Value = VI_WIDTH_REG; break; + case 0x0440000C: *Value = VI_INTR_REG; break; + case 0x04400010: + *Value = 0; + break; + case 0x04400014: *Value = VI_BURST_REG; break; + case 0x04400018: *Value = VI_V_SYNC_REG; break; + case 0x0440001C: *Value = VI_H_SYNC_REG; break; + case 0x04400020: *Value = VI_LEAP_REG; break; + case 0x04400024: *Value = VI_H_START_REG; break; + case 0x04400028: *Value = VI_V_START_REG ; break; + case 0x0440002C: *Value = VI_V_BURST_REG; break; + case 0x04400030: *Value = VI_X_SCALE_REG; break; + case 0x04400034: *Value = VI_Y_SCALE_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04500000: + switch (PAddr) { + case 0x04500004: *Value = AiReadLength(state); break; + case 0x0450000C: *Value = AI_STATUS_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04600000: + switch (PAddr) { + case 0x04600010: *Value = PI_STATUS_REG; break; + case 0x04600014: *Value = PI_DOMAIN1_REG; break; + case 0x04600018: *Value = PI_BSD_DOM1_PWD_REG; break; + case 0x0460001C: *Value = PI_BSD_DOM1_PGS_REG; break; + case 0x04600020: *Value = PI_BSD_DOM1_RLS_REG; break; + case 0x04600024: *Value = PI_DOMAIN2_REG; break; + case 0x04600028: *Value = PI_BSD_DOM2_PWD_REG; break; + case 0x0460002C: *Value = PI_BSD_DOM2_PGS_REG; break; + case 0x04600030: *Value = PI_BSD_DOM2_RLS_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04700000: + switch (PAddr) { + case 0x04700000: * Value = RI_MODE_REG; break; + case 0x04700004: * Value = RI_CONFIG_REG; break; + case 0x04700008: * Value = RI_CURRENT_LOAD_REG; break; + case 0x0470000C: * Value = RI_SELECT_REG; break; + case 0x04700010: * Value = RI_REFRESH_REG; break; + case 0x04700014: * Value = RI_LATENCY_REG; break; + case 0x04700018: * Value = RI_RERROR_REG; break; + case 0x0470001C: * Value = RI_WERROR_REG; break; + default: + * Value = 0; + return 0; + } + break; + case 0x04800000: + switch (PAddr) { + case 0x04800018: *Value = SI_STATUS_REG; break; + default: + *Value = 0; + return 0; + } + break; + case 0x05000000: + *Value = PAddr & 0xFFFF; + *Value = (*Value << 16) | *Value; + return 0; + case 0x08000000: + *Value = 0; + break; + default: + *Value = PAddr & 0xFFFF; + *Value = (*Value << 16) | *Value; + return 0; + break; + } + return 1; +} + +void r4300i_LW_PAddr ( usf_state_t * state, uint32_t PAddr, uint32_t * Value ) { + *Value = *(uint32_t *)(state->N64MEM+PAddr); +} + +uint32_t r4300i_LW_VAddr ( usf_state_t * state, uint32_t VAddr, uint32_t * Value ) { + uintptr_t address = (state->TLB_Map[VAddr >> 12] + VAddr); + + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + + if((address - (uintptr_t)state->RDRAM) > state->RdramSize) { + address = address - (uintptr_t)state->RDRAM; + return r4300i_LW_NonMemory(state, address, Value); + } + *Value = *(uint32_t *)address; + return 1; +} + +int32_t r4300i_SB_NonMemory ( usf_state_t * state, uint32_t PAddr, uint8_t Value ) { + switch (PAddr & 0xFFF00000) { + case 0x00000000: + case 0x00100000: + case 0x00200000: + case 0x00300000: + case 0x00400000: + case 0x00500000: + case 0x00600000: + case 0x00700000: + if (PAddr < state->RdramSize) { + *(uint8_t *)(state->N64MEM+PAddr) = Value; + } + break; + default: + return 0; + break; + } + return 1; +} + +uint32_t r4300i_SB_VAddr ( usf_state_t * state, uint32_t VAddr, uint8_t Value ) { + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + *(uint8_t *)(state->TLB_Map[VAddr >> 12] + (VAddr ^ 3)) = Value; + + return 1; +} + +int32_t r4300i_SH_NonMemory ( usf_state_t * state, uint32_t PAddr, uint16_t Value ) { + switch (PAddr & 0xFFF00000) { + case 0x00000000: + case 0x00100000: + case 0x00200000: + case 0x00300000: + case 0x00400000: + case 0x00500000: + case 0x00600000: + case 0x00700000: + if (PAddr < state->RdramSize) { + *(uint16_t *)(state->N64MEM+PAddr) = Value; + } + break; + default: + return 0; + break; + } + return 1; +} + +uint32_t r4300i_SD_VAddr ( usf_state_t * state, uint32_t VAddr, uint64_t Value ) { + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + *(uint32_t *)(state->TLB_Map[VAddr >> 12] + VAddr) = *((uint32_t *)(&Value) + 1); + *(uint32_t *)(state->TLB_Map[VAddr >> 12] + VAddr + 4) = *((uint32_t *)(&Value)); + return 1; +} + +uint32_t r4300i_SH_VAddr ( usf_state_t * state, uint32_t VAddr, uint16_t Value ) { + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + *(uint16_t *)(state->TLB_Map[VAddr >> 12] + (VAddr ^ 2)) = Value; + return 1; +} + +int32_t r4300i_SW_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t Value ) { + if (PAddr >= 0x10000000 && PAddr < 0x16000000) { + if ((PAddr - 0x10000000) < state->RomFileSize) { + state->WrittenToRom = 1; + state->WroteToRom = Value; + } else { + return 0; + } + } + + switch (PAddr & 0xFFF00000) { + case 0x00000000: + case 0x00100000: + case 0x00200000: + case 0x00300000: + case 0x00400000: + case 0x00500000: + case 0x00600000: + case 0x00700000: + if (PAddr < state->RdramSize) { + *(uint32_t *)(state->N64MEM+PAddr) = Value; + } + break; + case 0x03F00000: + switch (PAddr) { + case 0x03F00000: RDRAM_CONFIG_REG = Value; break; + case 0x03F00004: RDRAM_DEVICE_ID_REG = Value; break; + case 0x03F00008: RDRAM_DELAY_REG = Value; break; + case 0x03F0000C: RDRAM_MODE_REG = Value; break; + case 0x03F00010: RDRAM_REF_INTERVAL_REG = Value; break; + case 0x03F00014: RDRAM_REF_ROW_REG = Value; break; + case 0x03F00018: RDRAM_RAS_INTERVAL_REG = Value; break; + case 0x03F0001C: RDRAM_MIN_INTERVAL_REG = Value; break; + case 0x03F00020: RDRAM_ADDR_SELECT_REG = Value; break; + case 0x03F00024: RDRAM_DEVICE_MANUF_REG = Value; break; + case 0x03F04004: break; + case 0x03F08004: break; + case 0x03F80004: break; + case 0x03F80008: break; + case 0x03F8000C: break; + case 0x03F80014: break; + default: + return 0; + } + break; + case 0x04000000: + if (PAddr < 0x04002000) { + *(uint32_t *)(state->N64MEM+PAddr) = Value; + return 1; + } + switch (PAddr) { + case 0x04040000: SP_MEM_ADDR_REG = Value; break; + case 0x04040004: SP_DRAM_ADDR_REG = Value; break; + case 0x04040008: + SP_RD_LEN_REG = Value; + SP_DMA_READ(state); + break; + case 0x0404000C: + SP_WR_LEN_REG = Value; + SP_DMA_WRITE(state); + break; + case 0x04040010: + if ( ( Value & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; } + if ( ( Value & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; } + if ( ( Value & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; } + if ( ( Value & SP_CLR_INTR ) != 0) { + MI_INTR_REG &= ~MI_INTR_SP; + CheckInterrupts(state); + } + if ( ( Value & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; } + if ( ( Value & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; } + if ( ( Value & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; } + if ( ( Value & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; } + if ( ( Value & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; } + if ( ( Value & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; } + if ( ( Value & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; } + if ( ( Value & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; } + if ( ( Value & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; } + if ( ( Value & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; } + if ( ( Value & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; } + if ( ( Value & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; } + if ( ( Value & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; } + if ( ( Value & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; } + if ( ( Value & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; } + if ( ( Value & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; } + if ( ( Value & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; } + if ( ( Value & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; } + if ( ( Value & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; } + if ( ( Value & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; } + + RunRsp(state); + + break; + case 0x0404001C: SP_SEMAPHORE_REG = 0; break; + case 0x04080000: SP_PC_REG = Value & 0xFFC; break; + default: + return 0; + } + break; + case 0x04100000: + switch (PAddr) { + case 0x04100000: + DPC_START_REG = Value; + DPC_CURRENT_REG = Value; + break; + case 0x04100004: + DPC_END_REG = Value; + break; + case 0x04100008: DPC_CURRENT_REG = Value; break; + case 0x0410000C: + if ( ( Value & DPC_CLR_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_XBUS_DMEM_DMA; } + if ( ( Value & DPC_SET_XBUS_DMEM_DMA ) != 0) { DPC_STATUS_REG |= DPC_STATUS_XBUS_DMEM_DMA; } + if ( ( Value & DPC_CLR_FREEZE ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FREEZE; } + if ( ( Value & DPC_SET_FREEZE ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FREEZE; } + if ( ( Value & DPC_CLR_FLUSH ) != 0) { DPC_STATUS_REG &= ~DPC_STATUS_FLUSH; } + if ( ( Value & DPC_SET_FLUSH ) != 0) { DPC_STATUS_REG |= DPC_STATUS_FLUSH; } + if ( ( Value & DPC_CLR_FREEZE ) != 0) + { + if ( ( SP_STATUS_REG & SP_STATUS_HALT ) == 0) + { + if ( ( SP_STATUS_REG & SP_STATUS_BROKE ) == 0 ) + { + RunRsp(state); + } + } + } + break; + default: + return 0; + } + break; + case 0x04300000: + switch (PAddr) { + case 0x04300000: + MI_MODE_REG &= ~0x7F; + MI_MODE_REG |= (Value & 0x7F); + if ( ( Value & MI_CLR_INIT ) != 0 ) { MI_MODE_REG &= ~MI_MODE_INIT; } + if ( ( Value & MI_SET_INIT ) != 0 ) { MI_MODE_REG |= MI_MODE_INIT; } + if ( ( Value & MI_CLR_EBUS ) != 0 ) { MI_MODE_REG &= ~MI_MODE_EBUS; } + if ( ( Value & MI_SET_EBUS ) != 0 ) { MI_MODE_REG |= MI_MODE_EBUS; } + if ( ( Value & MI_CLR_DP_INTR ) != 0 ) { + MI_INTR_REG &= ~MI_INTR_DP; + CheckInterrupts(state); + } + if ( ( Value & MI_CLR_RDRAM ) != 0 ) { MI_MODE_REG &= ~MI_MODE_RDRAM; } + if ( ( Value & MI_SET_RDRAM ) != 0 ) { MI_MODE_REG |= MI_MODE_RDRAM; } + break; + case 0x0430000C: + if ( ( Value & MI_INTR_MASK_CLR_SP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP; } + if ( ( Value & MI_INTR_MASK_SET_SP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SP; } + if ( ( Value & MI_INTR_MASK_CLR_SI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI; } + if ( ( Value & MI_INTR_MASK_SET_SI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SI; } + if ( ( Value & MI_INTR_MASK_CLR_AI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI; } + if ( ( Value & MI_INTR_MASK_SET_AI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_AI; } + if ( ( Value & MI_INTR_MASK_CLR_VI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI; } + if ( ( Value & MI_INTR_MASK_SET_VI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_VI; } + if ( ( Value & MI_INTR_MASK_CLR_PI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI; } + if ( ( Value & MI_INTR_MASK_SET_PI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_PI; } + if ( ( Value & MI_INTR_MASK_CLR_DP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP; } + if ( ( Value & MI_INTR_MASK_SET_DP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_DP; } + break; + default: + return 0; + } + break; + case 0x04400000: + switch (PAddr) { + case 0x04400000: + //if (VI_STATUS_REG != Value) { + VI_STATUS_REG = Value; + // if (ViStatusChanged != NULL ) { ViStatusChanged(); } + //} + break; + case 0x04400004: + + VI_ORIGIN_REG = (Value & 0xFFFFFF); + //if (UpdateScreen != NULL ) { UpdateScreen(); } + break; + case 0x04400008: + //if (VI_WIDTH_REG != Value) { + VI_WIDTH_REG = Value; + // if (ViWidthChanged != NULL ) { ViWidthChanged(); } + //} + break; + case 0x0440000C: VI_INTR_REG = Value; break; + case 0x04400010: + MI_INTR_REG &= ~MI_INTR_VI; + CheckInterrupts(state); + break; + case 0x04400014: VI_BURST_REG = Value; break; + case 0x04400018: VI_V_SYNC_REG = Value; break; + case 0x0440001C: VI_H_SYNC_REG = Value; break; + case 0x04400020: VI_LEAP_REG = Value; break; + case 0x04400024: VI_H_START_REG = Value; break; + case 0x04400028: VI_V_START_REG = Value; break; + case 0x0440002C: VI_V_BURST_REG = Value; break; + case 0x04400030: VI_X_SCALE_REG = Value; break; + case 0x04400034: VI_Y_SCALE_REG = Value; break; + default: + return 0; + } + break; + case 0x04500000: + switch (PAddr) { + case 0x04500000: AI_DRAM_ADDR_REG = Value; break; + case 0x04500004: + AI_LEN_REG = Value; + AiLenChanged(state); + break; + case 0x04500008: AI_CONTROL_REG = (Value & 0x1); break; + case 0x0450000C: + /* Clear Interrupt */; + MI_INTR_REG &= ~MI_INTR_AI; + state->AudioIntrReg &= ~MI_INTR_AI; + CheckInterrupts(state); + break; + case 0x04500010: + AI_DACRATE_REG = Value; + //if (AiDacrateChanged != NULL) { AiDacrateChanged(SYSTEM_NTSC); } + break; + case 0x04500014: AI_BITRATE_REG = Value; break; + default: + return 0; + } + break; + case 0x04600000: + switch (PAddr) { + case 0x04600000: PI_DRAM_ADDR_REG = Value; break; + case 0x04600004: PI_CART_ADDR_REG = Value; break; + case 0x04600008: + PI_RD_LEN_REG = Value; + PI_DMA_READ(state); + break; + case 0x0460000C: + PI_WR_LEN_REG = Value; + PI_DMA_WRITE(state); + break; + case 0x04600010: + //if ((Value & PI_SET_RESET) != 0 ) { DisplayError("reset Controller"); } + if ((Value & PI_CLR_INTR) != 0 ) { + MI_INTR_REG &= ~MI_INTR_PI; + CheckInterrupts(state); + } + break; + case 0x04600014: PI_DOMAIN1_REG = (Value & 0xFF); break; + case 0x04600018: PI_BSD_DOM1_PWD_REG = (Value & 0xFF); break; + case 0x0460001C: PI_BSD_DOM1_PGS_REG = (Value & 0xFF); break; + case 0x04600020: PI_BSD_DOM1_RLS_REG = (Value & 0xFF); break; + default: + return 0; + } + break; + case 0x04700000: + switch (PAddr) { + case 0x04700000: RI_MODE_REG = Value; break; + case 0x04700004: RI_CONFIG_REG = Value; break; + case 0x04700008: RI_CURRENT_LOAD_REG = Value; break; + case 0x0470000C: RI_SELECT_REG = Value; break; + case 0x04700010: RI_REFRESH_REG = Value; break; + case 0x04700014: RI_LATENCY_REG = Value; break; + case 0x04700018: RI_RERROR_REG = Value; break; + case 0x0470001C: RI_WERROR_REG = Value; break; + default: + return 0; + } + break; + case 0x04800000: + switch (PAddr) { + case 0x04800000: SI_DRAM_ADDR_REG = Value; break; + case 0x04800004: + SI_PIF_ADDR_RD64B_REG = Value; + SI_DMA_READ (state); + break; + case 0x04800010: + SI_PIF_ADDR_WR64B_REG = Value; + SI_DMA_WRITE(state); + break; + case 0x04800018: + MI_INTR_REG &= ~MI_INTR_SI; + SI_STATUS_REG &= ~SI_STATUS_INTERRUPT; + CheckInterrupts(state); + break; + default: + return 0; + } + break; + case 0x08000000: + if (PAddr != 0x08010000) { return 0; } + break; + case 0x1FC00000: + if (PAddr < 0x1FC007C0) { + return 0; + } else if (PAddr < 0x1FC00800) { + + if (PAddr == 0x1FC007FC) { + PifRamWrite(state); + } + return 1; + } + return 0; + break; + default: + return 0; + break; + } + return 1; +} + +uint32_t r4300i_SW_VAddr ( usf_state_t * state, uint32_t VAddr, uint32_t Value ) { + uintptr_t address = (state->TLB_Map[VAddr >> 12] + VAddr); + + if (state->TLB_Map[VAddr >> 12] == 0) { return 0; } + + if((address - (uintptr_t)state->RDRAM) > state->RdramSize) { + address = address - (uintptr_t)state->RDRAM; + return r4300i_SW_NonMemory(state, address, Value); + } + *(uint32_t *)address = Value; + return 1; +} diff --git a/Frameworks/lazyusf/lazyusf/memory.h b/Frameworks/lazyusf/lazyusf/memory.h new file mode 100644 index 000000000..e785c844b --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/memory.h @@ -0,0 +1,58 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#define LargeCompileBufferSize 0x03200000 +#define NormalCompileBufferSize 0x01500000 + +#define RSP_RECOMPMEM_SIZE 0x400000 +#define RSP_SECRECOMPMEM_SIZE 0x200000 + +#define ROM_IN_MAPSPACE + +/* Memory Control */ +int Allocate_Memory ( void * ); +void Release_Memory ( usf_state_t * ); +int PreAllocate_Memory( usf_state_t * ); + +/* CPU memory functions */ +//int r4300i_Command_MemoryFilter ( uint32_t dwExptCode, LPEXCEPTION_POINTERS lpEP ); +//int r4300i_CPU_MemoryFilter ( uint32_t dwExptCode, LPEXCEPTION_POINTERS lpEP ); +int32_t r4300i_LB_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t * Value, uint32_t SignExtend ); +uint32_t r4300i_LB_VAddr ( usf_state_t *, uint32_t VAddr, uint8_t * Value ); +uint32_t r4300i_LD_VAddr ( usf_state_t *, uint32_t VAddr, uint64_t * Value ); +int32_t r4300i_LH_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t * Value, int32_t SignExtend ); +uint32_t r4300i_LH_VAddr ( usf_state_t *, uint32_t VAddr, uint16_t * Value ); +int32_t r4300i_LW_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t * Value ); +void r4300i_LW_PAddr ( usf_state_t *, uint32_t PAddr, uint32_t * Value ); +uint32_t r4300i_LW_VAddr ( usf_state_t *, uint32_t VAddr, uint32_t * Value ); +int32_t r4300i_SB_NonMemory ( usf_state_t *, uint32_t PAddr, uint8_t Value ); +uint32_t r4300i_SB_VAddr ( usf_state_t *, uint32_t VAddr, uint8_t Value ); +uint32_t r4300i_SD_VAddr ( usf_state_t *, uint32_t VAddr, uint64_t Value ); +int32_t r4300i_SH_NonMemory ( usf_state_t *, uint32_t PAddr, uint16_t Value ); +uint32_t r4300i_SH_VAddr ( usf_state_t *, uint32_t VAddr, uint16_t Value ); +int32_t r4300i_SW_NonMemory ( usf_state_t *, uint32_t PAddr, uint32_t Value ); +uint32_t r4300i_SW_VAddr ( usf_state_t *, uint32_t VAddr, uint32_t Value ); + +uint8_t * PageROM(usf_state_t *, uint32_t addr); diff --git a/Frameworks/lazyusf/lazyusf/opcode.h b/Frameworks/lazyusf/lazyusf/opcode.h new file mode 100644 index 000000000..cf2fe39ef --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/opcode.h @@ -0,0 +1,274 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#ifndef __OpCode +#define __OpCode + +#include "types.h" + +typedef struct { + union { + + uint32_t Hex; + uint8_t Ascii[4]; + + struct { + unsigned offset : 16; + unsigned rt : 5; + unsigned rs : 5; + unsigned op : 6; + }; + + struct { + unsigned immediate : 16; + unsigned : 5; + unsigned base : 5; + unsigned : 6; + }; + + struct { + unsigned target : 26; + unsigned : 6; + }; + + struct { + unsigned funct : 6; + unsigned sa : 5; + unsigned rd : 5; + unsigned : 5; + unsigned : 5; + unsigned : 6; + }; + + struct { + unsigned : 6; + unsigned fd : 5; + unsigned fs : 5; + unsigned ft : 5; + unsigned fmt : 5; + unsigned : 6; + }; + }; + +} OPCODE; + +//R4300i OpCodes +#define R4300i_SPECIAL 0 +#define R4300i_REGIMM 1 +#define R4300i_J 2 +#define R4300i_JAL 3 +#define R4300i_BEQ 4 +#define R4300i_BNE 5 +#define R4300i_BLEZ 6 +#define R4300i_BGTZ 7 +#define R4300i_ADDI 8 +#define R4300i_ADDIU 9 +#define R4300i_SLTI 10 +#define R4300i_SLTIU 11 +#define R4300i_ANDI 12 +#define R4300i_ORI 13 +#define R4300i_XORI 14 +#define R4300i_LUI 15 +#define R4300i_CP0 16 +#define R4300i_CP1 17 +#define R4300i_BEQL 20 +#define R4300i_BNEL 21 +#define R4300i_BLEZL 22 +#define R4300i_BGTZL 23 +#define R4300i_DADDI 24 +#define R4300i_DADDIU 25 +#define R4300i_LDL 26 +#define R4300i_LDR 27 +#define R4300i_LB 32 +#define R4300i_LH 33 +#define R4300i_LWL 34 +#define R4300i_LW 35 +#define R4300i_LBU 36 +#define R4300i_LHU 37 +#define R4300i_LWR 38 +#define R4300i_LWU 39 +#define R4300i_SB 40 +#define R4300i_SH 41 +#define R4300i_SWL 42 +#define R4300i_SW 43 +#define R4300i_SDL 44 +#define R4300i_SDR 45 +#define R4300i_SWR 46 +#define R4300i_CACHE 47 +#define R4300i_LL 48 +#define R4300i_LWC1 49 +#define R4300i_LWC2 0x32 +#define R4300i_LLD 0x34 +#define R4300i_LDC1 53 +#define R4300i_LDC2 0x36 +#define R4300i_LD 55 +#define R4300i_SC 0x38 +#define R4300i_SWC1 57 +#define R4300i_SWC2 0x3A +#define R4300i_SCD 0x3C +#define R4300i_SDC1 61 +#define R4300i_SDC2 62 +#define R4300i_SD 63 + +/* R4300i Special opcodes */ +#define R4300i_SPECIAL_SLL 0 +#define R4300i_SPECIAL_SRL 2 +#define R4300i_SPECIAL_SRA 3 +#define R4300i_SPECIAL_SLLV 4 +#define R4300i_SPECIAL_SRLV 6 +#define R4300i_SPECIAL_SRAV 7 +#define R4300i_SPECIAL_JR 8 +#define R4300i_SPECIAL_JALR 9 +#define R4300i_SPECIAL_SYSCALL 12 +#define R4300i_SPECIAL_BREAK 13 +#define R4300i_SPECIAL_SYNC 15 +#define R4300i_SPECIAL_MFHI 16 +#define R4300i_SPECIAL_MTHI 17 +#define R4300i_SPECIAL_MFLO 18 +#define R4300i_SPECIAL_MTLO 19 +#define R4300i_SPECIAL_DSLLV 20 +#define R4300i_SPECIAL_DSRLV 22 +#define R4300i_SPECIAL_DSRAV 23 +#define R4300i_SPECIAL_MULT 24 +#define R4300i_SPECIAL_MULTU 25 +#define R4300i_SPECIAL_DIV 26 +#define R4300i_SPECIAL_DIVU 27 +#define R4300i_SPECIAL_DMULT 28 +#define R4300i_SPECIAL_DMULTU 29 +#define R4300i_SPECIAL_DDIV 30 +#define R4300i_SPECIAL_DDIVU 31 +#define R4300i_SPECIAL_ADD 32 +#define R4300i_SPECIAL_ADDU 33 +#define R4300i_SPECIAL_SUB 34 +#define R4300i_SPECIAL_SUBU 35 +#define R4300i_SPECIAL_AND 36 +#define R4300i_SPECIAL_OR 37 +#define R4300i_SPECIAL_XOR 38 +#define R4300i_SPECIAL_NOR 39 +#define R4300i_SPECIAL_SLT 42 +#define R4300i_SPECIAL_SLTU 43 +#define R4300i_SPECIAL_DADD 44 +#define R4300i_SPECIAL_DADDU 45 +#define R4300i_SPECIAL_DSUB 46 +#define R4300i_SPECIAL_DSUBU 47 +#define R4300i_SPECIAL_TGE 48 +#define R4300i_SPECIAL_TGEU 49 +#define R4300i_SPECIAL_TLT 50 +#define R4300i_SPECIAL_TLTU 51 +#define R4300i_SPECIAL_TEQ 52 +#define R4300i_SPECIAL_TNE 54 +#define R4300i_SPECIAL_DSLL 56 +#define R4300i_SPECIAL_DSRL 58 +#define R4300i_SPECIAL_DSRA 59 +#define R4300i_SPECIAL_DSLL32 60 +#define R4300i_SPECIAL_DSRL32 62 +#define R4300i_SPECIAL_DSRA32 63 + +/* R4300i RegImm opcodes */ +#define R4300i_REGIMM_BLTZ 0 +#define R4300i_REGIMM_BGEZ 1 +#define R4300i_REGIMM_BLTZL 2 +#define R4300i_REGIMM_BGEZL 3 +#define R4300i_REGIMM_TGEI 0x08 +#define R4300i_REGIMM_TGEIU 0x09 +#define R4300i_REGIMM_TLTI 0x0A +#define R4300i_REGIMM_TLTIU 0x0B +#define R4300i_REGIMM_TEQI 0x0C +#define R4300i_REGIMM_TNEI 0x0E +#define R4300i_REGIMM_BLTZAL 0x10 +#define R4300i_REGIMM_BGEZAL 17 +#define R4300i_REGIMM_BLTZALL 0x12 +#define R4300i_REGIMM_BGEZALL 0x13 + +/* R4300i COP0 opcodes */ +#define R4300i_COP0_MF 0 +#define R4300i_COP0_MT 4 + +/* R4300i COP0 CO opcodes */ +#define R4300i_COP0_CO_TLBR 1 +#define R4300i_COP0_CO_TLBWI 2 +#define R4300i_COP0_CO_TLBWR 6 +#define R4300i_COP0_CO_TLBP 8 +#define R4300i_COP0_CO_ERET 24 + +/* R4300i COP1 opcodes */ +#define R4300i_COP1_MF 0 +#define R4300i_COP1_DMF 1 +#define R4300i_COP1_CF 2 +#define R4300i_COP1_MT 4 +#define R4300i_COP1_DMT 5 +#define R4300i_COP1_CT 6 +#define R4300i_COP1_BC 8 +#define R4300i_COP1_S 16 +#define R4300i_COP1_D 17 +#define R4300i_COP1_W 20 +#define R4300i_COP1_L 21 + +/* R4300i COP1 BC opcodes */ +#define R4300i_COP1_BC_BCF 0 +#define R4300i_COP1_BC_BCT 1 +#define R4300i_COP1_BC_BCFL 2 +#define R4300i_COP1_BC_BCTL 3 + +#define R4300i_COP1_FUNCT_ADD 0 +#define R4300i_COP1_FUNCT_SUB 1 +#define R4300i_COP1_FUNCT_MUL 2 +#define R4300i_COP1_FUNCT_DIV 3 +#define R4300i_COP1_FUNCT_SQRT 4 +#define R4300i_COP1_FUNCT_ABS 5 +#define R4300i_COP1_FUNCT_MOV 6 +#define R4300i_COP1_FUNCT_NEG 7 +#define R4300i_COP1_FUNCT_ROUND_L 8 +#define R4300i_COP1_FUNCT_TRUNC_L 9 +#define R4300i_COP1_FUNCT_CEIL_L 10 +#define R4300i_COP1_FUNCT_FLOOR_L 11 +#define R4300i_COP1_FUNCT_ROUND_W 12 +#define R4300i_COP1_FUNCT_TRUNC_W 13 +#define R4300i_COP1_FUNCT_CEIL_W 14 +#define R4300i_COP1_FUNCT_FLOOR_W 15 +#define R4300i_COP1_FUNCT_CVT_S 32 +#define R4300i_COP1_FUNCT_CVT_D 33 +#define R4300i_COP1_FUNCT_CVT_W 36 +#define R4300i_COP1_FUNCT_CVT_L 37 +#define R4300i_COP1_FUNCT_C_F 48 +#define R4300i_COP1_FUNCT_C_UN 49 +#define R4300i_COP1_FUNCT_C_EQ 50 +#define R4300i_COP1_FUNCT_C_UEQ 51 +#define R4300i_COP1_FUNCT_C_OLT 52 +#define R4300i_COP1_FUNCT_C_ULT 53 +#define R4300i_COP1_FUNCT_C_OLE 54 +#define R4300i_COP1_FUNCT_C_ULE 55 +#define R4300i_COP1_FUNCT_C_SF 56 +#define R4300i_COP1_FUNCT_C_NGLE 57 +#define R4300i_COP1_FUNCT_C_SEQ 58 +#define R4300i_COP1_FUNCT_C_NGL 59 +#define R4300i_COP1_FUNCT_C_LT 60 +#define R4300i_COP1_FUNCT_C_NGE 61 +#define R4300i_COP1_FUNCT_C_LE 62 +#define R4300i_COP1_FUNCT_C_NGT 63 + +#endif + + diff --git a/Frameworks/lazyusf/lazyusf/pif.c b/Frameworks/lazyusf/lazyusf/pif.c new file mode 100644 index 000000000..c8e6dfce3 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/pif.c @@ -0,0 +1,97 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#include "usf.h" +#include "main.h" +#include "cpu.h" + +#include "usf_internal.h" + +// Skeletal support so USFs that read the controller won't fail (bad practice, though) + +void ProcessControllerCommand ( usf_state_t * state, int32_t Control, uint8_t * Command); + +void PifRamRead (usf_state_t * state) { + int32_t Channel, CurPos; + + Channel = 0; + CurPos = 0; + + do { + switch(state->PIF_Ram[CurPos]) { + case 0x00: + Channel += 1; + if (Channel > 6) { CurPos = 0x40; } + break; + case 0xFE: CurPos = 0x40; break; + case 0xFF: break; + case 0xB4: case 0x56: case 0xB8: break; /* ??? */ + default: + if ((state->PIF_Ram[CurPos] & 0xC0) == 0) { + CurPos += state->PIF_Ram[CurPos] + (state->PIF_Ram[CurPos + 1] & 0x3F) + 1; + Channel += 1; + } else { + CurPos = 0x40; + } + break; + } + CurPos += 1; + } while( CurPos < 0x40 ); +} + +void PifRamWrite (usf_state_t * state) { + int Channel, CurPos; + + Channel = 0; + + for (CurPos = 0; CurPos < 0x40; CurPos++){ + switch(state->PIF_Ram[CurPos]) { + case 0x00: + Channel += 1; + if (Channel > 6) { CurPos = 0x40; } + break; + case 0xFE: CurPos = 0x40; break; + case 0xFF: break; + case 0xB4: case 0x56: case 0xB8: break; /* ??? */ + default: + if ((state->PIF_Ram[CurPos] & 0xC0) == 0) { + if (Channel < 4) { + ProcessControllerCommand(state,Channel,&state->PIF_Ram[CurPos]); + } + CurPos += state->PIF_Ram[CurPos] + (state->PIF_Ram[CurPos + 1] & 0x3F) + 1; + Channel += 1; + } else + CurPos = 0x40; + + break; + } + } + state->PIF_Ram[0x3F] = 0; +} + +// always return failure +void ProcessControllerCommand ( usf_state_t * state, int32_t Control, uint8_t * Command) { + Command[1] |= 0x80; +} diff --git a/Frameworks/lazyusf/lazyusf/pif.h b/Frameworks/lazyusf/lazyusf/pif.h new file mode 100644 index 000000000..d46ec4de6 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/pif.h @@ -0,0 +1,29 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +extern uint8_t *PIF_Ram; + +void PifRamWrite ( usf_state_t * ); +void PifRamRead ( usf_state_t * ); diff --git a/Frameworks/lazyusf/lazyusf/registers.c b/Frameworks/lazyusf/lazyusf/registers.c new file mode 100644 index 000000000..870542cd7 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/registers.c @@ -0,0 +1,145 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +// #ifdef EXT_REGS + +#include "usf.h" + +#include "main.h" +#include "cpu.h" +#include "types.h" + +#include "usf_internal.h" + +void SetupRegisters(usf_state_t * state, N64_REGISTERS * n64_Registers) { + state->PROGRAM_COUNTER = n64_Registers->PROGRAM_COUNTER; + state->HI.DW = n64_Registers->HI.DW; + state->LO.DW = n64_Registers->LO.DW; + state->CP0 = n64_Registers->CP0; + state->GPR = n64_Registers->GPR; + state->FPR = n64_Registers->FPR; + state->FPCR = n64_Registers->FPCR; + state->RegRDRAM = n64_Registers->RDRAM; + state->RegSP = n64_Registers->SP; + state->RegDPC = n64_Registers->DPC; + state->RegMI = n64_Registers->MI; + state->RegVI = n64_Registers->VI; + state->RegAI = n64_Registers->AI; + state->RegPI = n64_Registers->PI; + state->RegRI = n64_Registers->RI; + state->RegSI = n64_Registers->SI; + state->PIF_Ram = n64_Registers->PIF_Ram; +} + +void ChangeMiIntrMask (usf_state_t * state) { + if ( ( state->RegModValue & MI_INTR_MASK_CLR_SP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP; } + if ( ( state->RegModValue & MI_INTR_MASK_SET_SP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SP; } + if ( ( state->RegModValue & MI_INTR_MASK_CLR_SI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI; } + if ( ( state->RegModValue & MI_INTR_MASK_SET_SI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SI; } + if ( ( state->RegModValue & MI_INTR_MASK_CLR_AI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI; } + if ( ( state->RegModValue & MI_INTR_MASK_SET_AI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_AI; } + if ( ( state->RegModValue & MI_INTR_MASK_CLR_VI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI; } + if ( ( state->RegModValue & MI_INTR_MASK_SET_VI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_VI; } + if ( ( state->RegModValue & MI_INTR_MASK_CLR_PI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI; } + if ( ( state->RegModValue & MI_INTR_MASK_SET_PI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_PI; } + if ( ( state->RegModValue & MI_INTR_MASK_CLR_DP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP; } + if ( ( state->RegModValue & MI_INTR_MASK_SET_DP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_DP; } +} + +void ChangeMiModeReg (usf_state_t * state) { + MI_MODE_REG &= ~0x7F; + MI_MODE_REG |= (state->RegModValue & 0x7F); + if ( ( state->RegModValue & MI_CLR_INIT ) != 0 ) { MI_MODE_REG &= ~MI_MODE_INIT; } + if ( ( state->RegModValue & MI_SET_INIT ) != 0 ) { MI_MODE_REG |= MI_MODE_INIT; } + if ( ( state->RegModValue & MI_CLR_EBUS ) != 0 ) { MI_MODE_REG &= ~MI_MODE_EBUS; } + if ( ( state->RegModValue & MI_SET_EBUS ) != 0 ) { MI_MODE_REG |= MI_MODE_EBUS; } + if ( ( state->RegModValue & MI_CLR_DP_INTR ) != 0 ) { MI_INTR_REG &= ~MI_INTR_DP; } + if ( ( state->RegModValue & MI_CLR_RDRAM ) != 0 ) { MI_MODE_REG &= ~MI_MODE_RDRAM; } + if ( ( state->RegModValue & MI_SET_RDRAM ) != 0 ) { MI_MODE_REG |= MI_MODE_RDRAM; } +} + +void ChangeSpStatus (usf_state_t * state) { + if ( ( state->RegModValue & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; } + if ( ( state->RegModValue & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; } + if ( ( state->RegModValue & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; } + if ( ( state->RegModValue & SP_CLR_INTR ) != 0) { + MI_INTR_REG &= ~MI_INTR_SP; + CheckInterrupts(state); + } + + if ( ( state->RegModValue & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; } + if ( ( state->RegModValue & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; } + if ( ( state->RegModValue & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; } + if ( ( state->RegModValue & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; } + if ( ( state->RegModValue & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; } + if ( ( state->RegModValue & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; } + if ( ( state->RegModValue & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; } + if ( ( state->RegModValue & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; } + if ( ( state->RegModValue & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; } + if ( ( state->RegModValue & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; } + if ( ( state->RegModValue & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; } + if ( ( state->RegModValue & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; } + if ( ( state->RegModValue & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; } + if ( ( state->RegModValue & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; } + if ( ( state->RegModValue & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; } + if ( ( state->RegModValue & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; } + if ( ( state->RegModValue & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; } + if ( ( state->RegModValue & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; } + if ( ( state->RegModValue & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; } + if ( ( state->RegModValue & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; } + + RunRsp(state); + +} + +void UpdateCurrentHalfLine (usf_state_t * state) { + if (state->Timers->Timer < 0) { + state->HalfLine = 0; + return; + } + state->HalfLine = (state->Timers->Timer / 1500); + state->HalfLine &= ~1; + state->HalfLine += state->ViFieldNumber; +} + +void SetFpuLocations (usf_state_t * state) { + int count; + + if ((STATUS_REGISTER & STATUS_FR) == 0) { + for (count = 0; count < 32; count ++) { + state->FPRFloatLocation[count] = (void *)(&state->FPR[count >> 1].W[count & 1]); + //state->FPRDoubleLocation[count] = state->FPRFloatLocation[count]; + state->FPRDoubleLocation[count] = (void *)(&state->FPR[count >> 1].DW); + } + } else { + for (count = 0; count < 32; count ++) { + state->FPRFloatLocation[count] = (void *)(&state->FPR[count].W[1]); + //state->FPRFloatLocation[count] = (void *)(&state->FPR[count].W[1]); + //state->FPRDoubleLocation[count] = state->FPRFloatLocation[count]; + state->FPRDoubleLocation[count] = (void *)(&state->FPR[count].DW); + } + } +} diff --git a/Frameworks/lazyusf/lazyusf/registers.h b/Frameworks/lazyusf/lazyusf/registers.h new file mode 100644 index 000000000..6f4f205b4 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/registers.h @@ -0,0 +1,378 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#ifndef REGISTERS_H +#define REGISTERS_H + +#include "types.h" + +#define INDEX_REGISTER state->CP0[0] +#define RANDOM_REGISTER state->CP0[1] +#define ENTRYLO0_REGISTER state->CP0[2] +#define ENTRYLO1_REGISTER state->CP0[3] +#define CONTEXT_REGISTER state->CP0[4] +#define PAGE_MASK_REGISTER state->CP0[5] +#define WIRED_REGISTER state->CP0[6] +#define BAD_VADDR_REGISTER state->CP0[8] +#define COUNT_REGISTER state->CP0[9] +#define ENTRYHI_REGISTER state->CP0[10] +#define COMPARE_REGISTER state->CP0[11] +#define STATUS_REGISTER state->CP0[12] +#define CAUSE_REGISTER state->CP0[13] +#define EPC_REGISTER state->CP0[14] +#define CONFIG_REGISTER state->CP0[16] +#define TAGLO_REGISTER state->CP0[28] +#define TAGHI_REGISTER state->CP0[29] +#define ERROREPC_REGISTER state->CP0[30] +#define FAKE_CAUSE_REGISTER state->CP0[32] + +#define COMPARE_REGISTER_NO 11 +#define STATUS_REGISTER_NO 12 +#define CAUSE_REGISTER_NO 13 + +#define REVISION_REGISTER state->FPCR[0] +#define FSTATUS_REGISTER state->FPCR[31] + +#define GPR_S0 state->GPR[16] +#define GPR_S1 state->GPR[17] +#define GPR_S2 state->GPR[18] +#define GPR_S3 state->GPR[19] +#define GPR_S4 state->GPR[20] +#define GPR_S5 state->GPR[21] +#define GPR_S6 state->GPR[22] +#define GPR_S7 state->GPR[23] +#define GPR_SP state->GPR[29] +#define GPR_RA state->GPR[31] + +#define RDRAM_CONFIG_REG state->RegRDRAM[0] +#define RDRAM_DEVICE_TYPE_REG state->RegRDRAM[0] +#define RDRAM_DEVICE_ID_REG state->RegRDRAM[1] +#define RDRAM_DELAY_REG state->RegRDRAM[2] +#define RDRAM_MODE_REG state->RegRDRAM[3] +#define RDRAM_REF_INTERVAL_REG state->RegRDRAM[4] +#define RDRAM_REF_ROW_REG state->RegRDRAM[5] +#define RDRAM_RAS_INTERVAL_REG state->RegRDRAM[6] +#define RDRAM_MIN_INTERVAL_REG state->RegRDRAM[7] +#define RDRAM_ADDR_SELECT_REG state->RegRDRAM[8] +#define RDRAM_DEVICE_MANUF_REG state->RegRDRAM[9] + +#define SP_MEM_ADDR_REG state->RegSP[0] +#define SP_DRAM_ADDR_REG state->RegSP[1] +#define SP_RD_LEN_REG state->RegSP[2] +#define SP_WR_LEN_REG state->RegSP[3] +#define SP_STATUS_REG state->RegSP[4] +#define SP_DMA_FULL_REG state->RegSP[5] +#define SP_DMA_BUSY_REG state->RegSP[6] +#define SP_SEMAPHORE_REG state->RegSP[7] +#define SP_PC_REG state->RegSP[8] +#define SP_IBIST_REG state->RegSP[9] + +#define DPC_START_REG state->RegDPC[0] +#define DPC_END_REG state->RegDPC[1] +#define DPC_CURRENT_REG state->RegDPC[2] +#define DPC_STATUS_REG state->RegDPC[3] +#define DPC_CLOCK_REG state->RegDPC[4] +#define DPC_BUFBUSY_REG state->RegDPC[5] +#define DPC_PIPEBUSY_REG state->RegDPC[6] +#define DPC_TMEM_REG state->RegDPC[7] + +#define MI_INIT_MODE_REG state->RegMI[0] +#define MI_MODE_REG state->RegMI[0] +#define MI_VERSION_REG state->RegMI[1] +#define MI_NOOP_REG state->RegMI[1] +#define MI_INTR_REG state->RegMI[2] +#define MI_INTR_MASK_REG state->RegMI[3] + +#define VI_STATUS_REG state->RegVI[0] +#define VI_CONTROL_REG state->RegVI[0] +#define VI_ORIGIN_REG state->RegVI[1] +#define VI_DRAM_ADDR_REG state->RegVI[1] +#define VI_WIDTH_REG state->RegVI[2] +#define VI_H_WIDTH_REG state->RegVI[2] +#define VI_INTR_REG state->RegVI[3] +#define VI_V_INTR_REG state->RegVI[3] +#define VI_CURRENT_REG state->RegVI[4] +#define VI_V_CURRENT_LINE_REG state->RegVI[4] +#define VI_BURST_REG state->RegVI[5] +#define VI_TIMING_REG state->RegVI[5] +#define VI_V_SYNC_REG state->RegVI[6] +#define VI_H_SYNC_REG state->RegVI[7] +#define VI_LEAP_REG state->RegVI[8] +#define VI_H_SYNC_LEAP_REG state->RegVI[8] +#define VI_H_START_REG state->RegVI[9] +#define VI_H_VIDEO_REG state->RegVI[9] +#define VI_V_START_REG state->RegVI[10] +#define VI_V_VIDEO_REG state->RegVI[10] +#define VI_V_BURST_REG state->RegVI[11] +#define VI_X_SCALE_REG state->RegVI[12] +#define VI_Y_SCALE_REG state->RegVI[13] + +#define AI_DRAM_ADDR_REG state->RegAI[0] +#define AI_LEN_REG state->RegAI[1] +#define AI_CONTROL_REG state->RegAI[2] +#define AI_STATUS_REG state->RegAI[3] +#define AI_DACRATE_REG state->RegAI[4] +#define AI_BITRATE_REG state->RegAI[5] + +#define PI_DRAM_ADDR_REG state->RegPI[0] +#define PI_CART_ADDR_REG state->RegPI[1] +#define PI_RD_LEN_REG state->RegPI[2] +#define PI_WR_LEN_REG state->RegPI[3] +#define PI_STATUS_REG state->RegPI[4] +#define PI_BSD_DOM1_LAT_REG state->RegPI[5] +#define PI_DOMAIN1_REG state->RegPI[5] +#define PI_BSD_DOM1_PWD_REG state->RegPI[6] +#define PI_BSD_DOM1_PGS_REG state->RegPI[7] +#define PI_BSD_DOM1_RLS_REG state->RegPI[8] +#define PI_BSD_DOM2_LAT_REG state->RegPI[9] +#define PI_DOMAIN2_REG state->RegPI[9] +#define PI_BSD_DOM2_PWD_REG state->RegPI[10] +#define PI_BSD_DOM2_PGS_REG state->RegPI[11] +#define PI_BSD_DOM2_RLS_REG state->RegPI[12] + +#define RI_MODE_REG state->RegRI[0] +#define RI_CONFIG_REG state->RegRI[1] +#define RI_CURRENT_LOAD_REG state->RegRI[2] +#define RI_SELECT_REG state->RegRI[3] +#define RI_COUNT_REG state->RegRI[4] +#define RI_REFRESH_REG state->RegRI[4] +#define RI_LATENCY_REG state->RegRI[5] +#define RI_RERROR_REG state->RegRI[6] +#define RI_WERROR_REG state->RegRI[7] + +#define SI_DRAM_ADDR_REG state->RegSI[0] +#define SI_PIF_ADDR_RD64B_REG state->RegSI[1] +#define SI_PIF_ADDR_WR64B_REG state->RegSI[2] +#define SI_STATUS_REG state->RegSI[3] + +#define STATUS_IE 0x00000001 +#define STATUS_EXL 0x00000002 +#define STATUS_ERL 0x00000004 +#define STATUS_IP0 0x00000100 +#define STATUS_IP1 0x00000200 +#define STATUS_IP2 0x00000400 +#define STATUS_IP3 0x00000800 +#define STATUS_IP4 0x00001000 +#define STATUS_IP5 0x00002000 +#define STATUS_IP6 0x00004000 +#define STATUS_IP7 0x00008000 +#define STATUS_BEV 0x00400000 +#define STATUS_FR 0x04000000 +#define STATUS_CU0 0x10000000 +#define STATUS_CU1 0x20000000 + +#define CAUSE_EXC_CODE 0xFF +#define CAUSE_IP0 0x100 +#define CAUSE_IP1 0x200 +#define CAUSE_IP2 0x400 +#define CAUSE_IP3 0x800 +#define CAUSE_IP4 0x1000 +#define CAUSE_IP5 0x2000 +#define CAUSE_IP6 0x4000 +#define CAUSE_IP7 0x8000 +#define CAUSE_BD 0x80000000 + +#define SP_CLR_HALT 0x00001 /* Bit 0: clear halt */ +#define SP_SET_HALT 0x00002 /* Bit 1: set halt */ +#define SP_CLR_BROKE 0x00004 /* Bit 2: clear broke */ +#define SP_CLR_INTR 0x00008 /* Bit 3: clear intr */ +#define SP_SET_INTR 0x00010 /* Bit 4: set intr */ +#define SP_CLR_SSTEP 0x00020 /* Bit 5: clear sstep */ +#define SP_SET_SSTEP 0x00040 /* Bit 6: set sstep */ +#define SP_CLR_INTR_BREAK 0x00080 /* Bit 7: clear intr on break */ +#define SP_SET_INTR_BREAK 0x00100 /* Bit 8: set intr on break */ +#define SP_CLR_SIG0 0x00200 /* Bit 9: clear signal 0 */ +#define SP_SET_SIG0 0x00400 /* Bit 10: set signal 0 */ +#define SP_CLR_SIG1 0x00800 /* Bit 11: clear signal 1 */ +#define SP_SET_SIG1 0x01000 /* Bit 12: set signal 1 */ +#define SP_CLR_SIG2 0x02000 /* Bit 13: clear signal 2 */ +#define SP_SET_SIG2 0x04000 /* Bit 14: set signal 2 */ +#define SP_CLR_SIG3 0x08000 /* Bit 15: clear signal 3 */ +#define SP_SET_SIG3 0x10000 /* Bit 16: set signal 3 */ +#define SP_CLR_SIG4 0x20000 /* Bit 17: clear signal 4 */ +#define SP_SET_SIG4 0x40000 /* Bit 18: set signal 4 */ +#define SP_CLR_SIG5 0x80000 /* Bit 19: clear signal 5 */ +#define SP_SET_SIG5 0x100000 /* Bit 20: set signal 5 */ +#define SP_CLR_SIG6 0x200000 /* Bit 21: clear signal 6 */ +#define SP_SET_SIG6 0x400000 /* Bit 22: set signal 6 */ +#define SP_CLR_SIG7 0x800000 /* Bit 23: clear signal 7 */ +#define SP_SET_SIG7 0x1000000 /* Bit 24: set signal 7 */ + +#define SP_STATUS_HALT 0x001 /* Bit 0: halt */ +#define SP_STATUS_BROKE 0x002 /* Bit 1: broke */ +#define SP_STATUS_DMA_BUSY 0x004 /* Bit 2: dma busy */ +#define SP_STATUS_DMA_FULL 0x008 /* Bit 3: dma full */ +#define SP_STATUS_IO_FULL 0x010 /* Bit 4: io full */ +#define SP_STATUS_SSTEP 0x020 /* Bit 5: single step */ +#define SP_STATUS_INTR_BREAK 0x040 /* Bit 6: interrupt on break */ +#define SP_STATUS_SIG0 0x080 /* Bit 7: signal 0 set */ +#define SP_STATUS_SIG1 0x100 /* Bit 8: signal 1 set */ +#define SP_STATUS_SIG2 0x200 /* Bit 9: signal 2 set */ +#define SP_STATUS_SIG3 0x400 /* Bit 10: signal 3 set */ +#define SP_STATUS_SIG4 0x800 /* Bit 11: signal 4 set */ +#define SP_STATUS_SIG5 0x1000 /* Bit 12: signal 5 set */ +#define SP_STATUS_SIG6 0x2000 /* Bit 13: signal 6 set */ +#define SP_STATUS_SIG7 0x4000 /* Bit 14: signal 7 set */ + +#define DPC_CLR_XBUS_DMEM_DMA 0x0001 /* Bit 0: clear xbus_dmem_dma */ +#define DPC_SET_XBUS_DMEM_DMA 0x0002 /* Bit 1: set xbus_dmem_dma */ +#define DPC_CLR_FREEZE 0x0004 /* Bit 2: clear freeze */ +#define DPC_SET_FREEZE 0x0008 /* Bit 3: set freeze */ +#define DPC_CLR_FLUSH 0x0010 /* Bit 4: clear flush */ +#define DPC_SET_FLUSH 0x0020 /* Bit 5: set flush */ +#define DPC_CLR_TMEM_CTR 0x0040 /* Bit 6: clear tmem ctr */ +#define DPC_CLR_PIPE_CTR 0x0080 /* Bit 7: clear pipe ctr */ +#define DPC_CLR_CMD_CTR 0x0100 /* Bit 8: clear cmd ctr */ +#define DPC_CLR_CLOCK_CTR 0x0200 /* Bit 9: clear clock ctr */ + +#define DPC_STATUS_XBUS_DMEM_DMA 0x001 /* Bit 0: xbus_dmem_dma */ +#define DPC_STATUS_FREEZE 0x002 /* Bit 1: freeze */ +#define DPC_STATUS_FLUSH 0x004 /* Bit 2: flush */ +#define DPC_STATUS_START_GCLK 0x008 /* Bit 3: start gclk */ +#define DPC_STATUS_TMEM_BUSY 0x010 /* Bit 4: tmem busy */ +#define DPC_STATUS_PIPE_BUSY 0x020 /* Bit 5: pipe busy */ +#define DPC_STATUS_CMD_BUSY 0x040 /* Bit 6: cmd busy */ +#define DPC_STATUS_CBUF_READY 0x080 /* Bit 7: cbuf ready */ +#define DPC_STATUS_DMA_BUSY 0x100 /* Bit 8: dma busy */ +#define DPC_STATUS_END_VALID 0x200 /* Bit 9: end valid */ +#define DPC_STATUS_START_VALID 0x400 /* Bit 10: start valid */ + +#define MI_CLR_INIT 0x0080 /* Bit 7: clear init mode */ +#define MI_SET_INIT 0x0100 /* Bit 8: set init mode */ +#define MI_CLR_EBUS 0x0200 /* Bit 9: clear ebus test */ +#define MI_SET_EBUS 0x0400 /* Bit 10: set ebus test mode */ +#define MI_CLR_DP_INTR 0x0800 /* Bit 11: clear dp interrupt */ +#define MI_CLR_RDRAM 0x1000 /* Bit 12: clear RDRAM reg */ +#define MI_SET_RDRAM 0x2000 /* Bit 13: set RDRAM reg mode */ + +#define MI_MODE_INIT 0x0080 /* Bit 7: init mode */ +#define MI_MODE_EBUS 0x0100 /* Bit 8: ebus test mode */ +#define MI_MODE_RDRAM 0x0200 /* Bit 9: RDRAM reg mode */ + +#define MI_INTR_MASK_CLR_SP 0x0001 /* Bit 0: clear SP mask */ +#define MI_INTR_MASK_SET_SP 0x0002 /* Bit 1: set SP mask */ +#define MI_INTR_MASK_CLR_SI 0x0004 /* Bit 2: clear SI mask */ +#define MI_INTR_MASK_SET_SI 0x0008 /* Bit 3: set SI mask */ +#define MI_INTR_MASK_CLR_AI 0x0010 /* Bit 4: clear AI mask */ +#define MI_INTR_MASK_SET_AI 0x0020 /* Bit 5: set AI mask */ +#define MI_INTR_MASK_CLR_VI 0x0040 /* Bit 6: clear VI mask */ +#define MI_INTR_MASK_SET_VI 0x0080 /* Bit 7: set VI mask */ +#define MI_INTR_MASK_CLR_PI 0x0100 /* Bit 8: clear PI mask */ +#define MI_INTR_MASK_SET_PI 0x0200 /* Bit 9: set PI mask */ +#define MI_INTR_MASK_CLR_DP 0x0400 /* Bit 10: clear DP mask */ +#define MI_INTR_MASK_SET_DP 0x0800 /* Bit 11: set DP mask */ + +#define MI_INTR_MASK_SP 0x01 /* Bit 0: SP intr mask */ +#define MI_INTR_MASK_SI 0x02 /* Bit 1: SI intr mask */ +#define MI_INTR_MASK_AI 0x04 /* Bit 2: AI intr mask */ +#define MI_INTR_MASK_VI 0x08 /* Bit 3: VI intr mask */ +#define MI_INTR_MASK_PI 0x10 /* Bit 4: PI intr mask */ +#define MI_INTR_MASK_DP 0x20 /* Bit 5: DP intr mask */ + +#define MI_INTR_SP 0x01 /* Bit 0: SP intr */ +#define MI_INTR_SI 0x02 /* Bit 1: SI intr */ +#define MI_INTR_AI 0x04 /* Bit 2: AI intr */ +#define MI_INTR_VI 0x08 /* Bit 3: VI intr */ +#define MI_INTR_PI 0x10 /* Bit 4: PI intr */ +#define MI_INTR_DP 0x20 /* Bit 5: DP intr */ + +#define PI_STATUS_DMA_BUSY 0x01 +#define PI_STATUS_IO_BUSY 0x02 +#define PI_STATUS_ERROR 0x04 + +#define PI_SET_RESET 0x01 +#define PI_CLR_INTR 0x02 + +#define SI_STATUS_DMA_BUSY 0x0001 +#define SI_STATUS_RD_BUSY 0x0002 +#define SI_STATUS_DMA_ERROR 0x0008 +#define SI_STATUS_INTERRUPT 0x1000 + +#define FPCSR_FS 0x01000000 /* flush denorm to zero */ +#define FPCSR_C 0x00800000 /* condition bit */ +#define FPCSR_CE 0x00020000 /* cause: unimplemented operation */ +#define FPCSR_CV 0x00010000 /* cause: invalid operation */ +#define FPCSR_CZ 0x00008000 /* cause: division by zero */ +#define FPCSR_CO 0x00004000 /* cause: overflow */ +#define FPCSR_CU 0x00002000 /* cause: underflow */ +#define FPCSR_CI 0x00001000 /* cause: inexact operation */ +#define FPCSR_EV 0x00000800 /* enable: invalid operation */ +#define FPCSR_EZ 0x00000400 /* enable: division by zero */ +#define FPCSR_EO 0x00000200 /* enable: overflow */ +#define FPCSR_EU 0x00000100 /* enable: underflow */ +#define FPCSR_EI 0x00000080 /* enable: inexact operation */ +#define FPCSR_FV 0x00000040 /* flag: invalid operation */ +#define FPCSR_FZ 0x00000020 /* flag: division by zero */ +#define FPCSR_FO 0x00000010 /* flag: overflow */ +#define FPCSR_FU 0x00000008 /* flag: underflow */ +#define FPCSR_FI 0x00000004 /* flag: inexact operation */ +#define FPCSR_RM_MASK 0x00000003 /* rounding mode mask */ +#define FPCSR_RM_RN 0x00000000 /* round to nearest */ +#define FPCSR_RM_RZ 0x00000001 /* round to zero */ +#define FPCSR_RM_RP 0x00000002 /* round to positive infinity */ +#define FPCSR_RM_RM 0x00000003 /* round to negative infinity */ + +#define FPR_Type(Reg) (Reg) == R4300i_COP1_S ? "S" : (Reg) == R4300i_COP1_D ? "D" :\ + (Reg) == R4300i_COP1_W ? "W" : "L" + +typedef struct { + uint32_t PROGRAM_COUNTER; + MIPS_DWORD GPR[32]; + MIPS_DWORD FPR[32]; + uint32_t CP0[33]; + uint32_t FPCR[32]; + MIPS_DWORD HI; + MIPS_DWORD LO; + uint32_t RDRAM[10]; + uint32_t SP[10]; + uint32_t DPC[10]; + uint32_t MI[4]; + uint32_t VI[14]; + uint32_t AI[6]; + uint32_t PI[13]; + uint32_t RI[8]; + uint32_t SI[4]; + int8_t PIF_Ram[0x40]; +} N64_REGISTERS; + +enum FPU_Format { + FPU_Unkown,FPU_Dword, FPU_Qword, FPU_Float, FPU_Double +}; + +enum FPU_RoundingModel { + RoundUnknown, RoundDefault, RoundTruncate, RoundNearest, RoundDown, RoundUp +}; + +void ChangeMiIntrMask ( usf_state_t * ); +void ChangeMiModeReg ( usf_state_t * ); +void ChangeSpStatus ( usf_state_t * ); +void InitalizeR4300iRegisters ( usf_state_t * ); +void UpdateCurrentHalfLine ( usf_state_t * ); +void SetFpuLocations ( usf_state_t * ); + +void SetupRegisters(usf_state_t *, N64_REGISTERS * n64_Registers); + +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp.h b/Frameworks/lazyusf/lazyusf/rsp.h new file mode 100644 index 000000000..7dce5e512 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp.h @@ -0,0 +1,11 @@ +#ifndef RSP_H +#define RSP_H + +#include "usf.h" +#include "usf_internal.h" + +void real_run_rsp(usf_state_t *, uint32_t cycles); + +int32_t init_rsp(usf_state_t *); + +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/config.h b/Frameworks/lazyusf/lazyusf/rsp/config.h new file mode 100644 index 000000000..8dce602b4 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/config.h @@ -0,0 +1,60 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.12.04 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#define _CRT_SECURE_NO_WARNINGS +/* + * This is only here for people using modern Microsoft compilers. + * Usually the default warning level complains over "deprecated" CRT methods. + * It's basically Microsoft's way of saying they're better than everyone. + */ + +#define MINIMUM_MESSAGE_PRIORITY 1 +#define EXTERN_COMMAND_LIST_GBI +#define EXTERN_COMMAND_LIST_ABI +#define SEMAPHORE_LOCK_CORRECTIONS +#define WAIT_FOR_CPU_HOST +#define EMULATE_STATIC_PC + +#ifdef EMULATE_STATIC_PC +#define CONTINUE {continue;} +#define JUMP {goto BRANCH;} +#else +#define CONTINUE {break;} +#define JUMP {break;} +#endif + +#if (0) +#define SP_EXECUTE_LOG +#define VU_EMULATE_SCALAR_ACCUMULATOR_READ +#endif + +#define CFG_HLE_GFX (0) +#define CFG_HLE_AUD (0) +#define CFG_HLE_VID (0) /* reserved/unused */ +#define CFG_HLE_JPG (0) /* unused */ +#define CFG_QUEUE_E_DRAM (0) +#define CFG_QUEUE_E_DMEM (0) +#define CFG_QUEUE_E_IMEM (0) +/* + * Note: This never actually made it into the configuration system. + * Instead, DMEM and IMEM are always exported on every call to DllConfig(). + */ + +/* + * Special switches. + * (generally for correcting RSP clock behavior on Project64 2.x) + * Also includes RSP register states debugger. + */ +#define CFG_WAIT_FOR_CPU_HOST (1) +#define CFG_MEND_SEMAPHORE_LOCK (0) +#define CFG_TRACE_RSP_REGISTERS (0) diff --git a/Frameworks/lazyusf/lazyusf/rsp/execute.h b/Frameworks/lazyusf/lazyusf/rsp/execute.h new file mode 100644 index 000000000..bebc42223 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/execute.h @@ -0,0 +1,475 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.12.11 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "rsp.h" + +#include "su.h" +#include "vu/vu.h" + +#define FIT_IMEM(PC) (PC & 0xFFF & 0xFFC) + +NOINLINE void run_task(usf_state_t * state) +{ + register int PC; + + if (CFG_WAIT_FOR_CPU_HOST != 0) + { + register int i; + + for (i = 0; i < 32; i++) + state->MFC0_count[i] = 0; + } + PC = FIT_IMEM(SP_PC_REG); + while ((SP_STATUS_REG & 0x00000001) == 0x00000000) + { + register uint32_t inst; + + inst = *(uint32_t *)(state->IMEM + FIT_IMEM(PC)); +#ifdef EMULATE_STATIC_PC + PC = (PC + 0x004); +EX: +#endif +#ifdef SP_EXECUTE_LOG + step_SP_commands(inst); +#endif + if (inst >> 25 == 0x25) /* is a VU instruction */ + { + const int opcode = inst % 64; /* inst.R.func */ + const int vd = (inst & 0x000007FF) >> 6; /* inst.R.sa */ + const int vs = (unsigned short)(inst) >> 11; /* inst.R.rd */ + const int vt = (inst >> 16) & 31; /* inst.R.rt */ + const int e = (inst >> 21) & 0xF; /* rs & 0xF */ + + COP2_C2[opcode](state, vd, vs, vt, e); + } + else + { + const int op = inst >> 26; + const int rs = inst >> 21; /* &= 31 */ + const int rt = (inst >> 16) & 31; + const int rd = (unsigned short)(inst) >> 11; + const int element = (inst & 0x000007FF) >> 7; + const int base = (inst >> 21) & 31; + +#if (0) + state->SR[0] = 0x00000000; /* already handled on per-instruction basis */ +#endif + switch (op) + { + signed int offset; + register uint32_t addr; + + case 000: /* SPECIAL */ + switch (inst % 64) + { + case 000: /* SLL */ + state->SR[rd] = state->SR[rt] << MASK_SA(inst >> 6); + state->SR[0] = 0x00000000; + CONTINUE + case 002: /* SRL */ + state->SR[rd] = (unsigned)(state->SR[rt]) >> MASK_SA(inst >> 6); + state->SR[0] = 0x00000000; + CONTINUE + case 003: /* SRA */ + state->SR[rd] = (signed)(state->SR[rt]) >> MASK_SA(inst >> 6); + state->SR[0] = 0x00000000; + CONTINUE + case 004: /* SLLV */ + state->SR[rd] = state->SR[rt] << MASK_SA(state->SR[rs]); + state->SR[0] = 0x00000000; + CONTINUE + case 006: /* SRLV */ + state->SR[rd] = (unsigned)(state->SR[rt]) >> MASK_SA(state->SR[rs]); + state->SR[0] = 0x00000000; + CONTINUE + case 007: /* SRAV */ + state->SR[rd] = (signed)(state->SR[rt]) >> MASK_SA(state->SR[rs]); + state->SR[0] = 0x00000000; + CONTINUE + case 011: /* JALR */ + state->SR[rd] = (PC + LINK_OFF) & 0x00000FFC; + state->SR[0] = 0x00000000; + case 010: /* JR */ + set_PC(state, state->SR[rs]); + JUMP + case 015: /* BREAK */ + SP_STATUS_REG |= 0x00000003; /* BROKE | HALT */ + if (SP_STATUS_REG & 0x00000040) + { /* SP_STATUS_INTR_BREAK */ + MI_INTR_REG |= 0x00000001; + CheckInterrupts(state); + } + CONTINUE + case 040: /* ADD */ + case 041: /* ADDU */ + state->SR[rd] = state->SR[rs] + state->SR[rt]; + state->SR[0] = 0x00000000; /* needed for Rareware ucodes */ + CONTINUE + case 042: /* SUB */ + case 043: /* SUBU */ + state->SR[rd] = state->SR[rs] - state->SR[rt]; + state->SR[0] = 0x00000000; + CONTINUE + case 044: /* AND */ + state->SR[rd] = state->SR[rs] & state->SR[rt]; + state->SR[0] = 0x00000000; /* needed for Rareware ucodes */ + CONTINUE + case 045: /* OR */ + state->SR[rd] = state->SR[rs] | state->SR[rt]; + state->SR[0] = 0x00000000; + CONTINUE + case 046: /* XOR */ + state->SR[rd] = state->SR[rs] ^ state->SR[rt]; + state->SR[0] = 0x00000000; + CONTINUE + case 047: /* NOR */ + state->SR[rd] = ~(state->SR[rs] | state->SR[rt]); + state->SR[0] = 0x00000000; + CONTINUE + case 052: /* SLT */ + state->SR[rd] = ((signed)(state->SR[rs]) < (signed)(state->SR[rt])); + state->SR[0] = 0x00000000; + CONTINUE + case 053: /* SLTU */ + state->SR[rd] = ((unsigned)(state->SR[rs]) < (unsigned)(state->SR[rt])); + state->SR[0] = 0x00000000; + CONTINUE + default: + res_S(state); + CONTINUE + } + CONTINUE + case 001: /* REGIMM */ + switch (rt) + { + case 020: /* BLTZAL */ + state->SR[31] = (PC + LINK_OFF) & 0x00000FFC; + case 000: /* BLTZ */ + if (!(state->SR[base] < 0)) + CONTINUE + set_PC(state, PC + 4*inst + SLOT_OFF); + JUMP + case 021: /* BGEZAL */ + state->SR[31] = (PC + LINK_OFF) & 0x00000FFC; + case 001: /* BGEZ */ + if (!(state->SR[base] >= 0)) + CONTINUE + set_PC(state, PC + 4*inst + SLOT_OFF); + JUMP + default: + res_S(state); + CONTINUE + } + CONTINUE + case 003: /* JAL */ + state->SR[31] = (PC + LINK_OFF) & 0x00000FFC; + case 002: /* J */ + set_PC(state, 4*inst); + JUMP + case 004: /* BEQ */ + if (!(state->SR[base] == state->SR[rt])) + CONTINUE + set_PC(state, PC + 4*inst + SLOT_OFF); + JUMP + case 005: /* BNE */ + if (!(state->SR[base] != state->SR[rt])) + CONTINUE + set_PC(state, PC + 4*inst + SLOT_OFF); + JUMP + case 006: /* BLEZ */ + if (!((signed)state->SR[base] <= 0x00000000)) + CONTINUE + set_PC(state, PC + 4*inst + SLOT_OFF); + JUMP + case 007: /* BGTZ */ + if (!((signed)state->SR[base] > 0x00000000)) + CONTINUE + set_PC(state, PC + 4*inst + SLOT_OFF); + JUMP + case 010: /* ADDI */ + case 011: /* ADDIU */ + state->SR[rt] = state->SR[base] + (signed short)(inst); + state->SR[0] = 0x00000000; + CONTINUE + case 012: /* SLTI */ + state->SR[rt] = ((signed)(state->SR[base]) < (signed short)(inst)); + state->SR[0] = 0x00000000; + CONTINUE + case 013: /* SLTIU */ + state->SR[rt] = ((unsigned)(state->SR[base]) < (unsigned short)(inst)); + state->SR[0] = 0x00000000; + CONTINUE + case 014: /* ANDI */ + state->SR[rt] = state->SR[base] & (unsigned short)(inst); + state->SR[0] = 0x00000000; + CONTINUE + case 015: /* ORI */ + state->SR[rt] = state->SR[base] | (unsigned short)(inst); + state->SR[0] = 0x00000000; + CONTINUE + case 016: /* XORI */ + state->SR[rt] = state->SR[base] ^ (unsigned short)(inst); + state->SR[0] = 0x00000000; + CONTINUE + case 017: /* LUI */ + state->SR[rt] = inst << 16; + state->SR[0] = 0x00000000; + CONTINUE + case 020: /* COP0 */ + switch (base) + { + case 000: /* MFC0 */ + MFC0(state, rt, rd & 0xF); + CONTINUE + case 004: /* MTC0 */ + MTC0[rd & 0xF](state, rt); + CONTINUE + default: + res_S(state); + CONTINUE + } + CONTINUE + case 022: /* COP2 */ + switch (base) + { + case 000: /* MFC2 */ + MFC2(state, rt, rd, element); + CONTINUE + case 002: /* CFC2 */ + CFC2(state, rt, rd); + CONTINUE + case 004: /* MTC2 */ + MTC2(state, rt, rd, element); + CONTINUE + case 006: /* CTC2 */ + CTC2(state, rt, rd); + CONTINUE + default: + res_S(state); + CONTINUE + } + CONTINUE + case 040: /* LB */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + state->SR[rt] = state->DMEM[BES(addr)]; + state->SR[rt] = (signed char)(state->SR[rt]); + state->SR[0] = 0x00000000; + CONTINUE + case 041: /* LH */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + if (addr%0x004 == 0x003) + { + SR_B(rt, 2) = state->DMEM[addr - BES(0x000)]; + addr = (addr + 0x00000001) & 0x00000FFF; + SR_B(rt, 3) = state->DMEM[addr + BES(0x000)]; + state->SR[rt] = (signed short)(state->SR[rt]); + } + else + { + addr -= HES(0x000)*(addr%0x004 - 1); + state->SR[rt] = *(signed short *)(state->DMEM + addr); + } + state->SR[0] = 0x00000000; + CONTINUE + case 043: /* LW */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + if (addr%0x004 != 0x000) + ULW(state, rt, addr); + else + state->SR[rt] = *(int32_t *)(state->DMEM + addr); + state->SR[0] = 0x00000000; + CONTINUE + case 044: /* LBU */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + state->SR[rt] = state->DMEM[BES(addr)]; + state->SR[rt] = (unsigned char)(state->SR[rt]); + state->SR[0] = 0x00000000; + CONTINUE + case 045: /* LHU */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + if (addr%0x004 == 0x003) + { + SR_B(rt, 2) = state->DMEM[addr - BES(0x000)]; + addr = (addr + 0x00000001) & 0x00000FFF; + SR_B(rt, 3) = state->DMEM[addr + BES(0x000)]; + state->SR[rt] = (unsigned short)(state->SR[rt]); + } + else + { + addr -= HES(0x000)*(addr%0x004 - 1); + state->SR[rt] = *(unsigned short *)(state->DMEM + addr); + } + state->SR[0] = 0x00000000; + CONTINUE + case 050: /* SB */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + state->DMEM[BES(addr)] = (unsigned char)(state->SR[rt]); + CONTINUE + case 051: /* SH */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + if (addr%0x004 == 0x003) + { + state->DMEM[addr - BES(0x000)] = SR_B(rt, 2); + addr = (addr + 0x00000001) & 0x00000FFF; + state->DMEM[addr + BES(0x000)] = SR_B(rt, 3); + CONTINUE + } + addr -= HES(0x000)*(addr%0x004 - 1); + *(short *)(state->DMEM + addr) = (short)(state->SR[rt]); + CONTINUE + case 053: /* SW */ + offset = (signed short)(inst); + addr = (state->SR[base] + offset) & 0x00000FFF; + if (addr%0x004 != 0x000) + USW(state, rt, addr); + else + *(int32_t *)(state->DMEM + addr) = state->SR[rt]; + CONTINUE + case 062: /* LWC2 */ + offset = SE(inst, 6); + switch (rd) + { + case 000: /* LBV */ + LBV(state, rt, element, offset, base); + CONTINUE + case 001: /* LSV */ + LSV(state, rt, element, offset, base); + CONTINUE + case 002: /* LLV */ + LLV(state, rt, element, offset, base); + CONTINUE + case 003: /* LDV */ + LDV(state, rt, element, offset, base); + CONTINUE + case 004: /* LQV */ + LQV(state, rt, element, offset, base); + CONTINUE + case 005: /* LRV */ + LRV(state, rt, element, offset, base); + CONTINUE + case 006: /* LPV */ + LPV(state, rt, element, offset, base); + CONTINUE + case 007: /* LUV */ + LUV(state, rt, element, offset, base); + CONTINUE + case 010: /* LHV */ + LHV(state, rt, element, offset, base); + CONTINUE + case 011: /* LFV */ + LFV(state, rt, element, offset, base); + CONTINUE + case 013: /* LTV */ + LTV(state, rt, element, offset, base); + CONTINUE + default: + res_S(state); + CONTINUE + } + CONTINUE + case 072: /* SWC2 */ + offset = SE(inst, 6); + switch (rd) + { + case 000: /* SBV */ + SBV(state, rt, element, offset, base); + CONTINUE + case 001: /* SSV */ + SSV(state, rt, element, offset, base); + CONTINUE + case 002: /* SLV */ + SLV(state, rt, element, offset, base); + CONTINUE + case 003: /* SDV */ + SDV(state, rt, element, offset, base); + CONTINUE + case 004: /* SQV */ + SQV(state, rt, element, offset, base); + CONTINUE + case 005: /* SRV */ + SRV(state, rt, element, offset, base); + CONTINUE + case 006: /* SPV */ + SPV(state, rt, element, offset, base); + CONTINUE + case 007: /* SUV */ + SUV(state, rt, element, offset, base); + CONTINUE + case 010: /* SHV */ + SHV(state, rt, element, offset, base); + CONTINUE + case 011: /* SFV */ + SFV(state, rt, element, offset, base); + CONTINUE + case 012: /* SWV */ + SWV(state, rt, element, offset, base); + CONTINUE + case 013: /* STV */ + STV(state, rt, element, offset, base); + CONTINUE + default: + res_S(state); + CONTINUE + } + CONTINUE + default: + res_S(state); + CONTINUE + } + } +#ifndef EMULATE_STATIC_PC + if (state->stage == 2) /* branch phase of scheduler */ + { + state->stage = 0*stage; + PC = state->temp_PC & 0x00000FFC; + SP_PC_REG = state->temp_PC; + } + else + { + state->stage = 2*state->stage; /* next IW in branch delay slot? */ + PC = (PC + 0x004) & 0xFFC; + SP_PC_REG = 0x04001000 + PC; + } + continue; +#else + continue; +BRANCH: + inst = *(uint32_t *)(state->IMEM + FIT_IMEM(PC)); + PC = state->temp_PC & 0x00000FFC; + goto EX; +#endif + } + SP_PC_REG = 0x04001000 | FIT_IMEM(PC); + if (SP_STATUS_REG & 0x00000002) /* normal exit, from executing BREAK */ + return; + else if (MI_INTR_REG & 0x00000001) /* interrupt set by MTC0 to break */ + CheckInterrupts(state); + else if (CFG_WAIT_FOR_CPU_HOST != 0) /* plugin system hack to re-sync */ + {} + else if (SP_SEMAPHORE_REG != 0x00000000) /* semaphore lock fixes */ + {} + else /* ??? unknown, possibly external intervention from CPU memory map */ + { + message("SP_SET_HALT", 3); + return; + } + SP_STATUS_REG &= ~0x00000001; /* CPU restarts with the correct SIGs. */ + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/rsp.c b/Frameworks/lazyusf/lazyusf/rsp/rsp.c new file mode 100644 index 000000000..41c2d6f51 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/rsp.c @@ -0,0 +1,66 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.12.12 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "../usf.h" + +#include "../dma.h" +#include "../exception.h" +#include "../memory.h" +#include "../registers.h" + +#include "../usf_internal.h" + +#undef JUMP + +#include "config.h" + +#include "rsp.h" + +void real_run_rsp(usf_state_t * state, uint32_t cycles) +{ + if (SP_STATUS_REG & 0x00000003) + { + message("SP_STATUS_HALT", 3); + return; + } + run_task(state); + return; +} + +int32_t init_rsp(usf_state_t * state) +{ + state->CR[0x0] = &SP_MEM_ADDR_REG; + state->CR[0x1] = &SP_DRAM_ADDR_REG; + state->CR[0x2] = &SP_RD_LEN_REG; + state->CR[0x3] = &SP_WR_LEN_REG; + state->CR[0x4] = &SP_STATUS_REG; + state->CR[0x5] = &SP_DMA_FULL_REG; + state->CR[0x6] = &SP_DMA_BUSY_REG; + state->CR[0x7] = &SP_SEMAPHORE_REG; + state->CR[0x8] = &DPC_START_REG; + state->CR[0x9] = &DPC_END_REG; + state->CR[0xA] = &DPC_CURRENT_REG; + state->CR[0xB] = &DPC_STATUS_REG; + state->CR[0xC] = &DPC_CLOCK_REG; + state->CR[0xD] = &DPC_BUFBUSY_REG; + state->CR[0xE] = &DPC_PIPEBUSY_REG; + state->CR[0xF] = &DPC_TMEM_REG; + return 0; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/rsp.h b/Frameworks/lazyusf/lazyusf/rsp/rsp.h new file mode 100644 index 000000000..1b3f8d835 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/rsp.h @@ -0,0 +1,62 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.12.12 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#ifndef _RSP_H_ +#define _RSP_H_ + +#ifdef _MSC_VER +#define INLINE __inline +#define NOINLINE __declspec(noinline) +#define ALIGNED _declspec(align(16)) +#else +#define INLINE __attribute__((forceinline)) +#define NOINLINE __attribute__((noinline)) +#define ALIGNED __attribute__((aligned(16))) +#endif + +/* + * Streaming SIMD Extensions version import management + */ +#ifdef ARCH_MIN_SSSE3 +#define ARCH_MIN_SSE2 +#include +#endif +#ifdef ARCH_MIN_SSE2 +#include +#endif + +typedef unsigned char byte; + +typedef uint32_t RCPREG; + +NOINLINE void message(const char* body, int priority) +{ +} + +/* + * Update RSP configuration memory from local file resource. + */ +#define CHARACTERS_PER_LINE (80) +/* typical standard DOS text file limit per line */ +NOINLINE void update_conf(const char* source) +{ +} + +#include "su.h" +#include "vu/vu.h" + +/* Allocate the RSP CPU loop to its own functional space. */ +NOINLINE extern void run_task(usf_state_t * state); +#include "execute.h" + +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/su.h b/Frameworks/lazyusf/lazyusf/rsp/su.h new file mode 100644 index 000000000..5a80747ca --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/su.h @@ -0,0 +1,1537 @@ +/******************************************************************************\ +* Project: MSP Emulation Table for Scalar Unit Operations * +* Authors: Iconoclast * +* Release: 2013.12.10 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#ifndef _SU_H +#define _SU_H + +/* + * RSP virtual registers (of scalar unit) + * The most important are the 32 general-purpose scalar registers. + * We have the convenience of using a 32-bit machine (Win32) to emulate + * another 32-bit machine (MIPS/N64), so the most natural way to accurately + * emulate the scalar GPRs is to use the standard `int` type. Situations + * specifically requiring sign-extension or lack thereof are forcibly + * applied as defined in the MIPS quick reference card and user manuals. + * Remember that these are not the same "GPRs" as in the MIPS ISA and totally + * abandon their designated purposes on the master CPU host (the VR4300), + * hence most of the MIPS names "k0, k1, t0, t1, v0, v1 ..." no longer apply. + */ + +#include "rsp.h" + +NOINLINE static void res_S(usf_state_t * state) +{ + return; +} + +#ifdef EMULATE_STATIC_PC +#define BASE_OFF 0x000 +#else +#define BASE_OFF 0x004 +#endif + +#define SLOT_OFF (BASE_OFF + 0x000) +#define LINK_OFF (BASE_OFF + 0x004) +void set_PC(usf_state_t * state, int address) +{ + state->temp_PC = 0x04001000 + (address & 0xFFC); +#ifndef EMULATE_STATIC_PC + state->stage = 1; +#endif + return; +} + +#if (0) +#define MASK_SA(sa) (sa & 31) +/* Force masking in software. */ +#else +#define MASK_SA(sa) (sa) +/* Let hardware architecture do the mask for us. */ +#endif + +#if (0) +#define ENDIAN 0 +#else +#define ENDIAN ~0 +#endif +#define BES(address) ((address) ^ ((ENDIAN) & 03)) +#define HES(address) ((address) ^ ((ENDIAN) & 02)) +#define MES(address) ((address) ^ ((ENDIAN) & 01)) +#define WES(address) ((address) ^ ((ENDIAN) & 00)) +#define SR_B(s, i) (*(byte *)(((byte *)(state->SR + s)) + BES(i))) +#define SR_S(s, i) (*(short *)(((byte *)(state->SR + s)) + HES(i))) +#define SE(x, b) (-(x & (1 << b)) | (x & ~(~0 << b))) +#define ZE(x, b) (+(x & (1 << b)) | (x & ~(~0 << b))) + +static union { + unsigned char B[4]; + signed char SB[4]; + unsigned short H[2]; + signed short SH[2]; + unsigned W: 32; +} SR_temp; + +extern void ULW(usf_state_t *, int rd, uint32_t addr); +extern void USW(usf_state_t *, int rs, uint32_t addr); + +/* + * All other behaviors defined below this point in the file are specific to + * the SGI N64 extension to the MIPS R4000 and are not entirely implemented. + */ + +/*** Scalar, Coprocessor Operations (system control) ***/ + +static void MFC0(usf_state_t * state, int rt, int rd) +{ + state->SR[rt] = *(state->CR[rd]); + state->SR[0] = 0x00000000; + if (rd == 0x7) /* SP_SEMAPHORE_REG */ + { + if (CFG_MEND_SEMAPHORE_LOCK == 0) + return; + SP_SEMAPHORE_REG = 0x00000001; + SP_STATUS_REG |= 0x00000001; /* temporary bit to break CPU */ + return; + } + if (rd == 0x4) /* SP_STATUS_REG */ + { + if (CFG_WAIT_FOR_CPU_HOST == 0) + return; +#ifdef WAIT_FOR_CPU_HOST + ++state->MFC0_count[rt]; + if (state->MFC0_count[rt] > 07) + SP_STATUS_REG |= 0x00000001; /* Let OS restart the task. */ +#endif + } + return; +} + +static void MT_DMA_CACHE(usf_state_t * state, int rt) +{ + SP_MEM_ADDR_REG = state->SR[rt] & 0xFFFFFFF8; /* & 0x00001FF8 */ + return; /* Reserved upper bits are ignored during DMA R/W. */ +} +static void MT_DMA_DRAM(usf_state_t * state, int rt) +{ + SP_DRAM_ADDR_REG = state->SR[rt] & 0xFFFFFFF8; /* & 0x00FFFFF8 */ + return; /* Let the reserved bits get sent, but the pointer is 24-bit. */ +} +static void MT_DMA_READ_LENGTH(usf_state_t * state, int rt) +{ + SP_RD_LEN_REG = state->SR[rt] | 07; + SP_DMA_READ(state); + return; +} +static void MT_DMA_WRITE_LENGTH(usf_state_t * state, int rt) +{ + SP_WR_LEN_REG = state->SR[rt] | 07; + SP_DMA_WRITE(state); + return; +} +static void MT_SP_STATUS(usf_state_t * state, int rt) +{ + if (state->SR[rt] & 0xFE000040) + message("MTC0\nSP_STATUS", 2); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000001) << 0); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00000002) << 0); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000004) << 1); + MI_INTR_REG &= ~((state->SR[rt] & 0x00000008) >> 3); /* SP_CLR_INTR */ + MI_INTR_REG |= ((state->SR[rt] & 0x00000010) >> 4); /* SP_SET_INTR */ + SP_STATUS_REG |= (state->SR[rt] & 0x00000010) >> 4; /* int set halt */ + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000020) << 5); + /* SP_STATUS_REG |= (!!(state->SR[rt] & 0x00000040) << 5); */ + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000080) << 6); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00000100) << 6); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000200) << 7); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00000400) << 7); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000800) << 8); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00001000) << 8); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00002000) << 9); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00004000) << 9); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00008000) << 10); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00010000) << 10); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00020000) << 11); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00040000) << 11); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00080000) << 12); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00100000) << 12); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00200000) << 13); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x00400000) << 13); + SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00800000) << 14); + SP_STATUS_REG |= (!!(state->SR[rt] & 0x01000000) << 14); + return; +} +static void MT_SP_RESERVED(usf_state_t * state, int rt) +{ + const uint32_t source = state->SR[rt] & 0x00000000; /* forced (zilmar, dox) */ + + SP_SEMAPHORE_REG = source; + return; +} +static void MT_CMD_START(usf_state_t * state, int rt) +{ + const uint32_t source = state->SR[rt] & 0xFFFFFFF8; /* Funnelcube demo */ + + if (DPC_BUFBUSY_REG) /* lock hazards not implemented */ + message("MTC0\nCMD_START", 0); + DPC_END_REG = DPC_CURRENT_REG = DPC_START_REG = source; + return; +} +static void MT_CMD_END(usf_state_t * state, int rt) +{ + if (DPC_BUFBUSY_REG) + message("MTC0\nCMD_END", 0); /* This is just CA-related. */ + DPC_END_REG = state->SR[rt] & 0xFFFFFFF8; + return; +} +static void MT_CMD_STATUS(usf_state_t * state, int rt) +{ + if (state->SR[rt] & 0xFFFFFD80) /* unsupported or reserved bits */ + message("MTC0\nCMD_STATUS", 2); + DPC_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000001) << 0); + DPC_STATUS_REG |= (!!(state->SR[rt] & 0x00000002) << 0); + DPC_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000004) << 1); + DPC_STATUS_REG |= (!!(state->SR[rt] & 0x00000008) << 1); + DPC_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000010) << 2); + DPC_STATUS_REG |= (!!(state->SR[rt] & 0x00000020) << 2); +/* Some NUS-CIC-6105 SP tasks try to clear some zeroed DPC registers. */ + DPC_TMEM_REG &= !(state->SR[rt] & 0x00000040) * -1; + /* DPC_PIPEBUSY_REG &= !(state->SR[rt] & 0x00000080) * -1; */ + /* DPC_BUFBUSY_REG &= !(state->SR[rt] & 0x00000100) * -1; */ + DPC_CLOCK_REG &= !(state->SR[rt] & 0x00000200) * -1; + return; +} +static void MT_CMD_CLOCK(usf_state_t * state, int rt) +{ + message("MTC0\nCMD_CLOCK", 1); /* read-only?? */ + DPC_CLOCK_REG = state->SR[rt]; + return; /* Appendix says this is RW; elsewhere it says R. */ +} +static void MT_READ_ONLY(usf_state_t * state, int rt) +{ + char text[64]; + + sprintf(text, "MTC0\nInvalid write attempt.\nstate->SR[%i] = 0x%08X", rt, state->SR[rt]); + message(text, 2); + return; +} + +static void (*MTC0[16])(usf_state_t *, int) = { +MT_DMA_CACHE ,MT_DMA_DRAM ,MT_DMA_READ_LENGTH ,MT_DMA_WRITE_LENGTH, +MT_SP_STATUS ,MT_READ_ONLY ,MT_READ_ONLY ,MT_SP_RESERVED, +MT_CMD_START ,MT_CMD_END ,MT_READ_ONLY ,MT_CMD_STATUS, +MT_CMD_CLOCK ,MT_READ_ONLY ,MT_READ_ONLY ,MT_READ_ONLY +}; +#if 0 +void SP_DMA_READ(usf_state_t * state) +{ + register unsigned int length; + register unsigned int count; + register unsigned int skip; + + length = (SP_RD_LEN_REG & 0x00000FFF) >> 0; + count = (SP_RD_LEN_REG & 0x000FF000) >> 12; + skip = (SP_RD_LEN_REG & 0xFFF00000) >> 20; + /* length |= 07; // already corrected by mtc0 */ + ++length; + ++count; + skip += length; + do + { /* `count` always starts > 0, so we begin with `do` instead of `while`. */ + unsigned int offC, offD; /* SP cache and dynamic DMA pointers */ + register unsigned int i = 0; + + --count; + do + { + offC = (count*length + SP_MEM_ADDR_REG + i) & 0x00001FF8; + offD = (count*skip + SP_DRAM_ADDR_REG + i) & 0x00FFFFF8; + memcpy(state->DMEM + offC, state->RDRAM + offD, 8); + i += 0x008; + } while (i < length); + } while (count); + SP_DMA_BUSY_REG = 0x00000000; + SP_STATUS_REG &= ~0x00000004; /* SP_STATUS_DMABUSY */ +} +void SP_DMA_WRITE(usf_state_t * state) +{ + register unsigned int length; + register unsigned int count; + register unsigned int skip; + + length = (SP_WR_LEN_REG & 0x00000FFF) >> 0; + count = (SP_WR_LEN_REG & 0x000FF000) >> 12; + skip = (SP_WR_LEN_REG & 0xFFF00000) >> 20; + /* length |= 07; // already corrected by mtc0 */ + ++length; + ++count; + skip += length; + do + { /* `count` always starts > 0, so we begin with `do` instead of `while`. */ + unsigned int offC, offD; /* SP cache and dynamic DMA pointers */ + register unsigned int i = 0; + + --count; + do + { + offC = (count*length + SP_MEM_ADDR_REG + i) & 0x00001FF8; + offD = (count*skip + SP_DRAM_ADDR_REG + i) & 0x00FFFFF8; + memcpy(state->RDRAM + offD, state->DMEM + offC, 8); + i += 0x000008; + } while (i < length); + } while (count); + SP_DMA_BUSY_REG = 0x00000000; + SP_STATUS_REG &= ~0x00000004; /* SP_STATUS_DMABUSY */ +} +#endif + +/*** Scalar, Coprocessor Operations (vector unit) ***/ + +/* + * Since RSP vectors are stored 100% accurately as big-endian arrays for the + * proper vector operation math to be done, LWC2 and SWC2 emulation code will + * have to look a little different. zilmar's method is to distort the endian + * using an array of unions, permitting hacked byte- and halfword-precision. + */ + +/* + * Universal byte-access macro for 16*8 halfword vectors. + * Use this macro if you are not sure whether the element is odd or even. + */ +#define VR_B(vt,element) (*(byte *)((byte *)(state->VR[vt]) + MES(element))) + +/* + * Optimized byte-access macros for the vector registers. + * Use these ONLY if you know the element is even (or odd in the second). + */ +#define VR_A(vt,element) (*(byte *)((byte *)(state->VR[vt]) + element + MES(0x0))) +#define VR_U(vt,element) (*(byte *)((byte *)(state->VR[vt]) + element - MES(0x0))) + +/* + * Optimized halfword-access macro for indexing eight-element vectors. + * Use this ONLY if you know the element is even, not odd. + * + * If the four-bit element is odd, then there is no solution in one hit. + */ +#define VR_S(vt,element) (*(short *)((byte *)(state->VR[vt]) + element)) + +extern unsigned short get_VCO(usf_state_t * state); +extern unsigned short get_VCC(usf_state_t * state); +extern unsigned char get_VCE(usf_state_t * state); +extern void set_VCO(usf_state_t * state, unsigned short VCO); +extern void set_VCC(usf_state_t * state, unsigned short VCC); +extern void set_VCE(usf_state_t * state, unsigned char VCE); + +unsigned short rwR_VCE(usf_state_t * state) +{ /* never saw a game try to read VCE out to a scalar GPR yet */ + register unsigned short ret_slot; + + ret_slot = 0x00 | (unsigned short)get_VCE(state); + return (ret_slot); +} +void rwW_VCE(usf_state_t * state, unsigned short VCE) +{ /* never saw a game try to write VCE using a scalar GPR yet */ + register int i; + + VCE = 0x00 | (VCE & 0xFF); + for (i = 0; i < 8; i++) + state->vce[i] = (VCE >> i) & 1; + return; +} + +static unsigned short (*R_VCF[32])(usf_state_t *) = { + get_VCO,get_VCC,rwR_VCE,rwR_VCE, +/* Hazard reaction barrier: RD = (UINT16)(inst) >> 11, without &= 3. */ + get_VCO,get_VCC,rwR_VCE,rwR_VCE, + get_VCO,get_VCC,rwR_VCE,rwR_VCE, + get_VCO,get_VCC,rwR_VCE,rwR_VCE, + get_VCO,get_VCC,rwR_VCE,rwR_VCE, + get_VCO,get_VCC,rwR_VCE,rwR_VCE, + get_VCO,get_VCC,rwR_VCE,rwR_VCE, + get_VCO,get_VCC,rwR_VCE,rwR_VCE +}; +static void (*W_VCF[32])(usf_state_t *, unsigned short) = { + set_VCO,set_VCC,rwW_VCE,rwW_VCE, +/* Hazard reaction barrier: RD = (UINT16)(inst) >> 11, without &= 3. */ + set_VCO,set_VCC,rwW_VCE,rwW_VCE, + set_VCO,set_VCC,rwW_VCE,rwW_VCE, + set_VCO,set_VCC,rwW_VCE,rwW_VCE, + set_VCO,set_VCC,rwW_VCE,rwW_VCE, + set_VCO,set_VCC,rwW_VCE,rwW_VCE, + set_VCO,set_VCC,rwW_VCE,rwW_VCE, + set_VCO,set_VCC,rwW_VCE,rwW_VCE +}; +static void MFC2(usf_state_t * state, int rt, int vs, int e) +{ + SR_B(rt, 2) = VR_B(vs, e); + e = (e + 0x1) & 0xF; + SR_B(rt, 3) = VR_B(vs, e); + state->SR[rt] = (signed short)(state->SR[rt]); + state->SR[0] = 0x00000000; + return; +} +static void MTC2(usf_state_t * state, int rt, int vd, int e) +{ + VR_B(vd, e+0x0) = SR_B(rt, 2); + VR_B(vd, e+0x1) = SR_B(rt, 3); + return; /* If element == 0xF, it does not matter; loads do not wrap over. */ +} +static void CFC2(usf_state_t * state, int rt, int rd) +{ + state->SR[rt] = (signed short)R_VCF[rd](state); + state->SR[0] = 0x00000000; + return; +} +static void CTC2(usf_state_t * state, int rt, int rd) +{ + W_VCF[rd](state, state->SR[rt] & 0x0000FFFF); + return; +} + +/*** Scalar, Coprocessor Operations (vector unit, scalar cache transfers) ***/ +INLINE static void LBV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + addr = (state->SR[base] + 1*offset) & 0x00000FFF; + VR_B(vt, e) = state->DMEM[BES(addr)]; + return; +} +INLINE static void LSV(usf_state_t * state, int vt, int element, int offset, int base) +{ + int correction; + register uint32_t addr; + const int e = element; + + if (e & 0x1) + { + message("LSV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 2*offset) & 0x00000FFF; + correction = addr % 0x004; + if (correction == 0x003) + { + message("LSV\nWeird addr.", 3); + return; + } + VR_S(vt, e) = *(short *)(state->DMEM + addr - HES(0x000)*(correction - 1)); + return; +} +INLINE static void LLV(usf_state_t * state, int vt, int element, int offset, int base) +{ + int correction; + register uint32_t addr; + const int e = element; + + if (e & 0x1) + { + message("LLV\nOdd element.", 3); + return; + } /* Illegal (but still even) elements are used by Boss Game Studios. */ + addr = (state->SR[base] + 4*offset) & 0x00000FFF; + if (addr & 0x00000001) + { + message("LLV\nOdd addr.", 3); + return; + } + correction = HES(0x000)*(addr%0x004 - 1); + VR_S(vt, e+0x0) = *(short *)(state->DMEM + addr - correction); + addr = (addr + 0x00000002) & 0x00000FFF; /* F3DLX 1.23: addr%4 is 0x002. */ + VR_S(vt, e+0x2) = *(short *)(state->DMEM + addr + correction); + return; +} +INLINE static void LDV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + if (e & 0x1) + { + message("LDV\nOdd element.", 3); + return; + } /* Illegal (but still even) elements are used by Boss Game Studios. */ + addr = (state->SR[base] + 8*offset) & 0x00000FFF; + switch (addr & 07) + { + case 00: + VR_S(vt, e+0x0) = *(short *)(state->DMEM + addr + HES(0x000)); + VR_S(vt, e+0x2) = *(short *)(state->DMEM + addr + HES(0x002)); + VR_S(vt, e+0x4) = *(short *)(state->DMEM + addr + HES(0x004)); + VR_S(vt, e+0x6) = *(short *)(state->DMEM + addr + HES(0x006)); + return; + case 01: /* standard ABI ucodes (unlike e.g. MusyX w/ even addresses) */ + VR_S(vt, e+0x0) = *(short *)(state->DMEM + addr + 0x000); + VR_A(vt, e+0x2) = state->DMEM[addr + 0x002 - BES(0x000)]; + VR_U(vt, e+0x3) = state->DMEM[addr + 0x003 + BES(0x000)]; + VR_S(vt, e+0x4) = *(short *)(state->DMEM + addr + 0x004); + VR_A(vt, e+0x6) = state->DMEM[addr + 0x006 - BES(0x000)]; + addr += 0x007 + BES(00); + addr &= 0x00000FFF; + VR_U(vt, e+0x7) = state->DMEM[addr]; + return; + case 02: + VR_S(vt, e+0x0) = *(short *)(state->DMEM + addr + 0x000 - HES(0x000)); + VR_S(vt, e+0x2) = *(short *)(state->DMEM + addr + 0x002 + HES(0x000)); + VR_S(vt, e+0x4) = *(short *)(state->DMEM + addr + 0x004 - HES(0x000)); + addr += 0x006 + HES(00); + addr &= 0x00000FFF; + VR_S(vt, e+0x6) = *(short *)(state->DMEM + addr); + return; + case 03: /* standard ABI ucodes (unlike e.g. MusyX w/ even addresses) */ + VR_A(vt, e+0x0) = state->DMEM[addr + 0x000 - BES(0x000)]; + VR_U(vt, e+0x1) = state->DMEM[addr + 0x001 + BES(0x000)]; + VR_S(vt, e+0x2) = *(short *)(state->DMEM + addr + 0x002); + VR_A(vt, e+0x4) = state->DMEM[addr + 0x004 - BES(0x000)]; + addr += 0x005 + BES(00); + addr &= 0x00000FFF; + VR_U(vt, e+0x5) = state->DMEM[addr]; + VR_S(vt, e+0x6) = *(short *)(state->DMEM + addr + 0x001 - BES(0x000)); + return; + case 04: + VR_S(vt, e+0x0) = *(short *)(state->DMEM + addr + HES(0x000)); + VR_S(vt, e+0x2) = *(short *)(state->DMEM + addr + HES(0x002)); + addr += 0x004 + WES(00); + addr &= 0x00000FFF; + VR_S(vt, e+0x4) = *(short *)(state->DMEM + addr + HES(0x000)); + VR_S(vt, e+0x6) = *(short *)(state->DMEM + addr + HES(0x002)); + return; + case 05: /* standard ABI ucodes (unlike e.g. MusyX w/ even addresses) */ + VR_S(vt, e+0x0) = *(short *)(state->DMEM + addr + 0x000); + VR_A(vt, e+0x2) = state->DMEM[addr + 0x002 - BES(0x000)]; + addr += 0x003; + addr &= 0x00000FFF; + VR_U(vt, e+0x3) = state->DMEM[addr + BES(0x000)]; + VR_S(vt, e+0x4) = *(short *)(state->DMEM + addr + 0x001); + VR_A(vt, e+0x6) = state->DMEM[addr + BES(0x003)]; + VR_U(vt, e+0x7) = state->DMEM[addr + BES(0x004)]; + return; + case 06: + VR_S(vt, e+0x0) = *(short *)(state->DMEM + addr - HES(0x000)); + addr += 0x002; + addr &= 0x00000FFF; + VR_S(vt, e+0x2) = *(short *)(state->DMEM + addr + HES(0x000)); + VR_S(vt, e+0x4) = *(short *)(state->DMEM + addr + HES(0x002)); + VR_S(vt, e+0x6) = *(short *)(state->DMEM + addr + HES(0x004)); + return; + case 07: /* standard ABI ucodes (unlike e.g. MusyX w/ even addresses) */ + VR_A(vt, e+0x0) = state->DMEM[addr - BES(0x000)]; + addr += 0x001; + addr &= 0x00000FFF; + VR_U(vt, e+0x1) = state->DMEM[addr + BES(0x000)]; + VR_S(vt, e+0x2) = *(short *)(state->DMEM + addr + 0x001); + VR_A(vt, e+0x4) = state->DMEM[addr + BES(0x003)]; + VR_U(vt, e+0x5) = state->DMEM[addr + BES(0x004)]; + VR_S(vt, e+0x6) = *(short *)(state->DMEM + addr + 0x005); + return; + } +} +INLINE static void SBV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + addr = (state->SR[base] + 1*offset) & 0x00000FFF; + state->DMEM[BES(addr)] = VR_B(vt, e); + return; +} +INLINE static void SSV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + addr = (state->SR[base] + 2*offset) & 0x00000FFF; + state->DMEM[BES(addr)] = VR_B(vt, (e + 0x0)); + addr = (addr + 0x00000001) & 0x00000FFF; + state->DMEM[BES(addr)] = VR_B(vt, (e + 0x1) & 0xF); + return; +} +INLINE static void SLV(usf_state_t * state, int vt, int element, int offset, int base) +{ + int correction; + register uint32_t addr; + const int e = element; + + if ((e & 0x1) || e > 0xC) /* must support illegal even elements in F3DEX2 */ + { + message("SLV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 4*offset) & 0x00000FFF; + if (addr & 0x00000001) + { + message("SLV\nOdd addr.", 3); + return; + } + correction = HES(0x000)*(addr%0x004 - 1); + *(short *)(state->DMEM + addr - correction) = VR_S(vt, e+0x0); + addr = (addr + 0x00000002) & 0x00000FFF; /* F3DLX 0.95: "Mario Kart 64" */ + *(short *)(state->DMEM + addr + correction) = VR_S(vt, e+0x2); + return; +} +INLINE static void SDV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + addr = (state->SR[base] + 8*offset) & 0x00000FFF; + if (e > 0x8 || (e & 0x1)) + { /* Illegal elements with Boss Game Studios publications. */ + register int i; + + for (i = 0; i < 8; i++) + state->DMEM[BES(addr &= 0x00000FFF)] = VR_B(vt, (e+i)&0xF); + return; + } + switch (addr & 07) + { + case 00: + *(short *)(state->DMEM + addr + HES(0x000)) = VR_S(vt, e+0x0); + *(short *)(state->DMEM + addr + HES(0x002)) = VR_S(vt, e+0x2); + *(short *)(state->DMEM + addr + HES(0x004)) = VR_S(vt, e+0x4); + *(short *)(state->DMEM + addr + HES(0x006)) = VR_S(vt, e+0x6); + return; + case 01: /* "Tetrisphere" audio ucode */ + *(short *)(state->DMEM + addr + 0x000) = VR_S(vt, e+0x0); + state->DMEM[addr + 0x002 - BES(0x000)] = VR_A(vt, e+0x2); + state->DMEM[addr + 0x003 + BES(0x000)] = VR_U(vt, e+0x3); + *(short *)(state->DMEM + addr + 0x004) = VR_S(vt, e+0x4); + state->DMEM[addr + 0x006 - BES(0x000)] = VR_A(vt, e+0x6); + addr += 0x007 + BES(0x000); + addr &= 0x00000FFF; + state->DMEM[addr] = VR_U(vt, e+0x7); + return; + case 02: + *(short *)(state->DMEM + addr + 0x000 - HES(0x000)) = VR_S(vt, e+0x0); + *(short *)(state->DMEM + addr + 0x002 + HES(0x000)) = VR_S(vt, e+0x2); + *(short *)(state->DMEM + addr + 0x004 - HES(0x000)) = VR_S(vt, e+0x4); + addr += 0x006 + HES(0x000); + addr &= 0x00000FFF; + *(short *)(state->DMEM + addr) = VR_S(vt, e+0x6); + return; + case 03: /* "Tetrisphere" audio ucode */ + state->DMEM[addr + 0x000 - BES(0x000)] = VR_A(vt, e+0x0); + state->DMEM[addr + 0x001 + BES(0x000)] = VR_U(vt, e+0x1); + *(short *)(state->DMEM + addr + 0x002) = VR_S(vt, e+0x2); + state->DMEM[addr + 0x004 - BES(0x000)] = VR_A(vt, e+0x4); + addr += 0x005 + BES(0x000); + addr &= 0x00000FFF; + state->DMEM[addr] = VR_U(vt, e+0x5); + *(short *)(state->DMEM + addr + 0x001 - BES(0x000)) = VR_S(vt, 0x6); + return; + case 04: + *(short *)(state->DMEM + addr + HES(0x000)) = VR_S(vt, e+0x0); + *(short *)(state->DMEM + addr + HES(0x002)) = VR_S(vt, e+0x2); + addr = (addr + 0x004) & 0x00000FFF; + *(short *)(state->DMEM + addr + HES(0x000)) = VR_S(vt, e+0x4); + *(short *)(state->DMEM + addr + HES(0x002)) = VR_S(vt, e+0x6); + return; + case 05: /* "Tetrisphere" audio ucode */ + *(short *)(state->DMEM + addr + 0x000) = VR_S(vt, e+0x0); + state->DMEM[addr + 0x002 - BES(0x000)] = VR_A(vt, e+0x2); + addr = (addr + 0x003) & 0x00000FFF; + state->DMEM[addr + BES(0x000)] = VR_U(vt, e+0x3); + *(short *)(state->DMEM + addr + 0x001) = VR_S(vt, e+0x4); + state->DMEM[addr + BES(0x003)] = VR_A(vt, e+0x6); + state->DMEM[addr + BES(0x004)] = VR_U(vt, e+0x7); + return; + case 06: + *(short *)(state->DMEM + addr - HES(0x000)) = VR_S(vt, e+0x0); + addr = (addr + 0x002) & 0x00000FFF; + *(short *)(state->DMEM + addr + HES(0x000)) = VR_S(vt, e+0x2); + *(short *)(state->DMEM + addr + HES(0x002)) = VR_S(vt, e+0x4); + *(short *)(state->DMEM + addr + HES(0x004)) = VR_S(vt, e+0x6); + return; + case 07: /* "Tetrisphere" audio ucode */ + state->DMEM[addr - BES(0x000)] = VR_A(vt, e+0x0); + addr = (addr + 0x001) & 0x00000FFF; + state->DMEM[addr + BES(0x000)] = VR_U(vt, e+0x1); + *(short *)(state->DMEM + addr + 0x001) = VR_S(vt, e+0x2); + state->DMEM[addr + BES(0x003)] = VR_A(vt, e+0x4); + state->DMEM[addr + BES(0x004)] = VR_U(vt, e+0x5); + *(short *)(state->DMEM + addr + 0x005) = VR_S(vt, e+0x6); + return; + } +} + +/* + * Group II vector loads and stores: + * PV and UV (As of RCP implementation, XV and ZV are reserved opcodes.) + */ +INLINE static void LPV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + register int b; + const int e = element; + + if (e != 0x0) + { + message("LPV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 8*offset) & 0x00000FFF; + b = addr & 07; + addr &= ~07; + switch (b) + { + case 00: + state->VR[vt][07] = state->DMEM[addr + BES(0x007)] << 8; + state->VR[vt][06] = state->DMEM[addr + BES(0x006)] << 8; + state->VR[vt][05] = state->DMEM[addr + BES(0x005)] << 8; + state->VR[vt][04] = state->DMEM[addr + BES(0x004)] << 8; + state->VR[vt][03] = state->DMEM[addr + BES(0x003)] << 8; + state->VR[vt][02] = state->DMEM[addr + BES(0x002)] << 8; + state->VR[vt][01] = state->DMEM[addr + BES(0x001)] << 8; + state->VR[vt][00] = state->DMEM[addr + BES(0x000)] << 8; + return; + case 01: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->VR[vt][00] = state->DMEM[addr + BES(0x001)] << 8; + state->VR[vt][01] = state->DMEM[addr + BES(0x002)] << 8; + state->VR[vt][02] = state->DMEM[addr + BES(0x003)] << 8; + state->VR[vt][03] = state->DMEM[addr + BES(0x004)] << 8; + state->VR[vt][04] = state->DMEM[addr + BES(0x005)] << 8; + state->VR[vt][05] = state->DMEM[addr + BES(0x006)] << 8; + state->VR[vt][06] = state->DMEM[addr + BES(0x007)] << 8; + addr += BES(0x008); + addr &= 0x00000FFF; + state->VR[vt][07] = state->DMEM[addr] << 8; + return; + case 02: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->VR[vt][00] = state->DMEM[addr + BES(0x002)] << 8; + state->VR[vt][01] = state->DMEM[addr + BES(0x003)] << 8; + state->VR[vt][02] = state->DMEM[addr + BES(0x004)] << 8; + state->VR[vt][03] = state->DMEM[addr + BES(0x005)] << 8; + state->VR[vt][04] = state->DMEM[addr + BES(0x006)] << 8; + state->VR[vt][05] = state->DMEM[addr + BES(0x007)] << 8; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][06] = state->DMEM[addr + BES(0x000)] << 8; + state->VR[vt][07] = state->DMEM[addr + BES(0x001)] << 8; + return; + case 03: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->VR[vt][00] = state->DMEM[addr + BES(0x003)] << 8; + state->VR[vt][01] = state->DMEM[addr + BES(0x004)] << 8; + state->VR[vt][02] = state->DMEM[addr + BES(0x005)] << 8; + state->VR[vt][03] = state->DMEM[addr + BES(0x006)] << 8; + state->VR[vt][04] = state->DMEM[addr + BES(0x007)] << 8; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][05] = state->DMEM[addr + BES(0x000)] << 8; + state->VR[vt][06] = state->DMEM[addr + BES(0x001)] << 8; + state->VR[vt][07] = state->DMEM[addr + BES(0x002)] << 8; + return; + case 04: /* "Resident Evil 2" in-game 3-D, F3DLX 2.08--"WWF No Mercy" */ + state->VR[vt][00] = state->DMEM[addr + BES(0x004)] << 8; + state->VR[vt][01] = state->DMEM[addr + BES(0x005)] << 8; + state->VR[vt][02] = state->DMEM[addr + BES(0x006)] << 8; + state->VR[vt][03] = state->DMEM[addr + BES(0x007)] << 8; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][04] = state->DMEM[addr + BES(0x000)] << 8; + state->VR[vt][05] = state->DMEM[addr + BES(0x001)] << 8; + state->VR[vt][06] = state->DMEM[addr + BES(0x002)] << 8; + state->VR[vt][07] = state->DMEM[addr + BES(0x003)] << 8; + return; + case 05: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->VR[vt][00] = state->DMEM[addr + BES(0x005)] << 8; + state->VR[vt][01] = state->DMEM[addr + BES(0x006)] << 8; + state->VR[vt][02] = state->DMEM[addr + BES(0x007)] << 8; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][03] = state->DMEM[addr + BES(0x000)] << 8; + state->VR[vt][04] = state->DMEM[addr + BES(0x001)] << 8; + state->VR[vt][05] = state->DMEM[addr + BES(0x002)] << 8; + state->VR[vt][06] = state->DMEM[addr + BES(0x003)] << 8; + state->VR[vt][07] = state->DMEM[addr + BES(0x004)] << 8; + return; + case 06: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->VR[vt][00] = state->DMEM[addr + BES(0x006)] << 8; + state->VR[vt][01] = state->DMEM[addr + BES(0x007)] << 8; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][02] = state->DMEM[addr + BES(0x000)] << 8; + state->VR[vt][03] = state->DMEM[addr + BES(0x001)] << 8; + state->VR[vt][04] = state->DMEM[addr + BES(0x002)] << 8; + state->VR[vt][05] = state->DMEM[addr + BES(0x003)] << 8; + state->VR[vt][06] = state->DMEM[addr + BES(0x004)] << 8; + state->VR[vt][07] = state->DMEM[addr + BES(0x005)] << 8; + return; + case 07: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->VR[vt][00] = state->DMEM[addr + BES(0x007)] << 8; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][01] = state->DMEM[addr + BES(0x000)] << 8; + state->VR[vt][02] = state->DMEM[addr + BES(0x001)] << 8; + state->VR[vt][03] = state->DMEM[addr + BES(0x002)] << 8; + state->VR[vt][04] = state->DMEM[addr + BES(0x003)] << 8; + state->VR[vt][05] = state->DMEM[addr + BES(0x004)] << 8; + state->VR[vt][06] = state->DMEM[addr + BES(0x005)] << 8; + state->VR[vt][07] = state->DMEM[addr + BES(0x006)] << 8; + return; + } +} +INLINE static void LUV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + register int b; + int e = element; + + addr = (state->SR[base] + 8*offset) & 0x00000FFF; + if (e != 0x0) + { /* "Mia Hamm Soccer 64" SP exception override (zilmar) */ + addr += -e & 0xF; + for (b = 0; b < 8; b++) + { + state->VR[vt][b] = state->DMEM[BES(addr &= 0x00000FFF)] << 7; + --e; + addr -= 16 * (e == 0x0); + ++addr; + } + return; + } + b = addr & 07; + addr &= ~07; + switch (b) + { + case 00: + state->VR[vt][07] = state->DMEM[addr + BES(0x007)] << 7; + state->VR[vt][06] = state->DMEM[addr + BES(0x006)] << 7; + state->VR[vt][05] = state->DMEM[addr + BES(0x005)] << 7; + state->VR[vt][04] = state->DMEM[addr + BES(0x004)] << 7; + state->VR[vt][03] = state->DMEM[addr + BES(0x003)] << 7; + state->VR[vt][02] = state->DMEM[addr + BES(0x002)] << 7; + state->VR[vt][01] = state->DMEM[addr + BES(0x001)] << 7; + state->VR[vt][00] = state->DMEM[addr + BES(0x000)] << 7; + return; + case 01: /* PKMN Puzzle League HVQM decoder */ + state->VR[vt][00] = state->DMEM[addr + BES(0x001)] << 7; + state->VR[vt][01] = state->DMEM[addr + BES(0x002)] << 7; + state->VR[vt][02] = state->DMEM[addr + BES(0x003)] << 7; + state->VR[vt][03] = state->DMEM[addr + BES(0x004)] << 7; + state->VR[vt][04] = state->DMEM[addr + BES(0x005)] << 7; + state->VR[vt][05] = state->DMEM[addr + BES(0x006)] << 7; + state->VR[vt][06] = state->DMEM[addr + BES(0x007)] << 7; + addr += BES(0x008); + addr &= 0x00000FFF; + state->VR[vt][07] = state->DMEM[addr] << 7; + return; + case 02: /* PKMN Puzzle League HVQM decoder */ + state->VR[vt][00] = state->DMEM[addr + BES(0x002)] << 7; + state->VR[vt][01] = state->DMEM[addr + BES(0x003)] << 7; + state->VR[vt][02] = state->DMEM[addr + BES(0x004)] << 7; + state->VR[vt][03] = state->DMEM[addr + BES(0x005)] << 7; + state->VR[vt][04] = state->DMEM[addr + BES(0x006)] << 7; + state->VR[vt][05] = state->DMEM[addr + BES(0x007)] << 7; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][06] = state->DMEM[addr + BES(0x000)] << 7; + state->VR[vt][07] = state->DMEM[addr + BES(0x001)] << 7; + return; + case 03: /* PKMN Puzzle League HVQM decoder */ + state->VR[vt][00] = state->DMEM[addr + BES(0x003)] << 7; + state->VR[vt][01] = state->DMEM[addr + BES(0x004)] << 7; + state->VR[vt][02] = state->DMEM[addr + BES(0x005)] << 7; + state->VR[vt][03] = state->DMEM[addr + BES(0x006)] << 7; + state->VR[vt][04] = state->DMEM[addr + BES(0x007)] << 7; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][05] = state->DMEM[addr + BES(0x000)] << 7; + state->VR[vt][06] = state->DMEM[addr + BES(0x001)] << 7; + state->VR[vt][07] = state->DMEM[addr + BES(0x002)] << 7; + return; + case 04: /* PKMN Puzzle League HVQM decoder */ + state->VR[vt][00] = state->DMEM[addr + BES(0x004)] << 7; + state->VR[vt][01] = state->DMEM[addr + BES(0x005)] << 7; + state->VR[vt][02] = state->DMEM[addr + BES(0x006)] << 7; + state->VR[vt][03] = state->DMEM[addr + BES(0x007)] << 7; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][04] = state->DMEM[addr + BES(0x000)] << 7; + state->VR[vt][05] = state->DMEM[addr + BES(0x001)] << 7; + state->VR[vt][06] = state->DMEM[addr + BES(0x002)] << 7; + state->VR[vt][07] = state->DMEM[addr + BES(0x003)] << 7; + return; + case 05: /* PKMN Puzzle League HVQM decoder */ + state->VR[vt][00] = state->DMEM[addr + BES(0x005)] << 7; + state->VR[vt][01] = state->DMEM[addr + BES(0x006)] << 7; + state->VR[vt][02] = state->DMEM[addr + BES(0x007)] << 7; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][03] = state->DMEM[addr + BES(0x000)] << 7; + state->VR[vt][04] = state->DMEM[addr + BES(0x001)] << 7; + state->VR[vt][05] = state->DMEM[addr + BES(0x002)] << 7; + state->VR[vt][06] = state->DMEM[addr + BES(0x003)] << 7; + state->VR[vt][07] = state->DMEM[addr + BES(0x004)] << 7; + return; + case 06: /* PKMN Puzzle League HVQM decoder */ + state->VR[vt][00] = state->DMEM[addr + BES(0x006)] << 7; + state->VR[vt][01] = state->DMEM[addr + BES(0x007)] << 7; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][02] = state->DMEM[addr + BES(0x000)] << 7; + state->VR[vt][03] = state->DMEM[addr + BES(0x001)] << 7; + state->VR[vt][04] = state->DMEM[addr + BES(0x002)] << 7; + state->VR[vt][05] = state->DMEM[addr + BES(0x003)] << 7; + state->VR[vt][06] = state->DMEM[addr + BES(0x004)] << 7; + state->VR[vt][07] = state->DMEM[addr + BES(0x005)] << 7; + return; + case 07: /* PKMN Puzzle League HVQM decoder */ + state->VR[vt][00] = state->DMEM[addr + BES(0x007)] << 7; + addr += 0x008; + addr &= 0x00000FFF; + state->VR[vt][01] = state->DMEM[addr + BES(0x000)] << 7; + state->VR[vt][02] = state->DMEM[addr + BES(0x001)] << 7; + state->VR[vt][03] = state->DMEM[addr + BES(0x002)] << 7; + state->VR[vt][04] = state->DMEM[addr + BES(0x003)] << 7; + state->VR[vt][05] = state->DMEM[addr + BES(0x004)] << 7; + state->VR[vt][06] = state->DMEM[addr + BES(0x005)] << 7; + state->VR[vt][07] = state->DMEM[addr + BES(0x006)] << 7; + return; + } +} +INLINE static void SPV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register int b; + register uint32_t addr; + const int e = element; + + if (e != 0x0) + { + message("SPV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 8*offset) & 0x00000FFF; + b = addr & 07; + addr &= ~07; + switch (b) + { + case 00: + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][07] >> 8); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][06] >> 8); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][05] >> 8); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][04] >> 8); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][03] >> 8); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][02] >> 8); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][01] >> 8); + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][00] >> 8); + return; + case 01: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][00] >> 8); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][01] >> 8); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][02] >> 8); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][03] >> 8); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][04] >> 8); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][05] >> 8); + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][06] >> 8); + addr += BES(0x008); + addr &= 0x00000FFF; + state->DMEM[addr] = (unsigned char)(state->VR[vt][07] >> 8); + return; + case 02: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][00] >> 8); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][01] >> 8); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][02] >> 8); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][03] >> 8); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][04] >> 8); + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][05] >> 8); + addr += 0x008; + addr &= 0x00000FFF; + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][06] >> 8); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][07] >> 8); + return; + case 03: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][00] >> 8); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][01] >> 8); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][02] >> 8); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][03] >> 8); + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][04] >> 8); + addr += 0x008; + addr &= 0x00000FFF; + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][05] >> 8); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][06] >> 8); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][07] >> 8); + return; + case 04: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][00] >> 8); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][01] >> 8); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][02] >> 8); + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][03] >> 8); + addr += 0x008; + addr &= 0x00000FFF; + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][04] >> 8); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][05] >> 8); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][06] >> 8); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][07] >> 8); + return; + case 05: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][00] >> 8); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][01] >> 8); + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][02] >> 8); + addr += 0x008; + addr &= 0x00000FFF; + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][03] >> 8); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][04] >> 8); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][05] >> 8); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][06] >> 8); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][07] >> 8); + return; + case 06: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][00] >> 8); + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][01] >> 8); + addr += 0x008; + addr &= 0x00000FFF; + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][02] >> 8); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][03] >> 8); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][04] >> 8); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][05] >> 8); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][06] >> 8); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][07] >> 8); + return; + case 07: /* F3DZEX 2.08J "Doubutsu no Mori" (Animal Forest) CFB layer */ + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][00] >> 8); + addr += 0x008; + addr &= 0x00000FFF; + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][01] >> 8); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][02] >> 8); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][03] >> 8); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][04] >> 8); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][05] >> 8); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][06] >> 8); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][07] >> 8); + return; + } +} +INLINE static void SUV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register int b; + register uint32_t addr; + const int e = element; + + if (e != 0x0) + { + message("SUV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 8*offset) & 0x00000FFF; + b = addr & 07; + addr &= ~07; + switch (b) + { + case 00: + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][07] >> 7); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][06] >> 7); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][05] >> 7); + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][04] >> 7); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][03] >> 7); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][02] >> 7); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][01] >> 7); + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][00] >> 7); + return; + case 04: /* "Indiana Jones and the Infernal Machine" in-game */ + state->DMEM[addr + BES(0x004)] = (unsigned char)(state->VR[vt][00] >> 7); + state->DMEM[addr + BES(0x005)] = (unsigned char)(state->VR[vt][01] >> 7); + state->DMEM[addr + BES(0x006)] = (unsigned char)(state->VR[vt][02] >> 7); + state->DMEM[addr + BES(0x007)] = (unsigned char)(state->VR[vt][03] >> 7); + addr += 0x008; + addr &= 0x00000FFF; + state->DMEM[addr + BES(0x000)] = (unsigned char)(state->VR[vt][04] >> 7); + state->DMEM[addr + BES(0x001)] = (unsigned char)(state->VR[vt][05] >> 7); + state->DMEM[addr + BES(0x002)] = (unsigned char)(state->VR[vt][06] >> 7); + state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][07] >> 7); + return; + default: /* Completely legal, just never seen it be done. */ + message("SUV\nWeird addr.", 3); + return; + } +} + +/* + * Group III vector loads and stores: + * HV, FV, and AV (As of RCP implementation, AV opcodes are reserved.) + */ +static void LHV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + if (e != 0x0) + { + message("LHV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (addr & 0x0000000E) + { + message("LHV\nIllegal addr.", 3); + return; + } + addr ^= MES(00); + state->VR[vt][07] = state->DMEM[addr + HES(0x00E)] << 7; + state->VR[vt][06] = state->DMEM[addr + HES(0x00C)] << 7; + state->VR[vt][05] = state->DMEM[addr + HES(0x00A)] << 7; + state->VR[vt][04] = state->DMEM[addr + HES(0x008)] << 7; + state->VR[vt][03] = state->DMEM[addr + HES(0x006)] << 7; + state->VR[vt][02] = state->DMEM[addr + HES(0x004)] << 7; + state->VR[vt][01] = state->DMEM[addr + HES(0x002)] << 7; + state->VR[vt][00] = state->DMEM[addr + HES(0x000)] << 7; + return; +} +NOINLINE static void LFV(usf_state_t * state, int vt, int element, int offset, int base) +{ /* Dummy implementation only: Do any games execute this? */ + char debugger[32]; + + sprintf(debugger, "%s $v%i[0x%X], 0x%03X($%i)", "LFV", + vt, element, offset & 0xFFF, base); + message(debugger, 3); + return; +} +static void SHV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + if (e != 0x0) + { + message("SHV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (addr & 0x0000000E) + { + message("SHV\nIllegal addr.", 3); + return; + } + addr ^= MES(00); + state->DMEM[addr + HES(0x00E)] = (unsigned char)(state->VR[vt][07] >> 7); + state->DMEM[addr + HES(0x00C)] = (unsigned char)(state->VR[vt][06] >> 7); + state->DMEM[addr + HES(0x00A)] = (unsigned char)(state->VR[vt][05] >> 7); + state->DMEM[addr + HES(0x008)] = (unsigned char)(state->VR[vt][04] >> 7); + state->DMEM[addr + HES(0x006)] = (unsigned char)(state->VR[vt][03] >> 7); + state->DMEM[addr + HES(0x004)] = (unsigned char)(state->VR[vt][02] >> 7); + state->DMEM[addr + HES(0x002)] = (unsigned char)(state->VR[vt][01] >> 7); + state->DMEM[addr + HES(0x000)] = (unsigned char)(state->VR[vt][00] >> 7); + return; +} +static void SFV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + const int e = element; + + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + addr &= 0x00000FF3; + addr ^= BES(00); + switch (e) + { + case 0x0: + state->DMEM[addr + 0x000] = (unsigned char)(state->VR[vt][00] >> 7); + state->DMEM[addr + 0x004] = (unsigned char)(state->VR[vt][01] >> 7); + state->DMEM[addr + 0x008] = (unsigned char)(state->VR[vt][02] >> 7); + state->DMEM[addr + 0x00C] = (unsigned char)(state->VR[vt][03] >> 7); + return; + case 0x8: + state->DMEM[addr + 0x000] = (unsigned char)(state->VR[vt][04] >> 7); + state->DMEM[addr + 0x004] = (unsigned char)(state->VR[vt][05] >> 7); + state->DMEM[addr + 0x008] = (unsigned char)(state->VR[vt][06] >> 7); + state->DMEM[addr + 0x00C] = (unsigned char)(state->VR[vt][07] >> 7); + return; + default: + message("SFV\nIllegal element.", 3); + return; + } +} + +/* + * Group IV vector loads and stores: + * QV and RV + */ +INLINE static void LQV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + register int b; + const int e = element; /* Boss Game Studios illegal elements */ + + if (e & 0x1) + { + message("LQV\nOdd element.", 3); + return; + } + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (addr & 0x00000001) + { + message("LQV\nOdd addr.", 3); + return; + } + b = addr & 0x0000000F; + addr &= ~0x0000000F; + switch (b/2) /* mistake in SGI patent regarding LQV */ + { + case 0x0/2: + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x000)); + VR_S(vt,e+0x2) = *(short *)(state->DMEM + addr + HES(0x002)); + VR_S(vt,e+0x4) = *(short *)(state->DMEM + addr + HES(0x004)); + VR_S(vt,e+0x6) = *(short *)(state->DMEM + addr + HES(0x006)); + VR_S(vt,e+0x8) = *(short *)(state->DMEM + addr + HES(0x008)); + VR_S(vt,e+0xA) = *(short *)(state->DMEM + addr + HES(0x00A)); + VR_S(vt,e+0xC) = *(short *)(state->DMEM + addr + HES(0x00C)); + VR_S(vt,e+0xE) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + case 0x2/2: + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x002)); + VR_S(vt,e+0x2) = *(short *)(state->DMEM + addr + HES(0x004)); + VR_S(vt,e+0x4) = *(short *)(state->DMEM + addr + HES(0x006)); + VR_S(vt,e+0x6) = *(short *)(state->DMEM + addr + HES(0x008)); + VR_S(vt,e+0x8) = *(short *)(state->DMEM + addr + HES(0x00A)); + VR_S(vt,e+0xA) = *(short *)(state->DMEM + addr + HES(0x00C)); + VR_S(vt,e+0xC) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + case 0x4/2: + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x004)); + VR_S(vt,e+0x2) = *(short *)(state->DMEM + addr + HES(0x006)); + VR_S(vt,e+0x4) = *(short *)(state->DMEM + addr + HES(0x008)); + VR_S(vt,e+0x6) = *(short *)(state->DMEM + addr + HES(0x00A)); + VR_S(vt,e+0x8) = *(short *)(state->DMEM + addr + HES(0x00C)); + VR_S(vt,e+0xA) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + case 0x6/2: + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x006)); + VR_S(vt,e+0x2) = *(short *)(state->DMEM + addr + HES(0x008)); + VR_S(vt,e+0x4) = *(short *)(state->DMEM + addr + HES(0x00A)); + VR_S(vt,e+0x6) = *(short *)(state->DMEM + addr + HES(0x00C)); + VR_S(vt,e+0x8) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + case 0x8/2: /* "Resident Evil 2" cinematics and Boss Game Studios */ + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x008)); + VR_S(vt,e+0x2) = *(short *)(state->DMEM + addr + HES(0x00A)); + VR_S(vt,e+0x4) = *(short *)(state->DMEM + addr + HES(0x00C)); + VR_S(vt,e+0x6) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + case 0xA/2: /* "Conker's Bad Fur Day" audio microcode by Rareware */ + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x00A)); + VR_S(vt,e+0x2) = *(short *)(state->DMEM + addr + HES(0x00C)); + VR_S(vt,e+0x4) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + case 0xC/2: /* "Conker's Bad Fur Day" audio microcode by Rareware */ + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x00C)); + VR_S(vt,e+0x2) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + case 0xE/2: /* "Conker's Bad Fur Day" audio microcode by Rareware */ + VR_S(vt,e+0x0) = *(short *)(state->DMEM + addr + HES(0x00E)); + return; + } +} +static void LRV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + register int b; + const int e = element; + + if (e != 0x0) + { + message("LRV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (addr & 0x00000001) + { + message("LRV\nOdd addr.", 3); + return; + } + b = addr & 0x0000000F; + addr &= ~0x0000000F; + switch (b/2) + { + case 0xE/2: + state->VR[vt][01] = *(short *)(state->DMEM + addr + HES(0x000)); + state->VR[vt][02] = *(short *)(state->DMEM + addr + HES(0x002)); + state->VR[vt][03] = *(short *)(state->DMEM + addr + HES(0x004)); + state->VR[vt][04] = *(short *)(state->DMEM + addr + HES(0x006)); + state->VR[vt][05] = *(short *)(state->DMEM + addr + HES(0x008)); + state->VR[vt][06] = *(short *)(state->DMEM + addr + HES(0x00A)); + state->VR[vt][07] = *(short *)(state->DMEM + addr + HES(0x00C)); + return; + case 0xC/2: + state->VR[vt][02] = *(short *)(state->DMEM + addr + HES(0x000)); + state->VR[vt][03] = *(short *)(state->DMEM + addr + HES(0x002)); + state->VR[vt][04] = *(short *)(state->DMEM + addr + HES(0x004)); + state->VR[vt][05] = *(short *)(state->DMEM + addr + HES(0x006)); + state->VR[vt][06] = *(short *)(state->DMEM + addr + HES(0x008)); + state->VR[vt][07] = *(short *)(state->DMEM + addr + HES(0x00A)); + return; + case 0xA/2: + state->VR[vt][03] = *(short *)(state->DMEM + addr + HES(0x000)); + state->VR[vt][04] = *(short *)(state->DMEM + addr + HES(0x002)); + state->VR[vt][05] = *(short *)(state->DMEM + addr + HES(0x004)); + state->VR[vt][06] = *(short *)(state->DMEM + addr + HES(0x006)); + state->VR[vt][07] = *(short *)(state->DMEM + addr + HES(0x008)); + return; + case 0x8/2: + state->VR[vt][04] = *(short *)(state->DMEM + addr + HES(0x000)); + state->VR[vt][05] = *(short *)(state->DMEM + addr + HES(0x002)); + state->VR[vt][06] = *(short *)(state->DMEM + addr + HES(0x004)); + state->VR[vt][07] = *(short *)(state->DMEM + addr + HES(0x006)); + return; + case 0x6/2: + state->VR[vt][05] = *(short *)(state->DMEM + addr + HES(0x000)); + state->VR[vt][06] = *(short *)(state->DMEM + addr + HES(0x002)); + state->VR[vt][07] = *(short *)(state->DMEM + addr + HES(0x004)); + return; + case 0x4/2: + state->VR[vt][06] = *(short *)(state->DMEM + addr + HES(0x000)); + state->VR[vt][07] = *(short *)(state->DMEM + addr + HES(0x002)); + return; + case 0x2/2: + state->VR[vt][07] = *(short *)(state->DMEM + addr + HES(0x000)); + return; + case 0x0/2: + return; + } +} +INLINE static void SQV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + register int b; + const int e = element; + + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (e != 0x0) + { /* happens with "Mia Hamm Soccer 64" */ + register int i; + + for (i = 0; i < 16 - addr%16; i++) + state->DMEM[BES((addr + i) & 0xFFF)] = VR_B(vt, (e + i) & 0xF); + return; + } + b = addr & 0x0000000F; + addr &= ~0x0000000F; + switch (b) + { + case 00: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][00]; + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][01]; + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][02]; + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][03]; + *(short *)(state->DMEM + addr + HES(0x008)) = state->VR[vt][04]; + *(short *)(state->DMEM + addr + HES(0x00A)) = state->VR[vt][05]; + *(short *)(state->DMEM + addr + HES(0x00C)) = state->VR[vt][06]; + *(short *)(state->DMEM + addr + HES(0x00E)) = state->VR[vt][07]; + return; + case 02: + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][00]; + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][01]; + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][02]; + *(short *)(state->DMEM + addr + HES(0x008)) = state->VR[vt][03]; + *(short *)(state->DMEM + addr + HES(0x00A)) = state->VR[vt][04]; + *(short *)(state->DMEM + addr + HES(0x00C)) = state->VR[vt][05]; + *(short *)(state->DMEM + addr + HES(0x00E)) = state->VR[vt][06]; + return; + case 04: + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][00]; + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][01]; + *(short *)(state->DMEM + addr + HES(0x008)) = state->VR[vt][02]; + *(short *)(state->DMEM + addr + HES(0x00A)) = state->VR[vt][03]; + *(short *)(state->DMEM + addr + HES(0x00C)) = state->VR[vt][04]; + *(short *)(state->DMEM + addr + HES(0x00E)) = state->VR[vt][05]; + return; + case 06: + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][00]; + *(short *)(state->DMEM + addr + HES(0x008)) = state->VR[vt][01]; + *(short *)(state->DMEM + addr + HES(0x00A)) = state->VR[vt][02]; + *(short *)(state->DMEM + addr + HES(0x00C)) = state->VR[vt][03]; + *(short *)(state->DMEM + addr + HES(0x00E)) = state->VR[vt][04]; + return; + default: + message("SQV\nWeird addr.", 3); + return; + } +} +static void SRV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register uint32_t addr; + register int b; + const int e = element; + + if (e != 0x0) + { + message("SRV\nIllegal element.", 3); + return; + } + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (addr & 0x00000001) + { + message("SRV\nOdd addr.", 3); + return; + } + b = addr & 0x0000000F; + addr &= ~0x0000000F; + switch (b/2) + { + case 0xE/2: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][01]; + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][02]; + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][03]; + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][04]; + *(short *)(state->DMEM + addr + HES(0x008)) = state->VR[vt][05]; + *(short *)(state->DMEM + addr + HES(0x00A)) = state->VR[vt][06]; + *(short *)(state->DMEM + addr + HES(0x00C)) = state->VR[vt][07]; + return; + case 0xC/2: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][02]; + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][03]; + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][04]; + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][05]; + *(short *)(state->DMEM + addr + HES(0x008)) = state->VR[vt][06]; + *(short *)(state->DMEM + addr + HES(0x00A)) = state->VR[vt][07]; + return; + case 0xA/2: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][03]; + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][04]; + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][05]; + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][06]; + *(short *)(state->DMEM + addr + HES(0x008)) = state->VR[vt][07]; + return; + case 0x8/2: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][04]; + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][05]; + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][06]; + *(short *)(state->DMEM + addr + HES(0x006)) = state->VR[vt][07]; + return; + case 0x6/2: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][05]; + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][06]; + *(short *)(state->DMEM + addr + HES(0x004)) = state->VR[vt][07]; + return; + case 0x4/2: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][06]; + *(short *)(state->DMEM + addr + HES(0x002)) = state->VR[vt][07]; + return; + case 0x2/2: + *(short *)(state->DMEM + addr + HES(0x000)) = state->VR[vt][07]; + return; + case 0x0/2: + return; + } +} + +/* + * Group V vector loads and stores + * TV and SWV (As of RCP implementation, LTWV opcode was undesired.) + */ +INLINE static void LTV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register int i; + register uint32_t addr; + const int e = element; + + if (e & 1) + { + message("LTV\nIllegal element.", 3); + return; + } + if (vt & 07) + { + message("LTV\nUncertain case!", 3); + return; /* For LTV I am not sure; for STV I have an idea. */ + } + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (addr & 0x0000000F) + { + message("LTV\nIllegal addr.", 3); + return; + } + for (i = 0; i < 8; i++) /* SGI screwed LTV up on N64. See STV instead. */ + state->VR[vt+i][(-e/2 + i) & 07] = *(short *)(state->DMEM + addr + HES(2*i)); + return; +} +NOINLINE static void SWV(usf_state_t * state, int vt, int element, int offset, int base) +{ /* Dummy implementation only: Do any games execute this? */ + char debugger[32]; + + sprintf(debugger, "%s $v%i[0x%X], 0x%03X($%i)", "SWV", + vt, element, offset & 0xFFF, base); + message(debugger, 3); + return; +} +INLINE static void STV(usf_state_t * state, int vt, int element, int offset, int base) +{ + register int i; + register uint32_t addr; + const int e = element; + + if (e & 1) + { + message("STV\nIllegal element.", 3); + return; + } + if (vt & 07) + { + message("STV\nUncertain case!", 2); + return; /* vt &= 030; */ + } + addr = (state->SR[base] + 16*offset) & 0x00000FFF; + if (addr & 0x0000000F) + { + message("STV\nIllegal addr.", 3); + return; + } + for (i = 0; i < 8; i++) + *(short *)(state->DMEM + addr + HES(2*i)) = state->VR[vt + (e/2 + i)%8][i]; + return; +} + +/*** Modern pseudo-operations (not real instructions, but nice shortcuts) ***/ +void ULW(usf_state_t * state, int rd, uint32_t addr) +{ /* "Unaligned Load Word" */ + if (addr & 0x00000001) + { + SR_temp.B[03] = state->DMEM[BES(addr)]; + addr = (addr + 0x001) & 0xFFF; + SR_temp.B[02] = state->DMEM[BES(addr)]; + addr = (addr + 0x001) & 0xFFF; + SR_temp.B[01] = state->DMEM[BES(addr)]; + addr = (addr + 0x001) & 0xFFF; + SR_temp.B[00] = state->DMEM[BES(addr)]; + } + else /* addr & 0x00000002 */ + { + SR_temp.H[01] = *(short *)(state->DMEM + addr - HES(0x000)); + addr = (addr + 0x002) & 0xFFF; + SR_temp.H[00] = *(short *)(state->DMEM + addr + HES(0x000)); + } + state->SR[rd] = SR_temp.W; + /* state->SR[0] = 0x00000000; */ + return; +} +void USW(usf_state_t * state, int rs, uint32_t addr) +{ /* "Unaligned Store Word" */ + SR_temp.W = state->SR[rs]; + if (addr & 0x00000001) + { + state->DMEM[BES(addr)] = SR_temp.B[03]; + addr = (addr + 0x001) & 0xFFF; + state->DMEM[BES(addr)] = SR_temp.B[02]; + addr = (addr + 0x001) & 0xFFF; + state->DMEM[BES(addr)] = SR_temp.B[01]; + addr = (addr + 0x001) & 0xFFF; + state->DMEM[BES(addr)] = SR_temp.B[00]; + } + else /* addr & 0x00000002 */ + { + *(short *)(state->DMEM + addr - HES(0x000)) = SR_temp.H[01]; + addr = (addr + 0x002) & 0xFFF; + *(short *)(state->DMEM + addr + HES(0x000)) = SR_temp.H[00]; + } + return; +} + +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/cf.h b/Frameworks/lazyusf/lazyusf/rsp/vu/cf.h new file mode 100644 index 000000000..d4b31a910 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/cf.h @@ -0,0 +1,191 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.12.04 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#ifndef _CF_H +#define _CF_H + +/* + * For a non-cycle-accurate RSP emulator using SSE2, the following + * scalar definitions of the control registers are obsolete. + */ +#if (0) +/* + * Many vector units have pairs of "vector condition flags" registers. + * In SGI's vector unit implementation, these are denoted as the + * "vector control registers" under coprocessor 2. + * + * VCF-0 is the carry-out flags register: $vco. + * VCF-1 is the compare code flags register: $vcc. + * VCF-2 is the compare extension flags register: $vce. + * There is no fourth RSP flags register. + */ + +unsigned short VCO; +unsigned short VCC; +unsigned char VCE; +#endif + +/* + * These normally should have type `int` because they are Boolean T/F arrays. + * However, since SSE2 uses 128-bit XMM's, and Win32 `int` storage is 32-bit, + * we have the problem of 32*8 > 128 bits, so we use `short` to reduce packs. + */ + +#ifndef ARCH_MIN_SSE2 +unsigned short get_VCO(usf_state_t * state) +{ + register unsigned short VCO; + + VCO = 0x0000 + | (state->ne[0xF % 8] << 0xF) + | (state->ne[0xE % 8] << 0xE) + | (state->ne[0xD % 8] << 0xD) + | (state->ne[0xC % 8] << 0xC) + | (state->ne[0xB % 8] << 0xB) + | (state->ne[0xA % 8] << 0xA) + | (state->ne[0x9 % 8] << 0x9) + | (state->ne[0x8 % 8] << 0x8) + | (state->co[0x7 % 8] << 0x7) + | (state->co[0x6 % 8] << 0x6) + | (state->co[0x5 % 8] << 0x5) + | (state->co[0x4 % 8] << 0x4) + | (state->co[0x3 % 8] << 0x3) + | (state->co[0x2 % 8] << 0x2) + | (state->co[0x1 % 8] << 0x1) + | (state->co[0x0 % 8] << 0x0); + return (VCO); /* Big endian becomes little. */ +} +unsigned short get_VCC(usf_state_t * state) +{ + register unsigned short VCC; + + VCC = 0x0000 + | (state->clip[0xF % 8] << 0xF) + | (state->clip[0xE % 8] << 0xE) + | (state->clip[0xD % 8] << 0xD) + | (state->clip[0xC % 8] << 0xC) + | (state->clip[0xB % 8] << 0xB) + | (state->clip[0xA % 8] << 0xA) + | (state->clip[0x9 % 8] << 0x9) + | (state->clip[0x8 % 8] << 0x8) + | (state->comp[0x7 % 8] << 0x7) + | (state->comp[0x6 % 8] << 0x6) + | (state->comp[0x5 % 8] << 0x5) + | (state->comp[0x4 % 8] << 0x4) + | (state->comp[0x3 % 8] << 0x3) + | (state->comp[0x2 % 8] << 0x2) + | (state->comp[0x1 % 8] << 0x1) + | (state->comp[0x0 % 8] << 0x0); + return (VCC); /* Big endian becomes little. */ +} +unsigned char get_VCE(usf_state_t * state) +{ + register unsigned char VCE; + + VCE = 0x00 + | (state->vce[07] << 0x7) + | (state->vce[06] << 0x6) + | (state->vce[05] << 0x5) + | (state->vce[04] << 0x4) + | (state->vce[03] << 0x3) + | (state->vce[02] << 0x2) + | (state->vce[01] << 0x1) + | (state->vce[00] << 0x0); + return (VCE); /* Big endian becomes little. */ +} +#else +unsigned short get_VCO(usf_state_t * state) +{ + __m128i xmm, hi, lo; + register unsigned short VCO; + + hi = _mm_load_si128((__m128i *)state->ne); + lo = _mm_load_si128((__m128i *)state->co); + +/* + * Rotate Boolean storage from LSB to MSB. + */ + hi = _mm_slli_epi16(hi, 15); + lo = _mm_slli_epi16(lo, 15); + + xmm = _mm_packs_epi16(lo, hi); /* Decompress INT16 Booleans to INT8 ones. */ + VCO = _mm_movemask_epi8(xmm) & 0x0000FFFF; /* PMOVMSKB combines each MSB. */ + return (VCO); +} +unsigned short get_VCC(usf_state_t * state) +{ + __m128i xmm, hi, lo; + register unsigned short VCC; + + hi = _mm_load_si128((__m128i *)state->clip); + lo = _mm_load_si128((__m128i *)state->comp); + +/* + * Rotate Boolean storage from LSB to MSB. + */ + hi = _mm_slli_epi16(hi, 15); + lo = _mm_slli_epi16(lo, 15); + + xmm = _mm_packs_epi16(lo, hi); /* Decompress INT16 Booleans to INT8 ones. */ + VCC = _mm_movemask_epi8(xmm) & 0x0000FFFF; /* PMOVMSKB combines each MSB. */ + return (VCC); +} +unsigned char get_VCE(usf_state_t * state) +{ + __m128i xmm, hi, lo; + register unsigned char VCE; + + hi = _mm_setzero_si128(); + lo = _mm_load_si128((__m128i *)state->vce); + + lo = _mm_slli_epi16(lo, 15); /* Rotate Boolean storage from LSB to MSB. */ + + xmm = _mm_packs_epi16(lo, hi); /* Decompress INT16 Booleans to INT8 ones. */ + VCE = _mm_movemask_epi8(xmm) & 0x000000FF; /* PMOVMSKB combines each MSB. */ + return (VCE); +} +#endif + +/* + * CTC2 resources + * not sure how to vectorize going the other direction into SSE2 + */ +void set_VCO(usf_state_t * state, unsigned short VCO) +{ + register int i; + + for (i = 0; i < 8; i++) + state->co[i] = (VCO >> (i + 0x0)) & 1; + for (i = 0; i < 8; i++) + state->ne[i] = (VCO >> (i + 0x8)) & 1; + return; /* Little endian becomes big. */ +} +void set_VCC(usf_state_t * state, unsigned short VCC) +{ + register int i; + + for (i = 0; i < 8; i++) + state->comp[i] = (VCC >> (i + 0x0)) & 1; + for (i = 0; i < 8; i++) + state->clip[i] = (VCC >> (i + 0x8)) & 1; + return; /* Little endian becomes big. */ +} +void set_VCE(usf_state_t * state, unsigned char VCE) +{ + register int i; + + for (i = 0; i < 8; i++) + state->vce[i] = (VCE >> i) & 1; + return; /* Little endian becomes big. */ +} +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/clamp.h b/Frameworks/lazyusf/lazyusf/rsp/vu/clamp.h new file mode 100644 index 000000000..8a8b2ce2b --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/clamp.h @@ -0,0 +1,255 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.10.07 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#ifndef _CLAMP_H +#define _CLAMP_H + +/* + * for ANSI compliance (null INLINE attribute if not already set to `inline`) + * Include "rsp.h" for active, non-ANSI inline definition. + */ +#ifndef INLINE +#define INLINE +#endif + +/* + * dependency for 48-bit accumulator access + */ +#include "vu.h" + +/* + * vector select merge (`VMRG`) formula + * + * This is really just a vectorizer for ternary conditional storage. + * I've named it so because it directly maps to the VMRG op-code. + * -- example -- + * for (i = 0; i < N; i++) + * if (c_pass) + * dest = element_a; + * else + * dest = element_b; + */ +static INLINE void merge(short* VD, short* cmp, short* pass, short* fail) +{ + register int i; +#if (0) +/* Do not use this version yet, as it still does not vectorize to SSE2. */ + for (i = 0; i < N; i++) + VD[i] = (cmp[i] != 0) ? pass[i] : fail[i]; +#else + short diff[N]; + + for (i = 0; i < N; i++) + diff[i] = pass[i] - fail[i]; + for (i = 0; i < N; i++) + VD[i] = fail[i] + cmp[i]*diff[i]; /* actually `(cmp[i] != 0)*diff[i]` */ +#endif + return; +} + +#ifndef ARCH_MIN_SSE2 +static INLINE void vector_copy(short* VD, short* VS) +{ +#if (0) + memcpy(VD, VS, N*sizeof(short)); +#else + register int i; + + for (i = 0; i < N; i++) + VD[i] = VS[i]; +#endif + return; +} + +static INLINE void SIGNED_CLAMP_ADD(usf_state_t * state, short* VD, short* VS, short* VT) +{ + int32_t sum[N]; + short hi[N], lo[N]; + register int i; + + for (i = 0; i < N; i++) + sum[i] = VS[i] + VT[i] + state->co[i]; + for (i = 0; i < N; i++) + lo[i] = (sum[i] + 0x8000) >> 31; + for (i = 0; i < N; i++) + hi[i] = (0x7FFF - sum[i]) >> 31; + vector_copy(VD, VACC_L); + for (i = 0; i < N; i++) + VD[i] &= ~lo[i]; + for (i = 0; i < N; i++) + VD[i] |= hi[i]; + for (i = 0; i < N; i++) + VD[i] ^= 0x8000 & (hi[i] | lo[i]); + return; +} +static INLINE void SIGNED_CLAMP_SUB(usf_state_t * state, short* VD, short* VS, short* VT) +{ + int32_t dif[N]; + short hi[N], lo[N]; + register int i; + + for (i = 0; i < N; i++) + dif[i] = VS[i] - VT[i] - state->co[i]; + for (i = 0; i < N; i++) + lo[i] = (dif[i] + 0x8000) >> 31; + for (i = 0; i < N; i++) + hi[i] = (0x7FFF - dif[i]) >> 31; + vector_copy(VD, VACC_L); + for (i = 0; i < N; i++) + VD[i] &= ~lo[i]; + for (i = 0; i < N; i++) + VD[i] |= hi[i]; + for (i = 0; i < N; i++) + VD[i] ^= 0x8000 & (hi[i] | lo[i]); + return; +} +static INLINE void SIGNED_CLAMP_AM(usf_state_t * state, short* VD) +{ /* typical sign-clamp of accumulator-mid (bits 31:16) */ + short hi[N], lo[N]; + register int i; + + for (i = 0; i < N; i++) + lo[i] = (VACC_H[i] < ~0); + for (i = 0; i < N; i++) + lo[i] |= (VACC_H[i] < 0) & !(VACC_M[i] < 0); + for (i = 0; i < N; i++) + hi[i] = (VACC_H[i] > 0); + for (i = 0; i < N; i++) + hi[i] |= (VACC_H[i] == 0) & (VACC_M[i] < 0); + vector_copy(VD, VACC_M); + for (i = 0; i < N; i++) + VD[i] &= -(lo[i] ^ 1); + for (i = 0; i < N; i++) + VD[i] |= -(hi[i] ^ 0); + for (i = 0; i < N; i++) + VD[i] ^= 0x8000 * (hi[i] | lo[i]); + return; +} +#else +/* + * We actually need to write explicit SSE2 code for this because GCC 4.8.1 + * (and possibly later versions) has a code generation bug with vectorizing + * the accumulator when it's a signed short (but not when it's unsigned, for + * some stupid and buggy reason). + * + * In addition, as of the more stable GCC 4.7.2 release, while vectorizing + * the accumulator write-backs into SSE2 for me is successfully done, we save + * just one extra scalar x86 instruction for every RSP vector op-code when we + * use SSE2 explicitly for this particular goal instead of letting GCC do it. + */ +static INLINE void vector_copy(short* VD, short* VS) +{ + __m128i xmm; + + xmm = _mm_load_si128((__m128i *)VS); + _mm_store_si128((__m128i *)VD, xmm); + return; +} + +static INLINE void SIGNED_CLAMP_ADD(usf_state_t * state, short* VD, short* VS, short* VT) +{ + __m128i dst, src, vco; + __m128i max, min; + + src = _mm_load_si128((__m128i *)VS); + dst = _mm_load_si128((__m128i *)VT); + vco = _mm_load_si128((__m128i *)state->co); + +/* + * Due to premature clamping in between adds, sometimes we need to add the + * LESSER of two integers, either VS or VT, to the carry-in flag matching the + * current vector register slice, BEFORE finally adding the greater integer. + */ + max = _mm_max_epi16(dst, src); + min = _mm_min_epi16(dst, src); + + min = _mm_adds_epi16(min, vco); + max = _mm_adds_epi16(max, min); + _mm_store_si128((__m128i *)VD, max); + return; +} +static INLINE void SIGNED_CLAMP_SUB(usf_state_t * state, short* VD, short* VS, short* VT) +{ + __m128i dst, src, vco; + __m128i dif, res, xmm; + + src = _mm_load_si128((__m128i *)VS); + dst = _mm_load_si128((__m128i *)VT); + vco = _mm_load_si128((__m128i *)state->co); + + res = _mm_subs_epi16(src, dst); + +/* + * Due to premature clamps in-between subtracting two of the three operands, + * we must be careful not to offset the result accidentally when subtracting + * the corresponding VCO flag AFTER the saturation from doing (VS - VT). + */ + dif = _mm_add_epi16(res, vco); + dif = _mm_xor_si128(dif, res); /* Adding one suddenly inverts the sign? */ + dif = _mm_and_si128(dif, dst); /* Sign change due to subtracting a neg. */ + xmm = _mm_sub_epi16(src, dst); + src = _mm_andnot_si128(src, dif); /* VS must be >= 0x0000 for overflow. */ + xmm = _mm_and_si128(xmm, src); /* VS + VT != INT16_MIN; VS + VT >= +32768 */ + xmm = _mm_srli_epi16(xmm, 15); /* src = (INT16_MAX + 1 === INT16_MIN) ? */ + + xmm = _mm_andnot_si128(xmm, vco); /* If it's NOT overflow, keep flag. */ + res = _mm_subs_epi16(res, xmm); + _mm_store_si128((__m128i *)VD, res); + return; +} +static INLINE void SIGNED_CLAMP_AM(usf_state_t * state, short* VD) +{ /* typical sign-clamp of accumulator-mid (bits 31:16) */ + __m128i dst, src; + __m128i pvd, pvs; + + pvs = _mm_load_si128((__m128i *)VACC_H); + pvd = _mm_load_si128((__m128i *)VACC_M); + dst = _mm_unpacklo_epi16(pvd, pvs); + src = _mm_unpackhi_epi16(pvd, pvs); + + dst = _mm_packs_epi32(dst, src); + _mm_store_si128((__m128i *)VD, dst); + return; +} +#endif + +static INLINE void UNSIGNED_CLAMP(usf_state_t * state, short* VD) +{ /* sign-zero hybrid clamp of accumulator-mid (bits 31:16) */ + short cond[N]; + short temp[N]; + register int i; + + SIGNED_CLAMP_AM(state, temp); /* no direct map in SSE, but closely based on this */ + for (i = 0; i < N; i++) + cond[i] = -(temp[i] > VACC_M[i]); /* VD |= -(ACC47..16 > +32767) */ + for (i = 0; i < N; i++) + VD[i] = temp[i] & ~(temp[i] >> 15); /* Only this clamp is unsigned. */ + for (i = 0; i < N; i++) + VD[i] = VD[i] | cond[i]; + return; +} +static INLINE void SIGNED_CLAMP_AL(usf_state_t * state, short* VD) +{ /* sign-clamp accumulator-low (bits 15:0) */ + short cond[N]; + short temp[N]; + register int i; + + SIGNED_CLAMP_AM(state, temp); /* no direct map in SSE, but closely based on this */ + for (i = 0; i < N; i++) + cond[i] = (temp[i] != VACC_M[i]); /* result_clamped != result_raw ? */ + for (i = 0; i < N; i++) + temp[i] ^= 0x8000; /* half-assed unsigned saturation mix in the clamp */ + merge(VD, cond, temp, VACC_L); + return; +} +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/divrom.h b/Frameworks/lazyusf/lazyusf/rsp/vu/divrom.h new file mode 100644 index 000000000..18f5aad52 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/divrom.h @@ -0,0 +1,1111 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#ifndef _DIVROM_H +#define _DIVROM_H + +/* + * Boolean flag: Double-precision high was the last vector divide op? + * + * if (lastDivideOp == VRCP, VRCPL, VRSQ, VRSQL) + * DPH = false; // single-precision or double-precision low, not high + * else if (lastDivideOp == VRCPH, VRSQH) + * DPH = true; // double-precision high + * else if (lastDivideOp == VMOV, VNOP) + * DPH = DPH; // no change, divide-group ops but not real divides + */ + +/* + * 11-bit vector divide result look-up table + * Thanks to MooglyGuy @ MESS for organizing. + */ +static const unsigned short div_ROM[1024] = { + 0xFFFF, + 0xFF00, + 0xFE01, + 0xFD04, + 0xFC07, + 0xFB0C, + 0xFA11, + 0xF918, + 0xF81F, + 0xF727, + 0xF631, + 0xF53B, + 0xF446, + 0xF352, + 0xF25F, + 0xF16D, + 0xF07C, + 0xEF8B, + 0xEE9C, + 0xEDAE, + 0xECC0, + 0xEBD3, + 0xEAE8, + 0xE9FD, + 0xE913, + 0xE829, + 0xE741, + 0xE65A, + 0xE573, + 0xE48D, + 0xE3A9, + 0xE2C5, + 0xE1E1, + 0xE0FF, + 0xE01E, + 0xDF3D, + 0xDE5D, + 0xDD7E, + 0xDCA0, + 0xDBC2, + 0xDAE6, + 0xDA0A, + 0xD92F, + 0xD854, + 0xD77B, + 0xD6A2, + 0xD5CA, + 0xD4F3, + 0xD41D, + 0xD347, + 0xD272, + 0xD19E, + 0xD0CB, + 0xCFF8, + 0xCF26, + 0xCE55, + 0xCD85, + 0xCCB5, + 0xCBE6, + 0xCB18, + 0xCA4B, + 0xC97E, + 0xC8B2, + 0xC7E7, + 0xC71C, + 0xC652, + 0xC589, + 0xC4C0, + 0xC3F8, + 0xC331, + 0xC26B, + 0xC1A5, + 0xC0E0, + 0xC01C, + 0xBF58, + 0xBE95, + 0xBDD2, + 0xBD10, + 0xBC4F, + 0xBB8F, + 0xBACF, + 0xBA10, + 0xB951, + 0xB894, + 0xB7D6, + 0xB71A, + 0xB65E, + 0xB5A2, + 0xB4E8, + 0xB42E, + 0xB374, + 0xB2BB, + 0xB203, + 0xB14B, + 0xB094, + 0xAFDE, + 0xAF28, + 0xAE73, + 0xADBE, + 0xAD0A, + 0xAC57, + 0xABA4, + 0xAAF1, + 0xAA40, + 0xA98E, + 0xA8DE, + 0xA82E, + 0xA77E, + 0xA6D0, + 0xA621, + 0xA574, + 0xA4C6, + 0xA41A, + 0xA36E, + 0xA2C2, + 0xA217, + 0xA16D, + 0xA0C3, + 0xA01A, + 0x9F71, + 0x9EC8, + 0x9E21, + 0x9D79, + 0x9CD3, + 0x9C2D, + 0x9B87, + 0x9AE2, + 0x9A3D, + 0x9999, + 0x98F6, + 0x9852, + 0x97B0, + 0x970E, + 0x966C, + 0x95CB, + 0x952B, + 0x948B, + 0x93EB, + 0x934C, + 0x92AD, + 0x920F, + 0x9172, + 0x90D4, + 0x9038, + 0x8F9C, + 0x8F00, + 0x8E65, + 0x8DCA, + 0x8D30, + 0x8C96, + 0x8BFC, + 0x8B64, + 0x8ACB, + 0x8A33, + 0x899C, + 0x8904, + 0x886E, + 0x87D8, + 0x8742, + 0x86AD, + 0x8618, + 0x8583, + 0x84F0, + 0x845C, + 0x83C9, + 0x8336, + 0x82A4, + 0x8212, + 0x8181, + 0x80F0, + 0x8060, + 0x7FD0, + 0x7F40, + 0x7EB1, + 0x7E22, + 0x7D93, + 0x7D05, + 0x7C78, + 0x7BEB, + 0x7B5E, + 0x7AD2, + 0x7A46, + 0x79BA, + 0x792F, + 0x78A4, + 0x781A, + 0x7790, + 0x7706, + 0x767D, + 0x75F5, + 0x756C, + 0x74E4, + 0x745D, + 0x73D5, + 0x734F, + 0x72C8, + 0x7242, + 0x71BC, + 0x7137, + 0x70B2, + 0x702E, + 0x6FA9, + 0x6F26, + 0x6EA2, + 0x6E1F, + 0x6D9C, + 0x6D1A, + 0x6C98, + 0x6C16, + 0x6B95, + 0x6B14, + 0x6A94, + 0x6A13, + 0x6993, + 0x6914, + 0x6895, + 0x6816, + 0x6798, + 0x6719, + 0x669C, + 0x661E, + 0x65A1, + 0x6524, + 0x64A8, + 0x642C, + 0x63B0, + 0x6335, + 0x62BA, + 0x623F, + 0x61C5, + 0x614B, + 0x60D1, + 0x6058, + 0x5FDF, + 0x5F66, + 0x5EED, + 0x5E75, + 0x5DFD, + 0x5D86, + 0x5D0F, + 0x5C98, + 0x5C22, + 0x5BAB, + 0x5B35, + 0x5AC0, + 0x5A4B, + 0x59D6, + 0x5961, + 0x58ED, + 0x5879, + 0x5805, + 0x5791, + 0x571E, + 0x56AC, + 0x5639, + 0x55C7, + 0x5555, + 0x54E3, + 0x5472, + 0x5401, + 0x5390, + 0x5320, + 0x52AF, + 0x5240, + 0x51D0, + 0x5161, + 0x50F2, + 0x5083, + 0x5015, + 0x4FA6, + 0x4F38, + 0x4ECB, + 0x4E5E, + 0x4DF1, + 0x4D84, + 0x4D17, + 0x4CAB, + 0x4C3F, + 0x4BD3, + 0x4B68, + 0x4AFD, + 0x4A92, + 0x4A27, + 0x49BD, + 0x4953, + 0x48E9, + 0x4880, + 0x4817, + 0x47AE, + 0x4745, + 0x46DC, + 0x4674, + 0x460C, + 0x45A5, + 0x453D, + 0x44D6, + 0x446F, + 0x4408, + 0x43A2, + 0x433C, + 0x42D6, + 0x4270, + 0x420B, + 0x41A6, + 0x4141, + 0x40DC, + 0x4078, + 0x4014, + 0x3FB0, + 0x3F4C, + 0x3EE8, + 0x3E85, + 0x3E22, + 0x3DC0, + 0x3D5D, + 0x3CFB, + 0x3C99, + 0x3C37, + 0x3BD6, + 0x3B74, + 0x3B13, + 0x3AB2, + 0x3A52, + 0x39F1, + 0x3991, + 0x3931, + 0x38D2, + 0x3872, + 0x3813, + 0x37B4, + 0x3755, + 0x36F7, + 0x3698, + 0x363A, + 0x35DC, + 0x357F, + 0x3521, + 0x34C4, + 0x3467, + 0x340A, + 0x33AE, + 0x3351, + 0x32F5, + 0x3299, + 0x323E, + 0x31E2, + 0x3187, + 0x312C, + 0x30D1, + 0x3076, + 0x301C, + 0x2FC2, + 0x2F68, + 0x2F0E, + 0x2EB4, + 0x2E5B, + 0x2E02, + 0x2DA9, + 0x2D50, + 0x2CF8, + 0x2C9F, + 0x2C47, + 0x2BEF, + 0x2B97, + 0x2B40, + 0x2AE8, + 0x2A91, + 0x2A3A, + 0x29E4, + 0x298D, + 0x2937, + 0x28E0, + 0x288B, + 0x2835, + 0x27DF, + 0x278A, + 0x2735, + 0x26E0, + 0x268B, + 0x2636, + 0x25E2, + 0x258D, + 0x2539, + 0x24E5, + 0x2492, + 0x243E, + 0x23EB, + 0x2398, + 0x2345, + 0x22F2, + 0x22A0, + 0x224D, + 0x21FB, + 0x21A9, + 0x2157, + 0x2105, + 0x20B4, + 0x2063, + 0x2012, + 0x1FC1, + 0x1F70, + 0x1F1F, + 0x1ECF, + 0x1E7F, + 0x1E2E, + 0x1DDF, + 0x1D8F, + 0x1D3F, + 0x1CF0, + 0x1CA1, + 0x1C52, + 0x1C03, + 0x1BB4, + 0x1B66, + 0x1B17, + 0x1AC9, + 0x1A7B, + 0x1A2D, + 0x19E0, + 0x1992, + 0x1945, + 0x18F8, + 0x18AB, + 0x185E, + 0x1811, + 0x17C4, + 0x1778, + 0x172C, + 0x16E0, + 0x1694, + 0x1648, + 0x15FD, + 0x15B1, + 0x1566, + 0x151B, + 0x14D0, + 0x1485, + 0x143B, + 0x13F0, + 0x13A6, + 0x135C, + 0x1312, + 0x12C8, + 0x127F, + 0x1235, + 0x11EC, + 0x11A3, + 0x1159, + 0x1111, + 0x10C8, + 0x107F, + 0x1037, + 0x0FEF, + 0x0FA6, + 0x0F5E, + 0x0F17, + 0x0ECF, + 0x0E87, + 0x0E40, + 0x0DF9, + 0x0DB2, + 0x0D6B, + 0x0D24, + 0x0CDD, + 0x0C97, + 0x0C50, + 0x0C0A, + 0x0BC4, + 0x0B7E, + 0x0B38, + 0x0AF2, + 0x0AAD, + 0x0A68, + 0x0A22, + 0x09DD, + 0x0998, + 0x0953, + 0x090F, + 0x08CA, + 0x0886, + 0x0842, + 0x07FD, + 0x07B9, + 0x0776, + 0x0732, + 0x06EE, + 0x06AB, + 0x0668, + 0x0624, + 0x05E1, + 0x059E, + 0x055C, + 0x0519, + 0x04D6, + 0x0494, + 0x0452, + 0x0410, + 0x03CE, + 0x038C, + 0x034A, + 0x0309, + 0x02C7, + 0x0286, + 0x0245, + 0x0204, + 0x01C3, + 0x0182, + 0x0141, + 0x0101, + 0x00C0, + 0x0080, + 0x0040, + 0x6A09, + 0xFFFF, + 0x6955, + 0xFF00, + 0x68A1, + 0xFE02, + 0x67EF, + 0xFD06, + 0x673E, + 0xFC0B, + 0x668D, + 0xFB12, + 0x65DE, + 0xFA1A, + 0x6530, + 0xF923, + 0x6482, + 0xF82E, + 0x63D6, + 0xF73B, + 0x632B, + 0xF648, + 0x6280, + 0xF557, + 0x61D7, + 0xF467, + 0x612E, + 0xF379, + 0x6087, + 0xF28C, + 0x5FE0, + 0xF1A0, + 0x5F3A, + 0xF0B6, + 0x5E95, + 0xEFCD, + 0x5DF1, + 0xEEE5, + 0x5D4E, + 0xEDFF, + 0x5CAC, + 0xED19, + 0x5C0B, + 0xEC35, + 0x5B6B, + 0xEB52, + 0x5ACB, + 0xEA71, + 0x5A2C, + 0xE990, + 0x598F, + 0xE8B1, + 0x58F2, + 0xE7D3, + 0x5855, + 0xE6F6, + 0x57BA, + 0xE61B, + 0x5720, + 0xE540, + 0x5686, + 0xE467, + 0x55ED, + 0xE38E, + 0x5555, + 0xE2B7, + 0x54BE, + 0xE1E1, + 0x5427, + 0xE10D, + 0x5391, + 0xE039, + 0x52FC, + 0xDF66, + 0x5268, + 0xDE94, + 0x51D5, + 0xDDC4, + 0x5142, + 0xDCF4, + 0x50B0, + 0xDC26, + 0x501F, + 0xDB59, + 0x4F8E, + 0xDA8C, + 0x4EFE, + 0xD9C1, + 0x4E6F, + 0xD8F7, + 0x4DE1, + 0xD82D, + 0x4D53, + 0xD765, + 0x4CC6, + 0xD69E, + 0x4C3A, + 0xD5D7, + 0x4BAF, + 0xD512, + 0x4B24, + 0xD44E, + 0x4A9A, + 0xD38A, + 0x4A10, + 0xD2C8, + 0x4987, + 0xD206, + 0x48FF, + 0xD146, + 0x4878, + 0xD086, + 0x47F1, + 0xCFC7, + 0x476B, + 0xCF0A, + 0x46E5, + 0xCE4D, + 0x4660, + 0xCD91, + 0x45DC, + 0xCCD6, + 0x4558, + 0xCC1B, + 0x44D5, + 0xCB62, + 0x4453, + 0xCAA9, + 0x43D1, + 0xC9F2, + 0x434F, + 0xC93B, + 0x42CF, + 0xC885, + 0x424F, + 0xC7D0, + 0x41CF, + 0xC71C, + 0x4151, + 0xC669, + 0x40D2, + 0xC5B6, + 0x4055, + 0xC504, + 0x3FD8, + 0xC453, + 0x3F5B, + 0xC3A3, + 0x3EDF, + 0xC2F4, + 0x3E64, + 0xC245, + 0x3DE9, + 0xC198, + 0x3D6E, + 0xC0EB, + 0x3CF5, + 0xC03F, + 0x3C7C, + 0xBF93, + 0x3C03, + 0xBEE9, + 0x3B8B, + 0xBE3F, + 0x3B13, + 0xBD96, + 0x3A9C, + 0xBCED, + 0x3A26, + 0xBC46, + 0x39B0, + 0xBB9F, + 0x393A, + 0xBAF8, + 0x38C5, + 0xBA53, + 0x3851, + 0xB9AE, + 0x37DD, + 0xB90A, + 0x3769, + 0xB867, + 0x36F6, + 0xB7C5, + 0x3684, + 0xB723, + 0x3612, + 0xB681, + 0x35A0, + 0xB5E1, + 0x352F, + 0xB541, + 0x34BF, + 0xB4A2, + 0x344F, + 0xB404, + 0x33DF, + 0xB366, + 0x3370, + 0xB2C9, + 0x3302, + 0xB22C, + 0x3293, + 0xB191, + 0x3226, + 0xB0F5, + 0x31B9, + 0xB05B, + 0x314C, + 0xAFC1, + 0x30DF, + 0xAF28, + 0x3074, + 0xAE8F, + 0x3008, + 0xADF7, + 0x2F9D, + 0xAD60, + 0x2F33, + 0xACC9, + 0x2EC8, + 0xAC33, + 0x2E5F, + 0xAB9E, + 0x2DF6, + 0xAB09, + 0x2D8D, + 0xAA75, + 0x2D24, + 0xA9E1, + 0x2CBC, + 0xA94E, + 0x2C55, + 0xA8BC, + 0x2BEE, + 0xA82A, + 0x2B87, + 0xA799, + 0x2B21, + 0xA708, + 0x2ABB, + 0xA678, + 0x2A55, + 0xA5E8, + 0x29F0, + 0xA559, + 0x298B, + 0xA4CB, + 0x2927, + 0xA43D, + 0x28C3, + 0xA3B0, + 0x2860, + 0xA323, + 0x27FD, + 0xA297, + 0x279A, + 0xA20B, + 0x2738, + 0xA180, + 0x26D6, + 0xA0F6, + 0x2674, + 0xA06C, + 0x2613, + 0x9FE2, + 0x25B2, + 0x9F59, + 0x2552, + 0x9ED1, + 0x24F2, + 0x9E49, + 0x2492, + 0x9DC2, + 0x2432, + 0x9D3B, + 0x23D3, + 0x9CB4, + 0x2375, + 0x9C2F, + 0x2317, + 0x9BA9, + 0x22B9, + 0x9B25, + 0x225B, + 0x9AA0, + 0x21FE, + 0x9A1C, + 0x21A1, + 0x9999, + 0x2145, + 0x9916, + 0x20E8, + 0x9894, + 0x208D, + 0x9812, + 0x2031, + 0x9791, + 0x1FD6, + 0x9710, + 0x1F7B, + 0x968F, + 0x1F21, + 0x960F, + 0x1EC7, + 0x9590, + 0x1E6D, + 0x9511, + 0x1E13, + 0x9492, + 0x1DBA, + 0x9414, + 0x1D61, + 0x9397, + 0x1D09, + 0x931A, + 0x1CB1, + 0x929D, + 0x1C59, + 0x9221, + 0x1C01, + 0x91A5, + 0x1BAA, + 0x9129, + 0x1B53, + 0x90AF, + 0x1AFC, + 0x9034, + 0x1AA6, + 0x8FBA, + 0x1A50, + 0x8F40, + 0x19FA, + 0x8EC7, + 0x19A5, + 0x8E4F, + 0x1950, + 0x8DD6, + 0x18FB, + 0x8D5E, + 0x18A7, + 0x8CE7, + 0x1853, + 0x8C70, + 0x17FF, + 0x8BF9, + 0x17AB, + 0x8B83, + 0x1758, + 0x8B0D, + 0x1705, + 0x8A98, + 0x16B2, + 0x8A23, + 0x1660, + 0x89AE, + 0x160D, + 0x893A, + 0x15BC, + 0x88C6, + 0x156A, + 0x8853, + 0x1519, + 0x87E0, + 0x14C8, + 0x876D, + 0x1477, + 0x86FB, + 0x1426, + 0x8689, + 0x13D6, + 0x8618, + 0x1386, + 0x85A7, + 0x1337, + 0x8536, + 0x12E7, + 0x84C6, + 0x1298, + 0x8456, + 0x1249, + 0x83E7, + 0x11FB, + 0x8377, + 0x11AC, + 0x8309, + 0x115E, + 0x829A, + 0x1111, + 0x822C, + 0x10C3, + 0x81BF, + 0x1076, + 0x8151, + 0x1029, + 0x80E4, + 0x0FDC, + 0x8078, + 0x0F8F, + 0x800C, + 0x0F43, + 0x7FA0, + 0x0EF7, + 0x7F34, + 0x0EAB, + 0x7EC9, + 0x0E60, + 0x7E5E, + 0x0E15, + 0x7DF4, + 0x0DCA, + 0x7D8A, + 0x0D7F, + 0x7D20, + 0x0D34, + 0x7CB6, + 0x0CEA, + 0x7C4D, + 0x0CA0, + 0x7BE5, + 0x0C56, + 0x7B7C, + 0x0C0C, + 0x7B14, + 0x0BC3, + 0x7AAC, + 0x0B7A, + 0x7A45, + 0x0B31, + 0x79DE, + 0x0AE8, + 0x7977, + 0x0AA0, + 0x7911, + 0x0A58, + 0x78AB, + 0x0A10, + 0x7845, + 0x09C8, + 0x77DF, + 0x0981, + 0x777A, + 0x0939, + 0x7715, + 0x08F2, + 0x76B1, + 0x08AB, + 0x764D, + 0x0865, + 0x75E9, + 0x081E, + 0x7585, + 0x07D8, + 0x7522, + 0x0792, + 0x74BF, + 0x074D, + 0x745D, + 0x0707, + 0x73FA, + 0x06C2, + 0x7398, + 0x067D, + 0x7337, + 0x0638, + 0x72D5, + 0x05F3, + 0x7274, + 0x05AF, + 0x7213, + 0x056A, + 0x71B3, + 0x0526, + 0x7152, + 0x04E2, + 0x70F2, + 0x049F, + 0x7093, + 0x045B, + 0x7033, + 0x0418, + 0x6FD4, + 0x03D5, + 0x6F76, + 0x0392, + 0x6F17, + 0x0350, + 0x6EB9, + 0x030D, + 0x6E5B, + 0x02CB, + 0x6DFD, + 0x0289, + 0x6DA0, + 0x0247, + 0x6D43, + 0x0206, + 0x6CE6, + 0x01C4, + 0x6C8A, + 0x0183, + 0x6C2D, + 0x0142, + 0x6BD1, + 0x0101, + 0x6B76, + 0x00C0, + 0x6B1A, + 0x0080, + 0x6ABF, + 0x0040, + 0x6A64 +}; + +enum { + SP_DIV_SQRT_NO, + SP_DIV_SQRT_YES +}; +enum { + SP_DIV_PRECISION_SINGLE = 0, + SP_DIV_PRECISION_DOUBLE = 1, + SP_DIV_PRECISION_CURRENT +}; + +INLINE static void do_div(usf_state_t * state, int data, int sqrt, int precision) +{ + int32_t addr; + int fetch; + int shift; + + if (precision == SP_DIV_PRECISION_SINGLE) + data = (data < 0) ? -data : +data; + if (precision == SP_DIV_PRECISION_DOUBLE && data < 0) + data = (data >= -32768) ? -data : ~data; + +/* + * Note, from the code just above, that data cannot be negative. + * (data >= 0) is unconditionally forced by the above algorithm. + */ + addr = data; + if (data == 0x00000000) + { + shift = (precision == SP_DIV_PRECISION_SINGLE) ? 16 : 0; + addr = addr << shift; + } + else + for (shift = 0; addr >= 0x00000000; addr <<= 1, shift++); + addr = (addr >> 22) & 0x000001FF; + + if (sqrt == SP_DIV_SQRT_YES) + { + addr &= 0x000001FE; + addr |= 0x00000200 | (shift & 1); + } + fetch = div_ROM[addr]; + shift ^= 31; /* flipping shift direction from left- to right- */ + shift >>= (sqrt == SP_DIV_SQRT_YES); + state->DivOut = (0x40000000 | (fetch << 14)) >> shift; + if (state->DivIn == 0) /* corner case: overflow via division by zero */ + state->DivOut = 0x7FFFFFFF; + else if (state->DivIn == -32768) /* corner case: signed underflow barrier */ + state->DivOut = 0xFFFF0000; + else + state->DivOut ^= (state->DivIn < 0) ? ~0 : 0; + return; +} +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/shuffle.h b/Frameworks/lazyusf/lazyusf/rsp/vu/shuffle.h new file mode 100644 index 000000000..674e75fc0 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/shuffle.h @@ -0,0 +1,278 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.12.04 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#ifndef _SHUFFLE_H +#define _SHUFFLE_H + +/* + * for ANSI compliance (null INLINE attribute if not already set to `inline`) + * Include "rsp.h" for active, non-ANSI inline definition. + */ +#ifndef INLINE +#define INLINE +#endif + +#ifndef ARCH_MIN_SSE2 +/* + * vector-scalar element decoding + * Obsolete. Consider using at least the SSE2 algorithms instead. + */ +static const int ei[16][8] = { + { 00, 01, 02, 03, 04, 05, 06, 07 }, /* none (vector-only operand) */ + { 00, 01, 02, 03, 04, 05, 06, 07 }, + { 00, 00, 02, 02, 04, 04, 06, 06 }, /* 0Q */ + { 01, 01, 03, 03, 05, 05, 07, 07 }, /* 1Q */ + { 00, 00, 00, 00, 04, 04, 04, 04 }, /* 0H */ + { 01, 01, 01, 01, 05, 05, 05, 05 }, /* 1H */ + { 02, 02, 02, 02, 06, 06, 06, 06 }, /* 2H */ + { 03, 03, 03, 03, 07, 07, 07, 07 }, /* 3H */ + { 00, 00, 00, 00, 00, 00, 00, 00 }, /* 0 */ + { 01, 01, 01, 01, 01, 01, 01, 01 }, /* 1 */ + { 02, 02, 02, 02, 02, 02, 02, 02 }, /* 2 */ + { 03, 03, 03, 03, 03, 03, 03, 03 }, /* 3 */ + { 04, 04, 04, 04, 04, 04, 04, 04 }, /* 4 */ + { 05, 05, 05, 05, 05, 05, 05, 05 }, /* 5 */ + { 06, 06, 06, 06, 06, 06, 06, 06 }, /* 6 */ + { 07, 07, 07, 07, 07, 07, 07, 07 } /* 7 */ +}; + +int sub_mask[16] = { + 0x0, + 0x0, + 0x1, 0x1, + 0x3, 0x3, 0x3, 0x3, + 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7 +}; + +INLINE static void SHUFFLE_VECTOR(short* VD, short* VT, const int e) +{ + short SV[8]; + register int i, j; +#if (0 == 0) + j = sub_mask[e]; + for (i = 0; i < N; i++) + SV[i] = VT[(i & ~j) | (e & j)]; +#else + if (e & 0x8) + for (i = 0; i < N; i++) + SV[i] = VT[(i & 0x0) | (e & 0x7)]; + else if (e & 0x4) + for (i = 0; i < N; i++) + SV[i] = VT[(i & 0xC) | (e & 0x3)]; + else if (e & 0x2) + for (i = 0; i < N; i++) + SV[i] = VT[(i & 0xE) | (e & 0x1)]; + else /* if ((e == 0b0000) || (e == 0b0001)) */ + for (i = 0; i < N; i++) + SV[i] = VT[(i & 0x7) | (e & 0x0)]; +#endif + for (i = 0; i < N; i++) + *(VD + i) = *(SV + i); + return; +} +#else +#ifdef ARCH_MIN_SSSE3 +static const unsigned char smask[16][16] = { + {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF}, + {0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF}, + {0x0,0x1,0x0,0x1,0x4,0x5,0x4,0x5,0x8,0x9,0x8,0x9,0xC,0xD,0xC,0xD}, + {0x2,0x3,0x2,0x3,0x6,0x7,0x6,0x7,0xA,0xB,0xA,0xB,0xE,0xF,0xE,0xF}, + {0x0,0x1,0x0,0x1,0x0,0x1,0x0,0x1,0x8,0x9,0x8,0x9,0x8,0x9,0x8,0x9}, + {0x2,0x3,0x2,0x3,0x2,0x3,0x2,0x3,0xA,0xB,0xA,0xB,0xA,0xB,0xA,0xB}, + {0x4,0x5,0x4,0x5,0x4,0x5,0x4,0x5,0xC,0xD,0xC,0xD,0xC,0xD,0xC,0xD}, + {0x6,0x7,0x6,0x7,0x6,0x7,0x6,0x7,0xE,0xF,0xE,0xF,0xE,0xF,0xE,0xF}, + {0x0,0x1,0x0,0x1,0x0,0x1,0x0,0x1,0x0,0x1,0x0,0x1,0x0,0x1,0x0,0x1}, + {0x2,0x3,0x2,0x3,0x2,0x3,0x2,0x3,0x2,0x3,0x2,0x3,0x2,0x3,0x2,0x3}, + {0x4,0x5,0x4,0x5,0x4,0x5,0x4,0x5,0x4,0x5,0x4,0x5,0x4,0x5,0x4,0x5}, + {0x6,0x7,0x6,0x7,0x6,0x7,0x6,0x7,0x6,0x7,0x6,0x7,0x6,0x7,0x6,0x7}, + {0x8,0x9,0x8,0x9,0x8,0x9,0x8,0x9,0x8,0x9,0x8,0x9,0x8,0x9,0x8,0x9}, + {0xA,0xB,0xA,0xB,0xA,0xB,0xA,0xB,0xA,0xB,0xA,0xB,0xA,0xB,0xA,0xB}, + {0xC,0xD,0xC,0xD,0xC,0xD,0xC,0xD,0xC,0xD,0xC,0xD,0xC,0xD,0xC,0xD}, + {0xE,0xF,0xE,0xF,0xE,0xF,0xE,0xF,0xE,0xF,0xE,0xF,0xE,0xF,0xE,0xF} +}; + +INLINE static void SHUFFLE_VECTOR(short* VD, short* VT, const int e) +{ /* SSSE3 shuffling method was written entirely by CEN64 author MarathonMan. */ + __m128i xmm; + __m128i key; + + xmm = _mm_load_si128((__m128i *)VT); + key = _mm_load_si128((__m128i *)(smask[e])); + xmm = _mm_shuffle_epi8(xmm, key); + _mm_store_si128((__m128i *)VD, xmm); + return; +} +#else +#define B(x) ((x) & 3) +#define SHUFFLE(a,b,c,d) ((B(d)<<6) | (B(c)<<4) | (B(b)<<2) | (B(a)<<0)) + +static const int simm[16] = { + SHUFFLE(00, 01, 02, 03), /* vector operands */ + SHUFFLE(00, 01, 02, 03), + SHUFFLE(00, 00, 02, 02), /* scalar quarters */ + SHUFFLE(01, 01, 03, 03), + SHUFFLE(00, 00, 00, 00), /* scalar halves */ + SHUFFLE(01, 01, 01, 01), + SHUFFLE(02, 02, 02, 02), + SHUFFLE(03, 03, 03, 03), + SHUFFLE(00, 00, 00, 00), /* scalar wholes */ + SHUFFLE(01, 01, 01, 01), + SHUFFLE(02, 02, 02, 02), + SHUFFLE(03, 03, 03, 03), + SHUFFLE(04, 04, 04, 04), + SHUFFLE(05, 05, 05, 05), + SHUFFLE(06, 06, 06, 06), + SHUFFLE(07, 07, 07, 07) +}; + +static __m128i shuffle_none(__m128i xmm) +{/* + const int order = simm[0x0]; + + xmm = _mm_shufflehi_epi16(xmm, order); + xmm = _mm_shufflelo_epi16(xmm, order);*/ + return (xmm); +} +static __m128i shuffle_0q(__m128i xmm) +{ + const int order = simm[0x2]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(00, 00, 02, 02)); + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(00, 00, 02, 02)); + return (xmm); +} +static __m128i shuffle_1q(__m128i xmm) +{ + const int order = simm[0x3]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(01, 01, 03, 03)); + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(01, 01, 03, 03)); + return (xmm); +} +static __m128i shuffle_0h(__m128i xmm) +{ + const int order = simm[0x4]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(00, 00, 00, 00)); + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(00, 00, 00, 00)); + return (xmm); +} +static __m128i shuffle_1h(__m128i xmm) +{ + const int order = simm[0x5]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(01, 01, 01, 01)); + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(01, 01, 01, 01)); + return (xmm); +} +static __m128i shuffle_2h(__m128i xmm) +{ + const int order = simm[0x6]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(02, 02, 02, 02)); + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(02, 02, 02, 02)); + return (xmm); +} +static __m128i shuffle_3h(__m128i xmm) +{ + const int order = simm[0x7]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(03, 03, 03, 03)); + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(03, 03, 03, 03)); + return (xmm); +} +static __m128i shuffle_0w(__m128i xmm) +{ + const int order = simm[0x8]; + + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(00, 00, 00, 00)); + xmm = _mm_unpacklo_epi16(xmm, xmm); + return (xmm); +} +static __m128i shuffle_1w(__m128i xmm) +{ + const int order = simm[0x9]; + + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(01, 01, 01, 01)); + xmm = _mm_unpacklo_epi16(xmm, xmm); + return (xmm); +} +static __m128i shuffle_2w(__m128i xmm) +{ + const int order = simm[0xA]; + + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(02, 02, 02, 02)); + xmm = _mm_unpacklo_epi16(xmm, xmm); + return (xmm); +} +static __m128i shuffle_3w(__m128i xmm) +{ + const int order = simm[0xB]; + + xmm = _mm_shufflelo_epi16(xmm, SHUFFLE(03, 03, 03, 03)); + xmm = _mm_unpacklo_epi16(xmm, xmm); + return (xmm); +} +static __m128i shuffle_4w(__m128i xmm) +{ + const int order = simm[0xC]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(04, 04, 04, 04)); + xmm = _mm_unpackhi_epi16(xmm, xmm); + return (xmm); +} +static __m128i shuffle_5w(__m128i xmm) +{ + const int order = simm[0xD]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(05, 05, 05, 05)); + xmm = _mm_unpackhi_epi16(xmm, xmm); + return (xmm); +} +static __m128i shuffle_6w(__m128i xmm) +{ + const int order = simm[0xE]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(06, 06, 06, 06)); + xmm = _mm_unpackhi_epi16(xmm, xmm); + return (xmm); +} +static __m128i shuffle_7w(__m128i xmm) +{ + const int order = simm[0xF]; + + xmm = _mm_shufflehi_epi16(xmm, SHUFFLE(07, 07, 07, 07)); + xmm = _mm_unpackhi_epi16(xmm, xmm); + return (xmm); +} + +static __m128i (*SSE2_SHUFFLE_16[16])(__m128i) = { + shuffle_none, shuffle_none, + shuffle_0q, shuffle_1q, + shuffle_0h, shuffle_1h, shuffle_2h, shuffle_3h, + shuffle_0w, shuffle_1w, shuffle_2w, shuffle_3w, + shuffle_4w, shuffle_5w, shuffle_6w, shuffle_7w +}; + +INLINE static void SHUFFLE_VECTOR(short* VD, short* VT, const int e) +{ + __m128i xmm; + + xmm = _mm_load_si128((__m128i *)VT); + xmm = SSE2_SHUFFLE_16[e](xmm); + _mm_store_si128((__m128i *)VD, xmm); + return; +} +#endif +#endif +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vabs.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vabs.h new file mode 100644 index 000000000..09b599bc4 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vabs.h @@ -0,0 +1,77 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +/* + * -1: VT *= -1, because VS < 0 // VT ^= -2 if even, or ^= -1, += 1 + * 0: VT *= 0, because VS = 0 // VT ^= VT + * +1: VT *= +1, because VS > 0 // VT ^= 0 + * VT ^= -1, "negate" -32768 as ~+32767 (corner case hack for N64 SP) + */ +INLINE static void do_abs(usf_state_t * state, short* VD, short* VS, short* VT) +{ + short neg[N], pos[N]; + short nez[N], cch[N]; /* corner case hack -- abs(-32768) == +32767 */ + short res[N]; + register int i; + + vector_copy(res, VT); +#ifndef ARCH_MIN_SSE2 +#define MASK_XOR +#endif + for (i = 0; i < N; i++) + neg[i] = (VS[i] < 0x0000); + for (i = 0; i < N; i++) + pos[i] = (VS[i] > 0x0000); + for (i = 0; i < N; i++) + nez[i] = 0; +#ifdef MASK_XOR + for (i = 0; i < N; i++) + neg[i] = -neg[i]; + for (i = 0; i < N; i++) + nez[i] += neg[i]; +#else + for (i = 0; i < N; i++) + nez[i] -= neg[i]; +#endif + for (i = 0; i < N; i++) + nez[i] += pos[i]; +#ifdef MASK_XOR + for (i = 0; i < N; i++) + res[i] ^= nez[i]; + for (i = 0; i < N; i++) + cch[i] = (res[i] != -32768); + for (i = 0; i < N; i++) + res[i] += cch[i]; /* -(x) === (x ^ -1) + 1 */ +#else + for (i = 0; i < N; i++) + res[i] *= nez[i]; + for (i = 0; i < N; i++) + cch[i] = (res[i] == -32768); + for (i = 0; i < N; i++) + res[i] -= cch[i]; +#endif + vector_copy(VACC_L, res); + vector_copy(VD, VACC_L); + return; +} + +static void VABS(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_abs(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vadd.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vadd.h new file mode 100644 index 000000000..6f9e97f43 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vadd.h @@ -0,0 +1,37 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void clr_ci(usf_state_t * state, short* VD, short* VS, short* VT) +{ /* clear CARRY and carry in to accumulators */ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = VS[i] + VT[i] + state->co[i]; + SIGNED_CLAMP_ADD(state, VD, VS, VT); + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + return; +} + +static void VADD(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + clr_ci(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vaddc.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vaddc.h new file mode 100644 index 000000000..d055eaf11 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vaddc.h @@ -0,0 +1,40 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void set_co(usf_state_t * state, short* VD, short* VS, short* VT) +{ /* set CARRY and carry out from sum */ + int32_t sum[N]; + register int i; + + for (i = 0; i < N; i++) + sum[i] = (unsigned short)(VS[i]) + (unsigned short)(VT[i]); + for (i = 0; i < N; i++) + VACC_L[i] = VS[i] + VT[i]; + vector_copy(VD, VACC_L); + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = sum[i] >> 16; /* native: (sum[i] > +65535) */ + return; +} + +static void VADDC(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + set_co(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vand.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vand.h new file mode 100644 index 000000000..d0ff119ac --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vand.h @@ -0,0 +1,33 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE void do_and(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = VS[i] & VT[i]; + vector_copy(VD, VACC_L); + return; +} + +static void VAND(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_and(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vch.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vch.h new file mode 100644 index 000000000..acefdaaa4 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vch.h @@ -0,0 +1,84 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_ch(usf_state_t * state, short* VD, short* VS, short* VT) +{ + short eq[N], ge[N], le[N]; + short sn[N]; + short VC[N]; + short diff[N]; + register int i; + + for (i = 0; i < N; i++) + VC[i] = VT[i]; + for (i = 0; i < N; i++) + sn[i] = (VS[i] ^ VC[i]) < 0; + for (i = 0; i < N; i++) + VC[i] ^= -sn[i]; /* if (sn == ~0) {VT = ~VT;} else {VT = VT;} */ + for (i = 0; i < N; i++) + state->vce[i] = (VS[i] == VC[i]); /* (VR[vs][i] + ~VC[i] == ~1); */ + for (i = 0; i < N; i++) + state->vce[i] &= sn[i]; + for (i = 0; i < N; i++) + VC[i] += sn[i]; /* converts ~(VT) into -(VT) if (sign) */ + for (i = 0; i < N; i++) + eq[i] = (VS[i] == VC[i]); + for (i = 0; i < N; i++) + eq[i] |= state->vce[i]; + +#if (0) + for (i = 0; i < N; i++) + le[i] = sn[i] ? (VS[i] <= VC[i]) : (VC[i] < 0); + for (i = 0; i < N; i++) + ge[i] = sn[i] ? (VC[i] > 0x0000) : (VS[i] >= VC[i]); +#elif (0) + for (i = 0; i < N; i++) + le[i] = sn[i] ? (VT[i] <= -VS[i]) : (VT[i] <= ~0x0000); + for (i = 0; i < N; i++) + ge[i] = sn[i] ? (~0x0000 >= VT[i]) : (VS[i] >= VT[i]); +#else + for (i = 0; i < N; i++) + diff[i] = -VS[i] | -(sn[i] ^ 1); + for (i = 0; i < N; i++) + le[i] = VT[i] <= diff[i]; + for (i = 0; i < N; i++) + diff[i] = +VS[i] | -(sn[i] ^ 0); + for (i = 0; i < N; i++) + ge[i] = diff[i] >= VT[i]; +#endif + + merge(state->comp, sn, le, ge); + merge(VACC_L, state->comp, VC, VS); + vector_copy(VD, VACC_L); + + for (i = 0; i < N; i++) + state->clip[i] = ge[i]; + for (i = 0; i < N; i++) + state->comp[i] = le[i]; + for (i = 0; i < N; i++) + state->ne[i] = eq[i] ^ 1; + for (i = 0; i < N; i++) + state->co[i] = sn[i]; + return; +} + +static void VCH(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_ch(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vcl.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vcl.h new file mode 100644 index 000000000..dfaa6298d --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vcl.h @@ -0,0 +1,100 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_cl(usf_state_t * state, short* VD, short* VS, short* VT) +{ + short eq[N], ge[N], le[N]; + short gen[N], len[N], lz[N], uz[N], sn[N]; + short diff[N]; + short cmp[N]; + unsigned short VB[N], VC[N]; + register int i; + + for (i = 0; i < N; i++) + VB[i] = VS[i]; + for (i = 0; i < N; i++) + VC[i] = VT[i]; + +/* + for (i = 0; i < N; i++) + ge[i] = clip[i]; + for (i = 0; i < N; i++) + le[i] = comp[i]; +*/ + for (i = 0; i < N; i++) + eq[i] = state->ne[i] ^ 1; + for (i = 0; i < N; i++) + sn[i] = state->co[i]; +/* + * Now that we have extracted all the flags, we will essentially be masking + * them back in where they came from redundantly, unless the corresponding + * NOTEQUAL bit from VCO upper was not set.... + */ + for (i = 0; i < N; i++) + VC[i] = VC[i] ^ -sn[i]; + for (i = 0; i < N; i++) + VC[i] = VC[i] + sn[i]; /* conditional negation, if sn */ + for (i = 0; i < N; i++) + diff[i] = VB[i] - VC[i]; + for (i = 0; i < N; i++) + uz[i] = (VB[i] - VC[i] - 0xFFFF) >> 31; + for (i = 0; i < N; i++) + lz[i] = (diff[i] == 0x0000); + for (i = 0; i < N; i++) + gen[i] = lz[i] | uz[i]; + for (i = 0; i < N; i++) + len[i] = lz[i] & uz[i]; + for (i = 0; i < N; i++) + gen[i] = gen[i] & state->vce[i]; + for (i = 0; i < N; i++) + len[i] = len[i] & (state->vce[i] ^ 1); + for (i = 0; i < N; i++) + len[i] = len[i] | gen[i]; + for (i = 0; i < N; i++) + gen[i] = (VB[i] >= VC[i]); + + for (i = 0; i < N; i++) + cmp[i] = eq[i] & sn[i]; + merge(le, cmp, len, state->comp); + + for (i = 0; i < N; i++) + cmp[i] = eq[i] & (sn[i] ^ 1); + merge(ge, cmp, gen, state->clip); + + merge(cmp, sn, le, ge); + merge(VACC_L, cmp, (short *)VC, VS); + vector_copy(VD, VACC_L); + + for (i = 0; i < N; i++) + state->clip[i] = ge[i]; + for (i = 0; i < N; i++) + state->comp[i] = le[i]; + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + for (i = 0; i < N; i++) + state->vce[i] = 0; + return; +} + +static void VCL(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_cl(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vcr.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vcr.h new file mode 100644 index 000000000..9cb6637cd --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vcr.h @@ -0,0 +1,67 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_cr(usf_state_t * state, short* VD, short* VS, short* VT) +{ + short ge[N], le[N], sn[N]; + short VC[N]; + short cmp[N]; + register int i; + + for (i = 0; i < N; i++) + VC[i] = VT[i]; + for (i = 0; i < N; i++) + sn[i] = (signed short)(VS[i] ^ VT[i]) >> 15; +#if (0) + for (i = 0; i < N; i++) + le[i] = sn[i] ? (VT[i] <= ~VS[i]) : (VT[i] <= ~0x0000); + for (i = 0; i < N; i++) + ge[i] = sn[i] ? (~0x0000 >= VT[i]) : (VS[i] >= VT[i]); +#else + for (i = 0; i < N; i++) + cmp[i] = ~(VS[i] & sn[i]); + for (i = 0; i < N; i++) + le[i] = (VT[i] <= cmp[i]); + for (i = 0; i < N; i++) + cmp[i] = (VS[i] | sn[i]); + for (i = 0; i < N; i++) + ge[i] = (cmp[i] >= VT[i]); +#endif + for (i = 0; i < N; i++) + VC[i] ^= sn[i]; /* if (sn == ~0) {VT = ~VT;} else {VT = VT;} */ + merge(VACC_L, le, VC, VS); + vector_copy(VD, VACC_L); + + for (i = 0; i < N; i++) + state->clip[i] = ge[i]; + for (i = 0; i < N; i++) + state->comp[i] = le[i]; + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + for (i = 0; i < N; i++) + state->vce[i] = 0; + return; +} + +static void VCR(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_cr(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/veq.h b/Frameworks/lazyusf/lazyusf/rsp/vu/veq.h new file mode 100644 index 000000000..5afe23537 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/veq.h @@ -0,0 +1,47 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_eq(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + state->clip[i] = 0; + for (i = 0; i < N; i++) + state->comp[i] = (VS[i] == VT[i]); + for (i = 0; i < N; i++) + state->comp[i] = state->comp[i] & (state->ne[i] ^ 1); +#if (0) + merge(VACC_L, state->comp, VS, VT); /* correct but redundant */ +#else + vector_copy(VACC_L, VT); +#endif + vector_copy(VD, VACC_L); + + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + return; +} + +static void VEQ(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_eq(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vge.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vge.h new file mode 100644 index 000000000..15d0dab41 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vge.h @@ -0,0 +1,51 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_ge(usf_state_t * state, short* VD, short* VS, short* VT) +{ + short ce[N]; + short eq[N]; + register int i; + + for (i = 0; i < N; i++) + eq[i] = (VS[i] == VT[i]); + for (i = 0; i < N; i++) + ce[i] = (state->ne[i] & state->co[i]) ^ 1; + for (i = 0; i < N; i++) + eq[i] = eq[i] & ce[i]; + for (i = 0; i < N; i++) + state->clip[i] = 0; + for (i = 0; i < N; i++) + state->comp[i] = (VS[i] > VT[i]); /* greater than */ + for (i = 0; i < N; i++) + state->comp[i] = state->comp[i] | eq[i]; /* ... or equal (commonly) */ + + merge(VACC_L, state->comp, VS, VT); + vector_copy(VD, VACC_L); + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + return; +} + +static void VGE(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_ge(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vlt.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vlt.h new file mode 100644 index 000000000..bd877b16b --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vlt.h @@ -0,0 +1,51 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_lt(usf_state_t * state, short* VD, short* VS, short* VT) +{ + short cn[N]; + short eq[N]; + register int i; + + for (i = 0; i < N; i++) + eq[i] = (VS[i] == VT[i]); + for (i = 0; i < N; i++) + cn[i] = state->ne[i] & state->co[i]; + for (i = 0; i < N; i++) + eq[i] = eq[i] & cn[i]; + for (i = 0; i < N; i++) + state->clip[i] = 0; + for (i = 0; i < N; i++) + state->comp[i] = (VS[i] < VT[i]); /* less than */ + for (i = 0; i < N; i++) + state->comp[i] = state->comp[i] | eq[i]; /* ... or equal (uncommonly) */ + + merge(VACC_L, state->comp, VS, VT); + vector_copy(VD, VACC_L); + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + return; +} + +static void VLT(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_lt(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmacf.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacf.h new file mode 100644 index 000000000..0eb34998f --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacf.h @@ -0,0 +1,51 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_macf(usf_state_t * state, short* VD, short* VS, short* VT) +{ + int32_t product[N]; + uint32_t addend[N]; + register int i; + + for (i = 0; i < N; i++) + product[i] = VS[i] * VT[i]; + for (i = 0; i < N; i++) + addend[i] = (product[i] << 1) & 0x00000000FFFF; + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_L[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_L[i] = (short)(addend[i]); + for (i = 0; i < N; i++) + addend[i] = (addend[i] >> 16) + (unsigned short)(product[i] >> 15); + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_M[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_M[i] = (short)(addend[i]); + for (i = 0; i < N; i++) + VACC_H[i] -= (product[i] < 0); + for (i = 0; i < N; i++) + VACC_H[i] += addend[i] >> 16; + SIGNED_CLAMP_AM(state, VD); + return; +} + +static void VMACF(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_macf(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h new file mode 100644 index 000000000..911249e79 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h @@ -0,0 +1,23 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +static void VMACQ(int vd, int vs, int vt, int e) +{ + vd &= vs &= vt &= e &= 0; /* unused */ + if (vd != vs || vt != e) + return; + message("VMACQ\nUnimplemented.", 3); /* untested, any N64 ROMs use this?? */ + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmacu.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacu.h new file mode 100644 index 000000000..4d954d5ef --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacu.h @@ -0,0 +1,51 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_macu(usf_state_t * state, short* VD, short* VS, short* VT) +{ + int32_t product[N]; + uint32_t addend[N]; + register int i; + + for (i = 0; i < N; i++) + product[i] = VS[i] * VT[i]; + for (i = 0; i < N; i++) + addend[i] = (product[i] << 1) & 0x00000000FFFF; + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_L[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_L[i] = (short)(addend[i]); + for (i = 0; i < N; i++) + addend[i] = (addend[i] >> 16) + (unsigned short)(product[i] >> 15); + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_M[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_M[i] = (short)(addend[i]); + for (i = 0; i < N; i++) + VACC_H[i] -= (product[i] < 0); + for (i = 0; i < N; i++) + VACC_H[i] += addend[i] >> 16; + UNSIGNED_CLAMP(state, VD); + return; +} + +static void VMACU(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_macu(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmadh.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadh.h new file mode 100644 index 000000000..a1f5bc66c --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadh.h @@ -0,0 +1,41 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_madh(usf_state_t * state, short* VD, short* VS, short* VT) +{ + int32_t product[N]; + uint32_t addend[N]; + register int i; + + for (i = 0; i < N; i++) + product[i] = (signed short)(VS[i]) * (signed short)(VT[i]); + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_M[i]) + (unsigned short)(product[i]); + for (i = 0; i < N; i++) + VACC_M[i] += (short)(VS[i] * VT[i]); + for (i = 0; i < N; i++) + VACC_H[i] += (addend[i] >> 16) + (product[i] >> 16); + SIGNED_CLAMP_AM(state, VD); + return; +} + +static void VMADH(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_madh(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmadl.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadl.h new file mode 100644 index 000000000..41a3a8ef7 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadl.h @@ -0,0 +1,49 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_madl(usf_state_t * state, short* VD, short* VS, short* VT) +{ + int32_t product[N]; + uint32_t addend[N]; + register int i; + + for (i = 0; i < N; i++) + product[i] = (unsigned short)(VS[i]) * (unsigned short)(VT[i]); + for (i = 0; i < N; i++) + addend[i] = (product[i] & 0x0000FFFF0000) >> 16; + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_L[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_L[i] = (short)(addend[i]); + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(addend[i] >> 16); + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_M[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_M[i] = (short)(addend[i]); + for (i = 0; i < N; i++) + VACC_H[i] += addend[i] >> 16; + SIGNED_CLAMP_AL(state, VD); + return; +} + +static void VMADL(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_madl(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmadm.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadm.h new file mode 100644 index 000000000..034492fd6 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadm.h @@ -0,0 +1,44 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_madm(usf_state_t * state, short* VD, short* VS, short* VT) +{ + uint32_t addend[N]; + register int i; + + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_L[i]) + (unsigned short)(VS[i]*VT[i]); + for (i = 0; i < N; i++) + VACC_L[i] += (short)(VS[i] * VT[i]); + for (i = 0; i < N; i++) + addend[i] = (addend[i] >> 16) + (VS[i]*(unsigned short)(VT[i]) >> 16); + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_M[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_M[i] = (short)addend[i]; + for (i = 0; i < N; i++) + VACC_H[i] += addend[i] >> 16; + SIGNED_CLAMP_AM(state, VD); + return; +} + +static void VMADM(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_madm(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmadn.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadn.h new file mode 100644 index 000000000..16b282962 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmadn.h @@ -0,0 +1,44 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_madn(usf_state_t * state, short* VD, short* VS, short* VT) +{ + uint32_t addend[N]; + register int i; + + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_L[i]) + (unsigned short)(VS[i]*VT[i]); + for (i = 0; i < N; i++) + VACC_L[i] += (short)(VS[i] * VT[i]); + for (i = 0; i < N; i++) + addend[i] = (addend[i] >> 16) + ((unsigned short)(VS[i])*VT[i] >> 16); + for (i = 0; i < N; i++) + addend[i] = (unsigned short)(VACC_M[i]) + addend[i]; + for (i = 0; i < N; i++) + VACC_M[i] = (short)addend[i]; + for (i = 0; i < N; i++) + VACC_H[i] += addend[i] >> 16; + SIGNED_CLAMP_AL(state, VD); + return; +} + +static void VMADN(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_madn(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmov.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmov.h new file mode 100644 index 000000000..cadb5f9af --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmov.h @@ -0,0 +1,21 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +static void VMOV(usf_state_t * state, int vd, int de, int vt, int e) +{ + SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); + state->VR[vd][de &= 07] = VACC_L[e & 07]; + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmrg.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmrg.h new file mode 100644 index 000000000..1d2ecc76f --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmrg.h @@ -0,0 +1,30 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_mrg(usf_state_t * state, short* VD, short* VS, short* VT) +{ + merge(VACC_L, state->comp, VS, VT); + vector_copy(VD, VACC_L); + return; +} + +static void VMRG(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_mrg(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmudh.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudh.h new file mode 100644 index 000000000..c0d0fbe26 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudh.h @@ -0,0 +1,37 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_mudh(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = 0x0000; + for (i = 0; i < N; i++) + VACC_M[i] = (short)(VS[i]*VT[i] >> 0); + for (i = 0; i < N; i++) + VACC_H[i] = (short)(VS[i]*VT[i] >> 16); + SIGNED_CLAMP_AM(state, VD); + return; +} + +static void VMUDH(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_mudh(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmudl.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudl.h new file mode 100644 index 000000000..9cb006792 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudl.h @@ -0,0 +1,37 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_mudl(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = (unsigned short)(VS[i])*(unsigned short)(VT[i]) >> 16; + for (i = 0; i < N; i++) + VACC_M[i] = 0x0000; + for (i = 0; i < N; i++) + VACC_H[i] = 0x0000; + vector_copy(VD, VACC_L); /* no possibilities to clamp */ + return; +} + +static void VMUDL(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_mudl(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmudm.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudm.h new file mode 100644 index 000000000..ab3b5ed0a --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudm.h @@ -0,0 +1,37 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_mudm(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = (VS[i]*(unsigned short)(VT[i]) & 0x00000000FFFF) >> 0; + for (i = 0; i < N; i++) + VACC_M[i] = (VS[i]*(unsigned short)(VT[i]) & 0x0000FFFF0000) >> 16; + for (i = 0; i < N; i++) + VACC_H[i] = -(VACC_M[i] < 0); + vector_copy(VD, VACC_M); /* no possibilities to clamp */ + return; +} + +static void VMUDM(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_mudm(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmudn.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudn.h new file mode 100644 index 000000000..eb0692e9b --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmudn.h @@ -0,0 +1,37 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.10.11 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_mudn(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = ((unsigned short)(VS[i])*VT[i] & 0x00000000FFFF) >> 0; + for (i = 0; i < N; i++) + VACC_M[i] = ((unsigned short)(VS[i])*VT[i] & 0x0000FFFF0000) >> 16; + for (i = 0; i < N; i++) + VACC_H[i] = -(VACC_M[i] < 0); + vector_copy(VD, VACC_L); /* no possibilities to clamp */ + return; +} + +static void VMUDN(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_mudn(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmulf.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmulf.h new file mode 100644 index 000000000..b095f0315 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmulf.h @@ -0,0 +1,55 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +#ifndef SEMIFRAC +/* + * acc = VS * VT; + * acc = acc + 0x8000; // rounding value + * acc = acc << 1; // partial value shifting + * + * Wrong: ACC(HI) = -((INT32)(acc) < 0) + * Right: ACC(HI) = -(SEMIFRAC < 0) + */ +#define SEMIFRAC (VS[i]*VT[i]*2/2 + 0x8000/2) +#endif + +INLINE static void do_mulf(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = (SEMIFRAC << 1) >> 0; + for (i = 0; i < N; i++) + VACC_M[i] = (SEMIFRAC << 1) >> 16; + for (i = 0; i < N; i++) + VACC_H[i] = -((VACC_M[i] < 0) & (VS[i] != VT[i])); /* -32768 * -32768 */ +#ifndef ARCH_MIN_SSE2 + vector_copy(VD, VACC_M); + for (i = 0; i < N; i++) + VD[i] -= (VACC_M[i] < 0) & (VS[i] == VT[i]); /* ACC b 31 set, min*min */ +#else + SIGNED_CLAMP_AM(state, VD); +#endif + return; +} + +static void VMULF(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_mulf(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmulu.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmulu.h new file mode 100644 index 000000000..2726dca18 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmulu.h @@ -0,0 +1,57 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +#ifndef SEMIFRAC +/* + * acc = VS * VT; + * acc = acc + 0x8000; // rounding value + * acc = acc << 1; // partial value shifting + * + * Wrong: ACC(HI) = -((INT32)(acc) < 0) + * Right: ACC(HI) = -(SEMIFRAC < 0) + */ +#define SEMIFRAC (VS[i]*VT[i]*2/2 + 0x8000/2) +#endif + +INLINE static void do_mulu(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = (SEMIFRAC << 1) >> 0; + for (i = 0; i < N; i++) + VACC_M[i] = (SEMIFRAC << 1) >> 16; + for (i = 0; i < N; i++) + VACC_H[i] = -((VACC_M[i] < 0) & (VS[i] != VT[i])); /* -32768 * -32768 */ +#if (0) + UNSIGNED_CLAMP(state, VD); +#else + vector_copy(VD, VACC_M); + for (i = 0; i < N; i++) + VD[i] |= (VACC_M[i] >> 15); /* VD |= -(result == 0x000080008000) */ + for (i = 0; i < N; i++) + VD[i] &= ~(VACC_H[i] >> 0); /* VD &= -(result >= 0x000000000000) */ +#endif + return; +} + +static void VMULU(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_mulu(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vnand.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vnand.h new file mode 100644 index 000000000..af3aa012d --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vnand.h @@ -0,0 +1,33 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE void do_nand(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = ~(VS[i] & VT[i]); + vector_copy(VD, VACC_L); + return; +} + +static void VNAND(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_nand(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vne.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vne.h new file mode 100644 index 000000000..8f7869b93 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vne.h @@ -0,0 +1,47 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void do_ne(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + state->clip[i] = 0; + for (i = 0; i < N; i++) + state->comp[i] = (VS[i] != VT[i]); + for (i = 0; i < N; i++) + state->comp[i] = state->comp[i] | state->ne[i]; +#if (0) + merge(VACC_L, state->comp, VS, VT); /* correct but redundant */ +#else + vector_copy(VACC_L, VS); +#endif + vector_copy(VD, VACC_L); + + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + return; +} + +static void VNE(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_ne(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h new file mode 100644 index 000000000..7157a0b82 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h @@ -0,0 +1,23 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +static void VNOP(int vd, int vs, int vt, int e) +{ + const int WB_inhibit = vd = vs = vt = e = 1; + + if (WB_inhibit) + return; /* message("VNOP", WB_inhibit); */ + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vnor.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vnor.h new file mode 100644 index 000000000..9057fdf64 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vnor.h @@ -0,0 +1,33 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE void do_nor(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = ~(VS[i] | VT[i]); + vector_copy(VD, VACC_L); + return; +} + +static void VNOR(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_nor(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vnxor.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vnxor.h new file mode 100644 index 000000000..14030fa5b --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vnxor.h @@ -0,0 +1,33 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE void do_nxor(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = ~(VS[i] ^ VT[i]); + vector_copy(VD, VACC_L); + return; +} + +static void VNXOR(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_nxor(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vor.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vor.h new file mode 100644 index 000000000..d96b4aa46 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vor.h @@ -0,0 +1,33 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE void do_or(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = VS[i] | VT[i]; + vector_copy(VD, VACC_L); + return; +} + +static void VOR(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_or(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vrcp.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vrcp.h new file mode 100644 index 000000000..a34be6010 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vrcp.h @@ -0,0 +1,25 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" +#include "divrom.h" + +static void VRCP(usf_state_t * state, int vd, int de, int vt, int e) +{ + state->DivIn = (int)state->VR[vt][e & 07]; + do_div(state, state->DivIn, SP_DIV_SQRT_NO, SP_DIV_PRECISION_SINGLE); + SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); + state->VR[vd][de &= 07] = (short)state->DivOut; + state->DPH = SP_DIV_PRECISION_SINGLE; + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vrcph.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vrcph.h new file mode 100644 index 000000000..0d18906ba --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vrcph.h @@ -0,0 +1,24 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" +#include "divrom.h" + +static void VRCPH(usf_state_t * state, int vd, int de, int vt, int e) +{ + state->DivIn = state->VR[vt][e & 07] << 16; + SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); + state->VR[vd][de &= 07] = state->DivOut >> 16; + state->DPH = SP_DIV_PRECISION_DOUBLE; + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vrcpl.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vrcpl.h new file mode 100644 index 000000000..b2a987e2f --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vrcpl.h @@ -0,0 +1,26 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" +#include "divrom.h" + +static void VRCPL(usf_state_t * state, int vd, int de, int vt, int e) +{ + state->DivIn &= -state->DPH; + state->DivIn |= (unsigned short)state->VR[vt][e & 07]; + do_div(state, state->DivIn, SP_DIV_SQRT_NO, state->DPH); + SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); + state->VR[vd][de &= 07] = (short)state->DivOut; + state->DPH = SP_DIV_PRECISION_SINGLE; + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h new file mode 100644 index 000000000..34bb56ac7 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h @@ -0,0 +1,26 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" +#include "divrom.h" + +static void VRSQ(usf_state_t * state, int vd, int de, int vt, int e) +{ + message("VRSQ\nUntested.", 1); + state->DivIn = (int)state->VR[vt][e & 07]; + do_div(state, state->DivIn, SP_DIV_SQRT_YES, SP_DIV_PRECISION_SINGLE); + SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); + state->VR[vd][de &= 07] = (short)state->DivOut; + state->DPH = SP_DIV_PRECISION_SINGLE; + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vrsqh.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsqh.h new file mode 100644 index 000000000..663ab5015 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsqh.h @@ -0,0 +1,24 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" +#include "divrom.h" + +static void VRSQH(usf_state_t * state, int vd, int de, int vt, int e) +{ + state->DivIn = state->VR[vt][e & 07] << 16; + SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); + state->VR[vd][de &= 07] = state->DivOut >> 16; + state->DPH = SP_DIV_PRECISION_DOUBLE; + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vrsql.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsql.h new file mode 100644 index 000000000..69a21d8f0 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsql.h @@ -0,0 +1,26 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" +#include "divrom.h" + +static void VRSQL(usf_state_t * state, int vd, int de, int vt, int e) +{ + state->DivIn &= -state->DPH; + state->DivIn |= (unsigned short)state->VR[vt][e & 07]; + do_div(state, state->DivIn, SP_DIV_SQRT_YES, state->DPH); + SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); + state->VR[vd][de &= 07] = (short)state->DivOut; + state->DPH = SP_DIV_PRECISION_SINGLE; + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h new file mode 100644 index 000000000..4e2625d12 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h @@ -0,0 +1,68 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +#ifdef VU_EMULATE_SCALAR_ACCUMULATOR_READ +static void VSAR(int vd, int vs, int vt, int e) +{ + short oldval[N]; + register int i; + + for (i = 0; i < N; i++) + oldval[i] = VR[vs][i]; + vt = 0; +/* Even though VT is ignored in VSAR, according to official sources as well + * as reversing, lots of games seem to specify it as non-zero, possibly to + * avoid register stalling or other VU hazards. Not really certain why yet. + */ + e ^= 0x8; +/* Or, for exception overrides, should this be `e &= 0x7;` ? + * Currently this code is safer because &= is less likely to catch oddities. + * Either way, documentation shows that the switch range is 0:2, not 8:A. + */ + if (e > 2) + { + message("VSAR\nInvalid mask.", 2); + for (i = 0; i < N; i++) + VR[vd][i] = 0x0000; /* override behavior (zilmar) */ + } + else + for (i = 0; i < N; i++) + VR[vd][i] = VACC[e][i]; + for (i = 0; i < N; i++) + VACC[e][i] = oldval[i]; /* ... = VS */ + return; +} +#endif + +static void VSAW(usf_state_t * state, int vd, int vs, int vt, int e) +{ + register int i; + + vs = 0; /* unused--old VSAR algorithm */ + vt = 0; /* unused but mysteriously set many times */ + if (vs | vt) + return; + e ^= 0x8; /* &= 7 */ + + if (e > 0x2) + { /* branch very unlikely...never seen a game do VSAW illegally */ + message("VSAW\nIllegal mask.", 2); + for (i = 0; i < N; i++) + state->VR[vd][i] = 0x0000; /* override behavior (zilmar) */ + return; + } + vector_copy(state->VR[vd], state->VACC[e]); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vsub.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vsub.h new file mode 100644 index 000000000..a13fcb70e --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vsub.h @@ -0,0 +1,37 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void clr_bi(usf_state_t * state, short* VD, short* VS, short* VT) +{ /* clear CARRY and borrow in to accumulators */ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = VS[i] - VT[i] - state->co[i]; + SIGNED_CLAMP_SUB(state, VD, VS, VT); + for (i = 0; i < N; i++) + state->ne[i] = 0; + for (i = 0; i < N; i++) + state->co[i] = 0; + return; +} + +static void VSUB(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + clr_bi(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vsubc.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vsubc.h new file mode 100644 index 000000000..cb520ffca --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vsubc.h @@ -0,0 +1,40 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE static void set_bo(usf_state_t * state, short* VD, short* VS, short* VT) +{ /* set CARRY and borrow out from difference */ + int32_t dif[N]; + register int i; + + for (i = 0; i < N; i++) + dif[i] = (unsigned short)(VS[i]) - (unsigned short)(VT[i]); + for (i = 0; i < N; i++) + VACC_L[i] = VS[i] - VT[i]; + vector_copy(VD, VACC_L); + for (i = 0; i < N; i++) + state->ne[i] = (VS[i] != VT[i]); + for (i = 0; i < N; i++) + state->co[i] = (dif[i] < 0); + return; +} + +static void VSUBC(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + set_bo(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vu.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vu.h new file mode 100644 index 000000000..cfaac480c --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vu.h @@ -0,0 +1,120 @@ +/******************************************************************************\ +* Project: MSP Emulation Layer for Vector Unit Computational Operations * +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#ifndef _VU_H +#define _VU_H + +#define N 8 +/* N: number of processor elements in SIMD processor */ + +/* + * RSP virtual registers (of vector unit) + * The most important are the 32 general-purpose vector registers. + * The correct way to accurately store these is using big-endian vectors. + * + * For ?WC2 we may need to do byte-precision access just as directly. + * This is amended by using the `VU_S` and `VU_B` macros defined in `rsp.h`. + */ + +/* + * accumulator-indexing macros (inverted access dimensions, suited for SSE) + */ +#define HI 00 +#define MD 01 +#define LO 02 + +#define VACC_L (state->VACC[LO]) +#define VACC_M (state->VACC[MD]) +#define VACC_H (state->VACC[HI]) + +#define ACC_L(i) (VACC_L[i]) +#define ACC_M(i) (VACC_M[i]) +#define ACC_H(i) (VACC_H[i]) + +#include "shuffle.h" +#include "clamp.h" +#include "cf.h" + +static void res_V(usf_state_t * state, int vd, int vs, int vt, int e) +{ + register int i; + + vs = vt = e = 0; + if (vs != vt || vt != e) + return; + message("C2\nRESERVED", 2); /* uncertain how to handle reserved, untested */ + for (i = 0; i < N; i++) + state->VR[vd][i] = 0x0000; /* override behavior (bpoint) */ + return; +} +static void res_M(usf_state_t * state, int vd, int vs, int vt, int e) +{ + message("VMUL IQ", 2); + res_V(state, vd, vs, vt, e); + return; /* Ultra64 OS did have these, so one could implement this ext. */ +} + +#include "vabs.h" +#include "vadd.h" +#include "vaddc.h" +#include "vand.h" +#include "vch.h" +#include "vcl.h" +#include "vcr.h" +#include "veq.h" +#include "vge.h" +#include "vlt.h" +#include "vmacf.h" +#include "vmacq.h" +#include "vmacu.h" +#include "vmadh.h" +#include "vmadl.h" +#include "vmadm.h" +#include "vmadn.h" +#include "vmov.h" +#include "vmrg.h" +#include "vmudh.h" +#include "vmudl.h" +#include "vmudm.h" +#include "vmudn.h" +#include "vmulf.h" +#include "vmulu.h" +#include "vnand.h" +#include "vne.h" +#include "vnop.h" +#include "vnor.h" +#include "vnxor.h" +#include "vor.h" +#include "vrcp.h" +#include "vrcph.h" +#include "vrcpl.h" +#include "vrsq.h" +#include "vrsqh.h" +#include "vrsql.h" +#include "vsaw.h" +#include "vsub.h" +#include "vsubc.h" +#include "vxor.h" + +static void (*COP2_C2[64])(usf_state_t *, int, int, int, int) = { + VMULF ,VMULU ,res_M ,res_M ,VMUDL ,VMUDM ,VMUDN ,VMUDH , /* 000 */ + VMACF ,VMACU ,res_M ,VMACQ ,VMADL ,VMADM ,VMADN ,VMADH , /* 001 */ + VADD ,VSUB ,res_V ,VABS ,VADDC ,VSUBC ,res_V ,res_V , /* 010 */ + res_V ,res_V ,res_V ,res_V ,res_V ,VSAW ,res_V ,res_V , /* 011 */ + VLT ,VEQ ,VNE ,VGE ,VCL ,VCH ,VCR ,VMRG , /* 100 */ + VAND ,VNAND ,VOR ,VNOR ,VXOR ,VNXOR ,res_V ,res_V , /* 101 */ + VRCP ,VRCPL ,VRCPH ,VMOV ,VRSQ ,VRSQL ,VRSQH ,VNOP , /* 110 */ + res_V ,res_V ,res_V ,res_V ,res_V ,res_V ,res_V ,res_V , /* 111 */ +}; /* 000 001 010 011 100 101 110 111 */ +#endif diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vxor.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vxor.h new file mode 100644 index 000000000..7bbb2a54b --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vxor.h @@ -0,0 +1,33 @@ +/******************************************************************************\ +* Authors: Iconoclast * +* Release: 2013.11.26 * +* License: CC0 Public Domain Dedication * +* * +* To the extent possible under law, the author(s) have dedicated all copyright * +* and related and neighboring rights to this software to the public domain * +* worldwide. This software is distributed without any warranty. * +* * +* You should have received a copy of the CC0 Public Domain Dedication along * +* with this software. * +* If not, see . * +\******************************************************************************/ +#include "vu.h" + +INLINE void do_xor(usf_state_t * state, short* VD, short* VS, short* VT) +{ + register int i; + + for (i = 0; i < N; i++) + VACC_L[i] = VS[i] ^ VT[i]; + vector_copy(VD, VACC_L); + return; +} + +static void VXOR(usf_state_t * state, int vd, int vs, int vt, int e) +{ + short ST[N]; + + SHUFFLE_VECTOR(ST, state->VR[vt], e); + do_xor(state, state->VR[vd], state->VR[vs], ST); + return; +} diff --git a/Frameworks/lazyusf/lazyusf/tlb.c b/Frameworks/lazyusf/lazyusf/tlb.c new file mode 100644 index 000000000..cd75ff6ed --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/tlb.c @@ -0,0 +1,193 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include "main.h" +#include "cpu.h" + +#include "usf_internal.h" + +void SetupTLB_Entry (usf_state_t * state, int32_t Entry); + +uint32_t AddressDefined ( usf_state_t * state, uintptr_t VAddr) { + uint32_t i; + + if (VAddr >= 0x80000000 && VAddr <= 0xBFFFFFFF) { + return 1; + } + + for (i = 0; i < 64; i++) { + if (state->FastTlb[i].ValidEntry == 0) { continue; } + if (VAddr >= state->FastTlb[i].VSTART && VAddr <= state->FastTlb[i].VEND) { + return 1; + } + } + return 0; +} + +void InitilizeTLB (usf_state_t * state) { + uint32_t count; + + for (count = 0; count < 32; count++) { state->tlb[count].EntryDefined = 0; } + for (count = 0; count < 64; count++) { state->FastTlb[count].ValidEntry = 0; } + SetupTLB(state); +} + +void SetupTLB (usf_state_t * state) { + uint32_t count; + + memset(state->TLB_Map,0,(0xFFFFF * sizeof(uintptr_t))); + for (count = 0x80000000; count < 0xC0000000; count += 0x1000) { + state->TLB_Map[count >> 12] = ((uintptr_t)state->N64MEM + (count & 0x1FFFFFFF)) - count; + } + for (count = 0; count < 32; count ++) { SetupTLB_Entry(state, count); } +} +/* +test=(BYTE *) VirtualAlloc( 0x10, 0x70000, MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if(test == 0) { + //printf("FAIL!\n"); + exit(0); + } +*/ + +void SetupTLB_Entry (usf_state_t * state, int Entry) { + uint32_t FastIndx; + + + if (!state->tlb[Entry].EntryDefined) { return; } + FastIndx = Entry << 1; + state->FastTlb[FastIndx].VSTART=state->tlb[Entry].EntryHi.VPN2 << 13; + state->FastTlb[FastIndx].VEND = state->FastTlb[FastIndx].VSTART + (state->tlb[Entry].PageMask.Mask << 12) + 0xFFF; + state->FastTlb[FastIndx].PHYSSTART = state->tlb[Entry].EntryLo0.PFN << 12; + state->FastTlb[FastIndx].VALID = state->tlb[Entry].EntryLo0.V; + state->FastTlb[FastIndx].DIRTY = state->tlb[Entry].EntryLo0.D; + state->FastTlb[FastIndx].GLOBAL = state->tlb[Entry].EntryLo0.GLOBAL & state->tlb[Entry].EntryLo1.GLOBAL; + state->FastTlb[FastIndx].ValidEntry = 0; + + FastIndx = (Entry << 1) + 1; + state->FastTlb[FastIndx].VSTART=(state->tlb[Entry].EntryHi.VPN2 << 13) + ((state->tlb[Entry].PageMask.Mask << 12) + 0xFFF + 1); + state->FastTlb[FastIndx].VEND = state->FastTlb[FastIndx].VSTART + (state->tlb[Entry].PageMask.Mask << 12) + 0xFFF; + state->FastTlb[FastIndx].PHYSSTART = state->tlb[Entry].EntryLo1.PFN << 12; + state->FastTlb[FastIndx].VALID = state->tlb[Entry].EntryLo1.V; + state->FastTlb[FastIndx].DIRTY = state->tlb[Entry].EntryLo1.D; + state->FastTlb[FastIndx].GLOBAL = state->tlb[Entry].EntryLo0.GLOBAL & state->tlb[Entry].EntryLo1.GLOBAL; + state->FastTlb[FastIndx].ValidEntry = 0; + + for ( FastIndx = Entry << 1; FastIndx <= (Entry << 1) + 1; FastIndx++) { + uint32_t count; + + if (!state->FastTlb[FastIndx].VALID) { + state->FastTlb[FastIndx].ValidEntry = 1; + continue; + } + if (state->FastTlb[FastIndx].VEND <= state->FastTlb[FastIndx].VSTART) { + continue; + } + if (state->FastTlb[FastIndx].VSTART >= 0x80000000 && state->FastTlb[FastIndx].VEND <= 0xBFFFFFFF) { + continue; + } + if (state->FastTlb[FastIndx].PHYSSTART > 0x1FFFFFFF) { + continue; + } + + //test if overlap + state->FastTlb[FastIndx].ValidEntry = 1; + for (count = state->FastTlb[FastIndx].VSTART; count < state->FastTlb[FastIndx].VEND; count += 0x1000) { + state->TLB_Map[count >> 12] = ((uintptr_t)state->N64MEM + (count - state->FastTlb[FastIndx].VSTART + state->FastTlb[FastIndx].PHYSSTART)) - count; + } + } +} + +void TLB_Probe (usf_state_t * state) { + uint32_t Counter; + + + INDEX_REGISTER |= 0x80000000; + for (Counter = 0; Counter < 32; Counter ++) { + uint32_t TlbValue = state->tlb[Counter].EntryHi.Value & (~state->tlb[Counter].PageMask.Mask << 13); + uint32_t EntryHi = ENTRYHI_REGISTER & (~state->tlb[Counter].PageMask.Mask << 13); + + if (TlbValue == EntryHi) { + uint32_t Global = (state->tlb[Counter].EntryHi.Value & 0x100) != 0; + uint32_t SameAsid = ((state->tlb[Counter].EntryHi.Value & 0xFF) == (ENTRYHI_REGISTER & 0xFF)); + + if (Global || SameAsid) { + INDEX_REGISTER = Counter; + return; + } + } + } +} + +void TLB_Read (usf_state_t * state) { + uint32_t index = INDEX_REGISTER & 0x1F; + + PAGE_MASK_REGISTER = state->tlb[index].PageMask.Value ; + ENTRYHI_REGISTER = (state->tlb[index].EntryHi.Value & ~state->tlb[index].PageMask.Value) ; + ENTRYLO0_REGISTER = state->tlb[index].EntryLo0.Value; + ENTRYLO1_REGISTER = state->tlb[index].EntryLo1.Value; +} + +uint32_t TranslateVaddr ( usf_state_t * state, uintptr_t * Addr) { + if (state->TLB_Map[((*Addr) & 0xffffffff) >> 12] == 0) { return 0; } + *Addr = (uintptr_t)((uint8_t *)(state->TLB_Map[((*Addr) & 0xffffffff) >> 12] + ((*Addr) & 0xffffffff)) - (uintptr_t)state->N64MEM); + return 1; +} + +void WriteTLBEntry (usf_state_t * state, int32_t index) { + uint32_t FastIndx; + + FastIndx = index << 1; + if ((state->PROGRAM_COUNTER >= state->FastTlb[FastIndx].VSTART && + state->PROGRAM_COUNTER < state->FastTlb[FastIndx].VEND && + state->FastTlb[FastIndx].ValidEntry && state->FastTlb[FastIndx].VALID) + || + (state->PROGRAM_COUNTER >= state->FastTlb[FastIndx + 1].VSTART && + state->PROGRAM_COUNTER < state->FastTlb[FastIndx + 1].VEND && + state->FastTlb[FastIndx + 1].ValidEntry && state->FastTlb[FastIndx + 1].VALID)) + { + return; + } + + if (state->tlb[index].EntryDefined) { + uint32_t count; + + for ( FastIndx = index << 1; FastIndx <= (index << 1) + 1; FastIndx++) { + if (!state->FastTlb[FastIndx].ValidEntry) { continue; } + if (!state->FastTlb[FastIndx].VALID) { continue; } + for (count = state->FastTlb[FastIndx].VSTART; count < state->FastTlb[FastIndx].VEND; count += 0x1000) { + state->TLB_Map[count >> 12] = 0; + } + } + } + state->tlb[index].PageMask.Value = PAGE_MASK_REGISTER; + state->tlb[index].EntryHi.Value = ENTRYHI_REGISTER; + state->tlb[index].EntryLo0.Value = ENTRYLO0_REGISTER; + state->tlb[index].EntryLo1.Value = ENTRYLO1_REGISTER; + state->tlb[index].EntryDefined = 1; + + + SetupTLB_Entry(state, index); +} diff --git a/Frameworks/lazyusf/lazyusf/tlb.h b/Frameworks/lazyusf/lazyusf/tlb.h new file mode 100644 index 000000000..7127d132d --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/tlb.h @@ -0,0 +1,105 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#ifndef _TLB_H_ +#define _TLB_H_ + +typedef struct { + uint32_t EntryDefined; + union { + uint32_t Value; + uint8_t A[4]; + + struct { + unsigned zero : 13; + unsigned Mask : 12; + unsigned zero2 : 7; + } ; + + } PageMask; + + union { + uint32_t Value; + uint8_t A[4]; + + struct { + unsigned ASID : 8; + unsigned Zero : 4; + unsigned G : 1; + unsigned VPN2 : 19; + }; + + } EntryHi; + + union { + uint32_t Value; + uint8_t A[4]; + + struct { + unsigned GLOBAL: 1; + unsigned V : 1; + unsigned D : 1; + unsigned C : 3; + unsigned PFN : 20; + unsigned ZERO: 6; + }; + + } EntryLo0; + + union { + uint32_t Value; + uint8_t A[4]; + + struct { + unsigned GLOBAL: 1; + unsigned V : 1; + unsigned D : 1; + unsigned C : 3; + unsigned PFN : 20; + unsigned ZERO: 6; + } ; + + } EntryLo1; +} TLB; + +typedef struct { + uint32_t VSTART; + uint32_t VEND; + uint32_t PHYSSTART; + uint32_t VALID; + uint32_t DIRTY; + uint32_t GLOBAL; + uint32_t ValidEntry; +} FASTTLB; + +uint32_t AddressDefined ( usf_state_t *, uintptr_t VAddr); +void InitilizeTLB ( usf_state_t * ); +void SetupTLB ( usf_state_t * ); +void TLB_Probe ( usf_state_t * ); +void TLB_Read ( usf_state_t * ); +uint32_t TranslateVaddr ( usf_state_t *, uintptr_t * Addr); +void WriteTLBEntry ( usf_state_t *, int32_t index ); + +#endif diff --git a/Frameworks/lazyusf/lazyusf/types.h b/Frameworks/lazyusf/lazyusf/types.h new file mode 100644 index 000000000..30eb952cf --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/types.h @@ -0,0 +1,72 @@ +/* + * Project 64 - A Nintendo 64 emulator. + * + * (c) Copyright 2001 zilmar (zilmar@emulation64.com) and + * Jabo (jabo@emulation64.com). + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#ifndef __Types_h +#define __Types_h + +#include +typedef uint64_t QWORD; + +typedef union tagVect { + double FD[2]; + int64_t DW[2]; + uint64_t UDW[2]; + int32_t W[4]; + float FS[4]; + uint32_t UW[4]; + int16_t HW[8]; + uint16_t UHW[8]; + int8_t B[16]; + uint8_t UB[16]; +} VECTOR; + +typedef union tagUWORD { + int32_t W; + uint32_t UW; + int16_t HW[2]; + uint16_t UHW[2]; + int8_t B[4]; + uint8_t UB[4]; + float F; +} MIPS_WORD; + +typedef union tagUDWORD { + double D; + int64_t DW; + uint64_t UDW; + int32_t W[2]; + uint32_t UW[2]; + int16_t HW[4]; + uint16_t UHW[4]; + int8_t B[8]; + uint8_t UB[8]; + float F[2]; +} MIPS_DWORD; + +typedef MIPS_WORD MIPSUWORD; +typedef MIPS_DWORD MIPSUDWORD; + + +#endif diff --git a/Frameworks/lazyusf/lazyusf/usf.c b/Frameworks/lazyusf/lazyusf/usf.c new file mode 100644 index 000000000..8da164d62 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/usf.c @@ -0,0 +1,221 @@ + +#include + +#include "usf.h" +#include "cpu.h" +#include "memory.h" +#include "audio.h" + +#include +#include + +#include "types.h" + +#include "usf_internal.h" + +ssize_t get_usf_state_size() +{ + return sizeof(usf_state_t) + 8192 + 8192 + 0x100000 * sizeof(uintptr_t) + 0x1D000 + 0x800000; +} + +void usf_clear(void * state) +{ + ssize_t offset, offset_memchunk; + memset(state, 0, get_usf_state_size()); + offset = 4096 - (((uintptr_t)state) & 4095); + USF_STATE_HELPER->offset_to_structure = offset; + + offset_memchunk = ( offset + sizeof(usf_state_t) + 4095 ) & ~4095; + USF_STATE_HELPER->offset_to_memchunk = offset + offset_memchunk; + + //USF_STATE->savestatespace = NULL; + //USF_STATE->cpu_running = 0; + USF_STATE->cpu_stopped = 1; + + //USF_STATE->enablecompare = 0; + //USF_STATE->enableFIFOfull = 0; + + //USF_STATE->NextInstruction = 0; + //USF_STATE->JumpToLocation = 0; + //USF_STATE->AudioIntrReg = 0; + //USF_STATE->CPU_Action = 0; + //USF_STATE->Timers = 0; + //USF_STATE->CPURunning = 0; + //USF_STATE->SPHack = 0; + //USF_STATE->WaitMode = 0; + + //USF_STATE->TLB_Map = 0; + //USF_STATE->MemChunk = 0; + USF_STATE->RdramSize = 0x800000; + USF_STATE->SystemRdramSize = 0x800000; + USF_STATE->RomFileSize = 0x4000000; + + //USF_STATE->N64MEM = 0; + //USF_STATE->RDRAM = 0; + //USF_STATE->DMEM = 0; + //USF_STATE->IMEM = 0; + + //memset(USF_STATE->ROMPages, 0, sizeof(USF_STATE->ROMPages)); + //USF_STATE->savestatespace = 0; + //USF_STATE->NOMEM = 0; + + //USF_STATE->WrittenToRom = 0; + //USF_STATE->WroteToRom = 0; + //USF_STATE->TempValue = 0; + //USF_STATE->MemoryState = 0; + //USF_STATE->EmptySpace = 0; + + //USF_STATE->Registers = 0; + + //USF_STATE->PIF_Ram = 0; + + PreAllocate_Memory(USF_STATE); +} + +void usf_set_compare(void * state, int enable) +{ + USF_STATE->enablecompare = enable; +} + +void usf_set_fifo_full(void * state, int enable) +{ + USF_STATE->enableFIFOfull = enable; +} + +static uint32_t get_le32( const void * _p ) +{ + const uint8_t * p = (const uint8_t *) _p; + return p[0] + p[1] * 0x100 + p[2] * 0x10000 + p[3] * 0x1000000; +} + +int usf_upload_section(void * state, const uint8_t * data, ssize_t size) +{ + uint32_t temp; + + if ( size < 4 ) return -1; + temp = get_le32( data ); data += 4; size -= 4; + + if(temp == 0x34365253) { //there is a rom section + uint32_t len, start; + + if ( size < 4 ) return -1; + len = get_le32( data ); data += 4; size -= 4; + + while(len) { + if ( size < 4 ) return -1; + start = get_le32( data ); data += 4; size -= 4; + + while(len) { + int page = start >> 16; + int readLen = ( ((start + len) >> 16) > page) ? (((page + 1) << 16) - start) : len; + + if( USF_STATE->ROMPages[page] == 0 ) { + USF_STATE->ROMPages[page] = malloc(0x10000); + if ( USF_STATE->ROMPages[page] == 0 ) + return -1; + + memset(USF_STATE->ROMPages[page], 0, 0x10000); + } + + if ( size < readLen ) + return -1; + + memcpy( USF_STATE->ROMPages[page] + (start & 0xffff), data, readLen ); + data += readLen; size -= readLen; + + start += readLen; + len -= readLen; + } + + if ( size < 4 ) return -1; + len = get_le32( data ); data += 4; size -= 4; + } + } + + if ( size < 4 ) return -1; + temp = get_le32( data ); data += 4; size -= 4; + + if(temp == 0x34365253) { + uint32_t len, start; + + if ( size < 4 ) return -1; + len = get_le32( data ); data += 4; size -= 4; + + while(len) { + if ( size < 4 ) return -1; + start = get_le32( data ); data += 4; size -= 4; + + if ( size < len ) return -1; + memcpy( USF_STATE->savestatespace + start, data, len ); + data += len; size -= len; + + if ( size < 4 ) return -1; + len = get_le32( data ); data += 4; size -= 4; + } + } + + return 0; +} + +static void usf_startup(void * state) +{ + // Detect the Ramsize before the memory allocation + + if(*(uint32_t*)(USF_STATE->savestatespace + 4) == 0x400000) { + void * savestate; + USF_STATE->RdramSize = 0x400000; + savestate = realloc(USF_STATE->savestatespace, 0x40275c); + if ( savestate ) + USF_STATE->savestatespace = savestate; + } else if(*(uint32_t*)(USF_STATE->savestatespace + 4) == 0x800000) + USF_STATE->RdramSize = 0x800000; + + Allocate_Memory(state); + + StartEmulationFromSave(USF_STATE, USF_STATE->savestatespace); +} + +void usf_render(void * state, int16_t * buffer, ssize_t count, int32_t * sample_rate) +{ + if ( !USF_STATE->MemoryState ) + usf_startup( USF_STATE ); + + if ( USF_STATE->samples_in_buffer ) + { + ssize_t do_max = USF_STATE->samples_in_buffer; + if ( do_max > count ) + do_max = count; + + memcpy( buffer, USF_STATE->samplebuf, sizeof(int16_t) * 2 * do_max ); + + USF_STATE->samples_in_buffer -= do_max; + + if ( sample_rate ) + *sample_rate = USF_STATE->SampleRate; + + if ( USF_STATE->samples_in_buffer ) + { + memmove( USF_STATE->samplebuf, USF_STATE->samplebuf + do_max, sizeof(int16_t) * 2 * USF_STATE->samples_in_buffer ); + return; + } + + buffer += 2 * do_max; + count -= do_max; + } + + USF_STATE->sample_buffer = buffer; + USF_STATE->sample_buffer_count = count; + + USF_STATE->cpu_stopped = 0; + USF_STATE->cpu_running = 1; + + StartInterpreterCPU(USF_STATE); + + if ( sample_rate ) + *sample_rate = USF_STATE->SampleRate; +} + +void usf_shutdown(void * state) +{ + Release_Memory(USF_STATE); +} diff --git a/Frameworks/lazyusf/lazyusf/usf.h b/Frameworks/lazyusf/lazyusf/usf.h new file mode 100644 index 000000000..77f14ce0c --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/usf.h @@ -0,0 +1,41 @@ +#ifndef _USF_H_ +#define _USF_H_ +#define _CRT_SECURE_NO_WARNINGS + + +#include +#include +#include +#include +#include + +typedef struct usf_state usf_state_t; + +typedef struct usf_state_helper usf_state_helper_t; + +#include "usf.h" +#include "cpu.h" +#include "memory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ssize_t get_usf_state_size(); + +void usf_clear(void * state); + +void usf_set_compare(void * state, int enable); +void usf_set_fifo_full(void * state, int enable); + +int usf_upload_section(void * state, const uint8_t * data, ssize_t size); + +void usf_render(void * state, int16_t * buffer, ssize_t count, int32_t * sample_rate); + +void usf_shutdown(void * state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Frameworks/lazyusf/lazyusf/usf_internal.h b/Frameworks/lazyusf/lazyusf/usf_internal.h new file mode 100644 index 000000000..329e9cee1 --- /dev/null +++ b/Frameworks/lazyusf/lazyusf/usf_internal.h @@ -0,0 +1,105 @@ +#ifndef _USF_INTERNAL_H_ +#define _USF_INTERNAL_H_ + +struct usf_state_helper +{ + ssize_t offset_to_structure; + ssize_t offset_to_memchunk; +}; + +typedef uint32_t RCPREG; + +struct usf_state +{ + // RSP vector registers, need to be aligned to 16 bytes + short VR[32][8]; + short VACC[3][8]; + + // RSP virtual registers + int SR[32]; + + // rsp/rsp.c + RCPREG* CR[16]; + + // rsp/vu/cf.h + short ne[8]; /* $vco: high byte "NOTEQUAL" */ + short co[8]; /* $vco: low byte "carry/borrow in/out" */ + short clip[8]; /* $vcc: high byte (clip tests: VCL, VCH, VCR) */ + short comp[8]; /* $vcc: low byte (VEQ, VNE, VLT, VGE, VCL, VCH, VCR) */ + short vce[8]; /* $vce: vector compare extension register */ + + // rsp/vu/divrom.h + int DivIn; /* buffered numerator of division read from vector file */ + int DivOut; /* global division result set by VRCP/VRCPL/VRSQ/VRSQH */ +#if (0) + int MovIn; /* We do not emulate this register (obsolete, for VMOV). */ +#endif + + int DPH; + + // rsp/rsp.h + int temp_PC; + short MFC0_count[32]; + + uint32_t cpu_running, cpu_stopped; + + // options from file tags + uint32_t enablecompare, enableFIFOfull; + + // buffering for rendered sample data + ssize_t sample_buffer_count; + int16_t * sample_buffer; + + // audio.c + int32_t SampleRate; + int16_t samplebuf[16384]; + ssize_t samples_in_buffer; + + // cpu.c + uint32_t NextInstruction, JumpToLocation, AudioIntrReg; + CPU_ACTION * CPU_Action; + SYSTEM_TIMERS * Timers; + OPCODE Opcode; + uint32_t CPURunning, SPHack; + uint32_t * WaitMode; + + // interpreter_ops.c + uint32_t SWL_MASK[4], SWR_MASK[4], LWL_MASK[4], LWR_MASK[4]; + int32_t SWL_SHIFT[4], SWR_SHIFT[4], LWL_SHIFT[4], LWR_SHIFT[4]; + int32_t RoundingModel; + + // memory.c + uintptr_t *TLB_Map; + uint8_t * MemChunk; + uint32_t RdramSize, SystemRdramSize, RomFileSize; + uint8_t * N64MEM, * RDRAM, * DMEM, * IMEM, * ROMPages[0x400], * savestatespace, * NOMEM; + + uint32_t WrittenToRom; + uint32_t WroteToRom; + uint32_t TempValue; + uint32_t MemoryState; + + uint8_t EmptySpace; + + // pif.c + uint8_t *PIF_Ram; + + // registers.c + uint32_t PROGRAM_COUNTER, * CP0,*FPCR,*RegRDRAM,*RegSP,*RegDPC,*RegMI,*RegVI,*RegAI,*RegPI, + *RegRI,*RegSI, HalfLine, RegModValue, ViFieldNumber, LLBit, LLAddr; + void * FPRDoubleLocation[32], * FPRFloatLocation[32]; + MIPS_DWORD *GPR, *FPR, HI, LO; + int32_t fpuControl; + N64_REGISTERS * Registers; + + // tlb.c + FASTTLB FastTlb[64]; + TLB tlb[32]; +}; + +#define USF_STATE_HELPER ((usf_state_helper_t *)(state)) + +#define USF_STATE ((usf_state_t *)(((uint8_t *)(state))+((usf_state_helper_t *)(state))->offset_to_structure)) +#define USF_CHUNK (((uint8_t*)(state))+((usf_state_helper_t *)(state))->offset_to_memchunk) + +#endif diff --git a/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj b/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj index 222877755..ac8000f59 100644 --- a/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj +++ b/Plugins/HighlyComplete/HighlyComplete.xcodeproj/project.pbxproj @@ -21,7 +21,8 @@ 8360EF6E17F92E86005208A4 /* HighlyExperimental.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8360EF4417F92C92005208A4 /* HighlyExperimental.framework */; }; 8384904A180764B500E7332D /* SSEQPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; }; 8384904B180764C200E7332D /* SSEQPlayer.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83848FEC1807624000E7332D /* SSEQPlayer.framework */; }; - 83D4481E18ACA5C8000F443A /* lazyusf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83D4481B18ACA5AD000F443A /* lazyusf */; }; + 83C8B6FB18AF58FA0071B040 /* lazyusf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83C8B65618AF57770071B040 /* lazyusf.framework */; }; + 83C8B6FC18AF59080071B040 /* lazyusf.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83C8B65618AF57770071B040 /* lazyusf.framework */; }; 83DE0CBC180B02CC00269051 /* vio2sf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83DE0C3A180A9BD500269051 /* vio2sf.framework */; }; 83DE0CBD180B02D800269051 /* vio2sf.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83DE0C3A180A9BD500269051 /* vio2sf.framework */; }; 83DE0CC0180B27C200269051 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 83DE0CBF180B27C200269051 /* libz.dylib */; }; @@ -113,6 +114,13 @@ remoteGlobalIDString = 83848FB71807623F00E7332D; remoteInfo = SSEQPlayer; }; + 83C8B65518AF57770071B040 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83C8B65018AF57770071B040 /* lazyusf.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 83C8B62218AF57770071B040; + remoteInfo = lazyusf; + }; 83DE0C39180A9BD500269051 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */; @@ -136,7 +144,6 @@ dstPath = ""; dstSubfolderSpec = 6; files = ( - 83D4481E18ACA5C8000F443A /* lazyusf in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -146,6 +153,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 83C8B6FC18AF59080071B040 /* lazyusf.framework in CopyFiles */, 83DE0CBD180B02D800269051 /* vio2sf.framework in CopyFiles */, 8384904B180764C200E7332D /* SSEQPlayer.framework in CopyFiles */, 834379A617F97EB000584396 /* HighlyAdvanced.framework in CopyFiles */, @@ -178,7 +186,7 @@ 8360EEF317F92AC8005208A4 /* HighlyComplete-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HighlyComplete-Prefix.pch"; sourceTree = ""; }; 8360EF3E17F92C91005208A4 /* HighlyExperimental.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyExperimental.xcodeproj; path = ../../Frameworks/HighlyExperimental/HighlyExperimental.xcodeproj; sourceTree = ""; }; 83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SSEQPlayer.xcodeproj; path = ../../Frameworks/SSEQPlayer/SSEQPlayer.xcodeproj; sourceTree = ""; }; - 83D4481B18ACA5AD000F443A /* lazyusf */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = lazyusf; path = ../../ThirdParty/lazyusf/lazyusf; sourceTree = ""; }; + 83C8B65018AF57770071B040 /* lazyusf.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = lazyusf.xcodeproj; path = ../../Frameworks/lazyusf/lazyusf.xcodeproj; sourceTree = ""; }; 83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = vio2sf.xcodeproj; path = ../../Frameworks/vio2sf/vio2sf.xcodeproj; sourceTree = ""; }; 83DE0CBF180B27C200269051 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; 83FAF8A318ADD27F00057CAF /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = ""; }; @@ -189,6 +197,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 83C8B6FB18AF58FA0071B040 /* lazyusf.framework in Frameworks */, 83DE0CC0180B27C200269051 /* libz.dylib in Frameworks */, 83DE0CBC180B02CC00269051 /* vio2sf.framework in Frameworks */, 8384904A180764B500E7332D /* SSEQPlayer.framework in Frameworks */, @@ -239,7 +248,6 @@ 8360EEDB17F92AC8005208A4 = { isa = PBXGroup; children = ( - 83D4481D18ACA5B1000F443A /* External */, 8360EEED17F92AC8005208A4 /* HighlyComplete */, 8360EEE617F92AC8005208A4 /* Frameworks */, 8360EEE517F92AC8005208A4 /* Products */, @@ -267,6 +275,7 @@ 8343796317F97BDB00584396 /* HighlyAdvanced.xcodeproj */, 83848FE61807623F00E7332D /* SSEQPlayer.xcodeproj */, 83DE0C34180A9BD400269051 /* vio2sf.xcodeproj */, + 83C8B65018AF57770071B040 /* lazyusf.xcodeproj */, ); name = Frameworks; sourceTree = ""; @@ -321,12 +330,12 @@ name = Products; sourceTree = ""; }; - 83D4481D18ACA5B1000F443A /* External */ = { + 83C8B65118AF57770071B040 /* Products */ = { isa = PBXGroup; children = ( - 83D4481B18ACA5AD000F443A /* lazyusf */, + 83C8B65618AF57770071B040 /* lazyusf.framework */, ); - name = External; + name = Products; sourceTree = ""; }; 83DE0C35180A9BD400269051 /* Products */ = { @@ -402,6 +411,10 @@ ProductGroup = 8343789D17F9658E00584396 /* Products */; ProjectRef = 8343789C17F9658E00584396 /* HighlyTheoretical.xcodeproj */; }, + { + ProductGroup = 83C8B65118AF57770071B040 /* Products */; + ProjectRef = 83C8B65018AF57770071B040 /* lazyusf.xcodeproj */; + }, { ProductGroup = 8343784B17F93CB500584396 /* Products */; ProjectRef = 8343784A17F93CB500584396 /* psflib.xcodeproj */; @@ -465,6 +478,13 @@ remoteRef = 83848FEB1807624000E7332D /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 83C8B65618AF57770071B040 /* lazyusf.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = lazyusf.framework; + remoteRef = 83C8B65518AF57770071B040 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 83DE0C3A180A9BD500269051 /* vio2sf.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; diff --git a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm index 0fca2ad35..2c13078c6 100644 --- a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm +++ b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm @@ -30,6 +30,8 @@ #import +#import + #include #include @@ -896,197 +898,10 @@ static int twosf_info(void * context, const char * name, const char * value) struct usf_loader_state { -#ifdef USF_LOG - FILE * log; -#endif - NSTask * task; - NSPipe * pipe_stdin; - NSPipe * pipe_stdout; - NSFileHandle * file_stdin; - NSFileHandle * file_stdout; - bool donewriting; uint32_t enablecompare; uint32_t enablefifofull; - uint32_t samplerate; - uint32_t pairsleft; - - BOOL error_occurred; - - usf_loader_state() - : -#ifdef USF_LOG - log(NULL), -#endif - task(nil), pipe_stdin(nil), pipe_stdout(nil), - enablecompare(0), enablefifofull(0), - samplerate(0), pairsleft(0), - error_occurred(NO) { } - - ~usf_loader_state() - { - close(); - } - - void fwrite( const void * buf, ssize_t size, ssize_t count ) - { - if ( error_occurred ) - return; - - @try - { - [file_stdin writeData:[NSData dataWithBytes:buf length:size * count]]; - } - @catch (NSException *) - { - error_occurred = YES; - close(); - return; - } -#ifdef USF_LOG - if ( log ) - { - ::fwrite( buf, size, count, log ); - fflush( log ); - } -#endif - } - - ssize_t fread( void * buf, ssize_t size, ssize_t count ) - { - if ( error_occurred ) - return 0; - - NSData * data = nil; - @try - { - data = [file_stdout readDataOfLength:size * count]; - } - @catch (NSException *) - { - error_occurred = YES; - close(); - return 0; - } - if ( data && [data length] ) - { - memcpy( buf, [data bytes], [data length] ); - return [data length] / size; - } - return 0; - } - - void open() - { - close(); - -#ifdef USF_LOG - log = fopen("/tmp/lazyusf_transaction", "w"); -#endif - Dl_info info; - dladdr( (void*) &twosf_info, &info ); - - NSString * base_path = [[NSString stringWithUTF8String:info.dli_fname] stringByDeletingLastPathComponent]; - - task = [[NSTask alloc] init]; - [task setLaunchPath:[base_path stringByAppendingPathComponent:@"lazyusf"]]; - - pipe_stdin = [[NSPipe alloc] init]; - pipe_stdout = [[NSPipe alloc] init]; - - [task setStandardInput:pipe_stdin]; - [task setStandardOutput:pipe_stdout]; - - file_stdin = [pipe_stdin fileHandleForWriting]; - file_stdout = [pipe_stdout fileHandleForReading]; - - @try - { - [task launch]; - } - @catch (NSException *) - { - error_occurred = YES; - close(); - return; - } - - fwrite( &enablecompare, sizeof(enablecompare), 1 ); - fwrite( &enablefifofull, sizeof(enablefifofull), 1 ); - donewriting = false; - } - - void close() - { - if (task != nil) - { - if ( !error_occurred ) - { - uint32_t zero = 0; - fwrite( &zero, sizeof(uint32_t), 1 ); - } - [task release]; - task = nil; - [pipe_stdin release]; - pipe_stdin = nil; - [pipe_stdout release]; - pipe_stdout = nil; - } -#ifdef USF_LOG - if (log) fclose(log); - log = NULL; -#endif - } - - bool opened() - { - return task != nil; - } - - void write_reserved( const uint8_t * reserved, uint32_t reserved_size ) - { - fwrite( &reserved_size, sizeof(reserved_size), 1 ); - if ( reserved_size ) fwrite( reserved, 1, reserved_size ); - } - - BOOL read_samples( int16_t * out, ssize_t out_pairs ) - { - if ( !donewriting ) - { - write_reserved( NULL, 0 ); -#ifdef USF_LOG - fclose( log ); log = NULL; -#endif - donewriting = true; - } - while ( out_pairs ) - { - if ( !pairsleft ) - { - if (fread( &samplerate, sizeof(samplerate), 1 ) < 1) return NO; - if (fread( &pairsleft, sizeof(pairsleft), 1 ) < 1) return NO; - pairsleft >>= 1; - } - if ( pairsleft ) - { - if ( pairsleft > out_pairs ) - { - if (fread( out, sizeof(int16_t) * 2, out_pairs ) < out_pairs) return NO; - pairsleft -= out_pairs; - return YES; - } - - if (fread( out, sizeof(int16_t) * 2, pairsleft ) < pairsleft) return NO; - out += pairsleft * 2; - out_pairs -= pairsleft; - pairsleft = 0; - - uint32_t one = 1; - fwrite( &one, sizeof(one), 1 ); - } - } - return YES; - } + void * emu_state; }; static int usf_loader(void * context, const uint8_t * exe, size_t exe_size, @@ -1094,15 +909,8 @@ static int usf_loader(void * context, const uint8_t * exe, size_t exe_size, { struct usf_loader_state * uUsf = ( struct usf_loader_state * ) context; if ( exe && exe_size > 0 ) return -1; - - if ( !uUsf->opened() ) uUsf->open(); - - uUsf->write_reserved( reserved, (uint32_t) reserved_size ); - if ( uUsf->error_occurred ) - return -1; - - return 0; + return usf_upload_section( uUsf->emu_state, reserved, reserved_size ); } static int usf_info(void * context, const char * name, const char * value) @@ -1189,12 +997,20 @@ static int usf_info(void * context, const char * name, const char * value) } else if ( type == 0x21 ) { - struct usf_loader_state * uUsf = new usf_loader_state; + struct usf_loader_state state; + memset( &state, 0, sizeof(state) ); + + state.emu_state = malloc( get_usf_state_size() ); - emulatorCore = (uint8_t *) uUsf; + usf_clear( state.emu_state ); - if ( psf_load( [currentUrl UTF8String], &source_callbacks, 0x21, usf_loader, uUsf, usf_info, uUsf ) <= 0 ) + emulatorCore = ( uint8_t * ) state.emu_state; + + if ( psf_load( [currentUrl UTF8String], &source_callbacks, 0x21, usf_loader, &state, usf_info, &state ) <= 0 ) return NO; + + usf_set_compare( state.emu_state, state.enablecompare ); + usf_set_fifo_full( state.emu_state, state.enablefifofull ); } else if ( type == 0x22 ) { @@ -1474,12 +1290,11 @@ static int usf_info(void * context, const char * name, const char * value) } else if ( type == 0x21 ) { - struct usf_loader_state * uUsf = ( struct usf_loader_state * ) emulatorCore; + int32_t samplerate; + + usf_render( emulatorCore, (int16_t*) buf, frames, &samplerate ); - if ( !uUsf->read_samples( (int16_t *) buf, frames ) ) - return 0; - - sampleRate = uUsf->samplerate; + sampleRate = samplerate; } else if ( type == 0x22 ) { @@ -1595,8 +1410,8 @@ static int usf_info(void * context, const char * name, const char * value) { if ( emulatorCore ) { if ( type == 0x21 ) { - struct usf_loader_state * uUsf = ( struct usf_loader_state * ) emulatorCore; - delete uUsf; + usf_shutdown( emulatorCore ); + free( emulatorCore ); } else if ( type == 0x22 ) { GBASystem * system = ( GBASystem * ) emulatorCore; CPUCleanUp( system ); @@ -1690,13 +1505,12 @@ static int usf_info(void * context, const char * name, const char * value) } else if ( type == 0x21 ) { - struct usf_loader_state * uUsf = ( struct usf_loader_state * ) emulatorCore; int16_t temp[2048]; do { ssize_t howmany = frame - framesRead; if (howmany > 1024) howmany = 1024; - if (!uUsf->read_samples( temp, howmany )) return -1; + usf_render(emulatorCore, temp, howmany, NULL); framesRead += howmany; } while (framesRead < frame); } diff --git a/ThirdParty/lazyusf/lazyusf b/ThirdParty/lazyusf/lazyusf deleted file mode 100755 index a6c9d528b..000000000 Binary files a/ThirdParty/lazyusf/lazyusf and /dev/null differ