From f086d8c9bf72972524d9d5c35f7cf14648d593a3 Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Sat, 15 Feb 2014 01:37:59 -0800 Subject: [PATCH] Imported lazyusf in its new library form and removed the external app --- .../lazyusf/lazyusf.xcodeproj/project.pbxproj | 621 +++++++ Frameworks/lazyusf/lazyusf/audio.c | 82 + Frameworks/lazyusf/lazyusf/audio.h | 12 + Frameworks/lazyusf/lazyusf/config.h | 63 + Frameworks/lazyusf/lazyusf/cpu.c | 551 ++++++ Frameworks/lazyusf/lazyusf/cpu.h | 93 + Frameworks/lazyusf/lazyusf/dma.c | 177 ++ Frameworks/lazyusf/lazyusf/dma.h | 34 + Frameworks/lazyusf/lazyusf/exception.c | 147 ++ Frameworks/lazyusf/lazyusf/exception.h | 75 + Frameworks/lazyusf/lazyusf/interpreter_cpu.c | 738 ++++++++ Frameworks/lazyusf/lazyusf/interpreter_cpu.h | 37 + Frameworks/lazyusf/lazyusf/interpreter_ops.c | 1335 ++++++++++++++ Frameworks/lazyusf/lazyusf/interpreter_ops.h | 206 +++ Frameworks/lazyusf/lazyusf/lazyusf-Info.plist | 30 + Frameworks/lazyusf/lazyusf/main.c | 31 + Frameworks/lazyusf/lazyusf/main.h | 10 + Frameworks/lazyusf/lazyusf/memory.c | 748 ++++++++ Frameworks/lazyusf/lazyusf/memory.h | 58 + Frameworks/lazyusf/lazyusf/opcode.h | 274 +++ Frameworks/lazyusf/lazyusf/pif.c | 97 ++ Frameworks/lazyusf/lazyusf/pif.h | 29 + Frameworks/lazyusf/lazyusf/registers.c | 145 ++ Frameworks/lazyusf/lazyusf/registers.h | 378 ++++ Frameworks/lazyusf/lazyusf/rsp.h | 11 + Frameworks/lazyusf/lazyusf/rsp/config.h | 60 + Frameworks/lazyusf/lazyusf/rsp/execute.h | 475 +++++ Frameworks/lazyusf/lazyusf/rsp/rsp.c | 66 + Frameworks/lazyusf/lazyusf/rsp/rsp.h | 62 + Frameworks/lazyusf/lazyusf/rsp/su.h | 1537 +++++++++++++++++ Frameworks/lazyusf/lazyusf/rsp/vu/cf.h | 191 ++ Frameworks/lazyusf/lazyusf/rsp/vu/clamp.h | 255 +++ Frameworks/lazyusf/lazyusf/rsp/vu/divrom.h | 1111 ++++++++++++ Frameworks/lazyusf/lazyusf/rsp/vu/shuffle.h | 278 +++ Frameworks/lazyusf/lazyusf/rsp/vu/vabs.h | 77 + Frameworks/lazyusf/lazyusf/rsp/vu/vadd.h | 37 + Frameworks/lazyusf/lazyusf/rsp/vu/vaddc.h | 40 + Frameworks/lazyusf/lazyusf/rsp/vu/vand.h | 33 + Frameworks/lazyusf/lazyusf/rsp/vu/vch.h | 84 + Frameworks/lazyusf/lazyusf/rsp/vu/vcl.h | 100 ++ Frameworks/lazyusf/lazyusf/rsp/vu/vcr.h | 67 + Frameworks/lazyusf/lazyusf/rsp/vu/veq.h | 47 + Frameworks/lazyusf/lazyusf/rsp/vu/vge.h | 51 + Frameworks/lazyusf/lazyusf/rsp/vu/vlt.h | 51 + Frameworks/lazyusf/lazyusf/rsp/vu/vmacf.h | 51 + Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h | 23 + Frameworks/lazyusf/lazyusf/rsp/vu/vmacu.h | 51 + Frameworks/lazyusf/lazyusf/rsp/vu/vmadh.h | 41 + Frameworks/lazyusf/lazyusf/rsp/vu/vmadl.h | 49 + Frameworks/lazyusf/lazyusf/rsp/vu/vmadm.h | 44 + Frameworks/lazyusf/lazyusf/rsp/vu/vmadn.h | 44 + Frameworks/lazyusf/lazyusf/rsp/vu/vmov.h | 21 + Frameworks/lazyusf/lazyusf/rsp/vu/vmrg.h | 30 + Frameworks/lazyusf/lazyusf/rsp/vu/vmudh.h | 37 + Frameworks/lazyusf/lazyusf/rsp/vu/vmudl.h | 37 + Frameworks/lazyusf/lazyusf/rsp/vu/vmudm.h | 37 + Frameworks/lazyusf/lazyusf/rsp/vu/vmudn.h | 37 + Frameworks/lazyusf/lazyusf/rsp/vu/vmulf.h | 55 + Frameworks/lazyusf/lazyusf/rsp/vu/vmulu.h | 57 + Frameworks/lazyusf/lazyusf/rsp/vu/vnand.h | 33 + Frameworks/lazyusf/lazyusf/rsp/vu/vne.h | 47 + Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h | 23 + Frameworks/lazyusf/lazyusf/rsp/vu/vnor.h | 33 + Frameworks/lazyusf/lazyusf/rsp/vu/vnxor.h | 33 + Frameworks/lazyusf/lazyusf/rsp/vu/vor.h | 33 + Frameworks/lazyusf/lazyusf/rsp/vu/vrcp.h | 25 + Frameworks/lazyusf/lazyusf/rsp/vu/vrcph.h | 24 + Frameworks/lazyusf/lazyusf/rsp/vu/vrcpl.h | 26 + Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h | 26 + Frameworks/lazyusf/lazyusf/rsp/vu/vrsqh.h | 24 + Frameworks/lazyusf/lazyusf/rsp/vu/vrsql.h | 26 + Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h | 68 + Frameworks/lazyusf/lazyusf/rsp/vu/vsub.h | 37 + Frameworks/lazyusf/lazyusf/rsp/vu/vsubc.h | 40 + Frameworks/lazyusf/lazyusf/rsp/vu/vu.h | 120 ++ Frameworks/lazyusf/lazyusf/rsp/vu/vxor.h | 33 + Frameworks/lazyusf/lazyusf/tlb.c | 193 +++ Frameworks/lazyusf/lazyusf/tlb.h | 105 ++ Frameworks/lazyusf/lazyusf/types.h | 72 + Frameworks/lazyusf/lazyusf/usf.c | 221 +++ Frameworks/lazyusf/lazyusf/usf.h | 41 + Frameworks/lazyusf/lazyusf/usf_internal.h | 105 ++ .../HighlyComplete.xcodeproj/project.pbxproj | 34 +- .../HighlyComplete/HCDecoder.mm | 230 +-- ThirdParty/lazyusf/lazyusf | Bin 119608 -> 0 bytes 85 files changed, 12655 insertions(+), 215 deletions(-) create mode 100644 Frameworks/lazyusf/lazyusf.xcodeproj/project.pbxproj create mode 100644 Frameworks/lazyusf/lazyusf/audio.c create mode 100644 Frameworks/lazyusf/lazyusf/audio.h create mode 100644 Frameworks/lazyusf/lazyusf/config.h create mode 100644 Frameworks/lazyusf/lazyusf/cpu.c create mode 100644 Frameworks/lazyusf/lazyusf/cpu.h create mode 100644 Frameworks/lazyusf/lazyusf/dma.c create mode 100644 Frameworks/lazyusf/lazyusf/dma.h create mode 100644 Frameworks/lazyusf/lazyusf/exception.c create mode 100644 Frameworks/lazyusf/lazyusf/exception.h create mode 100644 Frameworks/lazyusf/lazyusf/interpreter_cpu.c create mode 100644 Frameworks/lazyusf/lazyusf/interpreter_cpu.h create mode 100644 Frameworks/lazyusf/lazyusf/interpreter_ops.c create mode 100644 Frameworks/lazyusf/lazyusf/interpreter_ops.h create mode 100644 Frameworks/lazyusf/lazyusf/lazyusf-Info.plist create mode 100644 Frameworks/lazyusf/lazyusf/main.c create mode 100644 Frameworks/lazyusf/lazyusf/main.h create mode 100644 Frameworks/lazyusf/lazyusf/memory.c create mode 100644 Frameworks/lazyusf/lazyusf/memory.h create mode 100644 Frameworks/lazyusf/lazyusf/opcode.h create mode 100644 Frameworks/lazyusf/lazyusf/pif.c create mode 100644 Frameworks/lazyusf/lazyusf/pif.h create mode 100644 Frameworks/lazyusf/lazyusf/registers.c create mode 100644 Frameworks/lazyusf/lazyusf/registers.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/config.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/execute.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/rsp.c create mode 100644 Frameworks/lazyusf/lazyusf/rsp/rsp.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/su.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/cf.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/clamp.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/divrom.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/shuffle.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vabs.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vadd.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vaddc.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vand.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vch.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vcl.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vcr.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/veq.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vge.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vlt.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmacf.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmacu.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmadh.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmadl.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmadm.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmadn.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmov.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmrg.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmudh.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmudl.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmudm.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmudn.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmulf.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vmulu.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vnand.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vne.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vnor.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vnxor.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vor.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vrcp.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vrcph.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vrcpl.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vrsqh.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vrsql.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vsub.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vsubc.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vu.h create mode 100644 Frameworks/lazyusf/lazyusf/rsp/vu/vxor.h create mode 100644 Frameworks/lazyusf/lazyusf/tlb.c create mode 100644 Frameworks/lazyusf/lazyusf/tlb.h create mode 100644 Frameworks/lazyusf/lazyusf/types.h create mode 100644 Frameworks/lazyusf/lazyusf/usf.c create mode 100644 Frameworks/lazyusf/lazyusf/usf.h create mode 100644 Frameworks/lazyusf/lazyusf/usf_internal.h delete mode 100755 ThirdParty/lazyusf/lazyusf 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 a6c9d528bb4833fdba18379ad7137da8f265d5b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119608 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 RVk5=tFlxNrQv5v#{trupWF-Iq