mirror of
https://github.com/shadergz/cosmic-station.git
synced 2024-11-23 06:09:40 +00:00
Fuji,EE,IOP
: Now our MIPS can make SYSCALL
This commit is contained in:
parent
52fe114081
commit
7e9694a119
@ -48,6 +48,7 @@ target_sources(zenith PRIVATE
|
||||
${ZENITH_DIR}/hle/bios_patch.cpp
|
||||
${ZENITH_DIR}/hle/group_mgr.cpp
|
||||
${ZENITH_DIR}/hle/bios_class.cpp
|
||||
${ZENITH_DIR}/hle/syscall_gate.cpp
|
||||
${ZENITH_DIR}/fs/bios_loader.cpp
|
||||
${ZENITH_DIR}/iop/iop_core.cpp
|
||||
${ZENITH_DIR}/iop/iop_cop.cpp
|
||||
@ -63,6 +64,7 @@ target_sources(zenith PRIVATE
|
||||
${ZENITH_DIR}/console/emu_thread.cpp
|
||||
${ZENITH_DIR}/console/sched_logical.cpp
|
||||
${ZENITH_DIR}/console/intc.cpp
|
||||
${ZENITH_DIR}/console/backdoor.cpp
|
||||
${ZENITH_MISC_DIR}/jvm_comm.cpp
|
||||
${ZENITH_MISC_DIR}/drivers_glvk_jni.cpp
|
||||
${ZENITH_MISC_DIR}/bios_jni.cpp
|
||||
|
46
app/src/main/cpp/zenith/console/backdoor.cpp
Normal file
46
app/src/main/cpp/zenith/console/backdoor.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include <console/backdoor.h>
|
||||
|
||||
namespace zenith {
|
||||
std::shared_ptr<console::RedPillow> redBox;
|
||||
}
|
||||
|
||||
namespace zenith::console {
|
||||
RedPillow::RedPillow(EmuVM& aliveVm) {
|
||||
vm = std::make_unique<raw_reference<EmuVM>>(std::ref(aliveVm));
|
||||
mutual = std::unique_lock<std::mutex>();
|
||||
vmRefs = 1;
|
||||
}
|
||||
raw_reference<EmuVM> RedPillow::openVm() {
|
||||
std::thread::id nub{};
|
||||
if (owner != std::this_thread::get_id()) {
|
||||
mutual.lock();
|
||||
owner = nub;
|
||||
}
|
||||
if (owner != nub) {
|
||||
if (owner != std::this_thread::get_id())
|
||||
throw AppFail("This resource should have the lock held until the object is released");
|
||||
} else {
|
||||
owner = std::this_thread::get_id();
|
||||
}
|
||||
raw_reference<EmuVM> vmRef{};
|
||||
if (vmRefs) {
|
||||
vmRef = *vm;
|
||||
vmRefs++;
|
||||
}
|
||||
return vmRef;
|
||||
}
|
||||
void RedPillow::leaveVm(raw_reference<EmuVM> lvm) {
|
||||
if (!mutual.try_lock()) {
|
||||
if (owner != std::this_thread::get_id())
|
||||
throw AppFail("The program flow is broken, review the usage of RedPillow in the code");
|
||||
}
|
||||
vmRefs--;
|
||||
if (!vm || vmRefs <= 0) {
|
||||
vm.reset();
|
||||
vm = std::make_unique<raw_reference<EmuVM>>(lvm);
|
||||
vmRefs = 1;
|
||||
}
|
||||
owner = {};
|
||||
mutual.unlock();
|
||||
}
|
||||
}
|
28
app/src/main/cpp/zenith/console/backdoor.h
Normal file
28
app/src/main/cpp/zenith/console/backdoor.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/types.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
namespace zenith::console {
|
||||
class EmuVM;
|
||||
|
||||
class RedPillow {
|
||||
public:
|
||||
RedPillow(EmuVM& aliveVm);
|
||||
|
||||
raw_reference<EmuVM> openVm();
|
||||
void leaveVm(raw_reference<EmuVM> lvm);
|
||||
|
||||
private:
|
||||
std::thread::id owner;
|
||||
std::unique_lock<std::mutex> mutual;
|
||||
std::unique_ptr<raw_reference<EmuVM>> vm;
|
||||
i32 vmRefs;
|
||||
};
|
||||
}
|
||||
|
||||
namespace zenith {
|
||||
extern std::shared_ptr<console::RedPillow> redBox;
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
// SPDX-short-identifier: MIT, Version N/A
|
||||
// This file is protected by the MIT license (please refer to LICENSE.md before making any changes, copying, or redistributing this software)
|
||||
#include <console/emu_vm.h>
|
||||
#include <common/global.h>
|
||||
#include <console/emu_vm.h>
|
||||
#include <console/backdoor.h>
|
||||
|
||||
#include <eeiv/ee_info.h>
|
||||
#define TestBiosAccess 0
|
||||
namespace zenith::console {
|
||||
EmuVM::EmuVM(JNIEnv* env,
|
||||
@ -22,6 +24,8 @@ namespace zenith::console {
|
||||
frames = 30;
|
||||
|
||||
intc = std::make_shared<INTCInfra>(*this);
|
||||
// Our way to perform interconnection between different isolated components
|
||||
redBox = std::make_shared<RedPillow>(*this);
|
||||
}
|
||||
|
||||
void EmuVM::startVM() {
|
||||
@ -55,4 +59,20 @@ namespace zenith::console {
|
||||
mips->resetCore();
|
||||
iop->resetIOP();
|
||||
}
|
||||
void EmuVM::dealWithSyscalls() {
|
||||
hle::SyscallOrigin ori{};
|
||||
// 08: Syscall Generated unconditionally by syscall instruction
|
||||
if (mips->cop0.cause.exCode == 0x8)
|
||||
ori = hle::SysEmotionEngine;
|
||||
else if (iop->cop.cause.code == 0x8)
|
||||
ori = hle::SysIop;
|
||||
|
||||
if (ori == hle::SysEmotionEngine) {
|
||||
i16 eeSystem{*mips->gprAt<i16*>(eeiv::$v1)};
|
||||
dealer.doSyscall(ori, eeSystem);
|
||||
mips->cop0.cause.exCode = 0;
|
||||
} else {
|
||||
iop->handleException(0x80000080, 0x8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <mio/main_memory.h>
|
||||
#include <gpu/hw_render.h>
|
||||
#include <hle/bios_patch.h>
|
||||
#include <hle/syscall_gate.h>
|
||||
#include <gpu/exhibition_engine.h>
|
||||
|
||||
#include <console/emu_thread.h>
|
||||
@ -18,6 +19,7 @@ namespace zenith::console {
|
||||
|
||||
void resetVM();
|
||||
void startVM();
|
||||
void dealWithSyscalls();
|
||||
|
||||
std::shared_ptr<hle::BiosPatcher> biosHLE;
|
||||
|
||||
@ -33,5 +35,7 @@ namespace zenith::console {
|
||||
private:
|
||||
EmuThread emuThread;
|
||||
std::shared_ptr<INTCInfra> intc;
|
||||
|
||||
hle::SyscallDealer dealer;
|
||||
};
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ namespace zenith::fuji {
|
||||
Cop0Mtc = 0x4,
|
||||
Cop0Bc0 = 0x8,
|
||||
Addi = 0x8,
|
||||
Slti = 0xa,
|
||||
EeSlti = 0xa,
|
||||
EeSpecialSyscall = 0xc,
|
||||
SpecialBreak = 0xd,
|
||||
RegImmBltzal = 0x10,
|
||||
CopOpcodes = 0x10,
|
||||
@ -44,7 +45,7 @@ namespace zenith::fuji {
|
||||
Nop = 0x33,
|
||||
Ld = 0x37,
|
||||
|
||||
SpecialXor = 0x26,
|
||||
EeSpecialXor = 0x26,
|
||||
SpecialSlt = 0x2a,
|
||||
Sw = 0x2b,
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <fuji/iop_interpreter.h>
|
||||
#include <iop/iop_core.h>
|
||||
#include <console/backdoor.h>
|
||||
#include <console/emu_vm.h>
|
||||
|
||||
#define SwOpcode(op)\
|
||||
op(Operands(opcode, opeRegs));\
|
||||
@ -39,7 +40,7 @@ namespace zenith::fuji {
|
||||
u32* gprSrc = &ioMips.IOGPRs[ops.thi];
|
||||
u32* gprDest = &ioMips.IOGPRs[ops.sec];
|
||||
u8 opp{ops.operation.pa8[3]};
|
||||
if (opp == Slti) {
|
||||
if (opp == IopSlti) {
|
||||
i32 imm{ops.operation.sins & 0xffff};
|
||||
*gprDest = *gprSrc < imm;
|
||||
} else if (opp == Sltiu) {
|
||||
@ -57,6 +58,13 @@ namespace zenith::fuji {
|
||||
orSMips(ops);
|
||||
ioMips.IOGPRs[ops.fir] = ~ioMips.IOGPRs[ops.fir];
|
||||
}
|
||||
IvFujiIopAsm(syscall) {
|
||||
ioMips.cop.cause.code = 0x8;
|
||||
raw_reference<console::EmuVM> vm{redBox->openVm()};
|
||||
vm->dealWithSyscalls();
|
||||
redBox->leaveVm(vm);
|
||||
}
|
||||
|
||||
u32 IOPInterpreter::execCopRow(u32 opcode, std::array<u8, 3> opeRegs) {
|
||||
u16 cop{static_cast<u16>((opcode >> 21) & 0x1f)};
|
||||
cop |= static_cast<u16>((opcode >> 26) & 0x3) << 8;
|
||||
@ -70,10 +78,11 @@ namespace zenith::fuji {
|
||||
u32 IOPInterpreter::execIO3S(u32 opcode, std::array<u8, 3> opeRegs) {
|
||||
u8 specialOp{static_cast<u8>(opcode & 0x3f)};
|
||||
switch (specialOp) {
|
||||
case SpecialMfhi: SwOpcode(mfhi);
|
||||
case SpecialMthi: SwOpcode(mthi);
|
||||
case SpecialOr: SwOpcode(orSMips);
|
||||
case SpecialXor: SwOpcode(xorSMips);
|
||||
case IopSpecialSyscall: SwOpcode(syscall);
|
||||
case SpecialMfhi: SwOpcode(mfhi);
|
||||
case SpecialMthi: SwOpcode(mthi);
|
||||
case SpecialOr: SwOpcode(orSMips);
|
||||
case IopSpecialXor: SwOpcode(xorSMips);
|
||||
}
|
||||
return opcode;
|
||||
}
|
||||
@ -85,7 +94,7 @@ namespace zenith::fuji {
|
||||
case 0x10 ... 0x13:
|
||||
execCopRow(opcode, opeRegs);
|
||||
break;
|
||||
case Slti:
|
||||
case IopSlti:
|
||||
case Sltiu:
|
||||
SwOpcode(sltBy);
|
||||
default:
|
||||
|
@ -9,13 +9,14 @@ namespace zenith::fuji {
|
||||
SpecialOp = 0x0,
|
||||
CopMfc = 0x0,
|
||||
CopMtc = 0x4,
|
||||
Slti = 0x0a,
|
||||
IopSlti = 0x0a,
|
||||
Sltiu = 0x0b,
|
||||
IopSpecialSyscall = 0xc,
|
||||
SpecialMfhi = 0x10,
|
||||
CopRfe = 0x10,
|
||||
SpecialMthi = 0x11,
|
||||
SpecialOr = 0x25,
|
||||
SpecialXor = 0x26,
|
||||
IopSpecialXor = 0x26,
|
||||
SpecialNor = 0x27
|
||||
};
|
||||
|
||||
@ -32,6 +33,7 @@ namespace zenith::fuji {
|
||||
u32 fetchPcInst() override;
|
||||
|
||||
IvFujiOp(sltBy);
|
||||
IvFujiOp(syscall);
|
||||
|
||||
IvFujiOp(mfhi);
|
||||
IvFujiOp(mthi);
|
||||
|
@ -16,7 +16,6 @@ namespace zenith::fuji {
|
||||
Eret = 0x10,
|
||||
Cop0 = 0x12
|
||||
};
|
||||
|
||||
friend EffectivePipeline operator^(EffectivePipeline dest, EffectivePipeline src) {
|
||||
return static_cast<EffectivePipeline>(static_cast<u16>(dest) ^ static_cast<u16>(src));
|
||||
}
|
||||
@ -77,6 +76,7 @@ namespace zenith::fuji {
|
||||
IvFujiOp(bltzal);
|
||||
IvFujiOp(bgez); IvFujiOp(bgezl); IvFujiOp(bgezall);
|
||||
IvFujiOp(mtsab); IvFujiOp(mtsah);
|
||||
IvFujiOp(syscall);
|
||||
|
||||
// Memory read functions through direct translation
|
||||
IvFujiOp(lb); IvFujiOp(lbu);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <fuji/mipsiv_interpreter.h>
|
||||
#include <eeiv/ee_engine.h>
|
||||
#include <eeiv/ee_assembler.h>
|
||||
#include <console/backdoor.h>
|
||||
#include <console/emu_vm.h>
|
||||
namespace zenith::fuji {
|
||||
IvFujiSuperAsm(addi) {
|
||||
mainMips.GPRs[ops.sec].words[0] = ops.operation.pa16[0] +
|
||||
@ -107,4 +109,11 @@ namespace zenith::fuji {
|
||||
IvFujiSuperAsm(iBreak) {
|
||||
mainMips.handleException(1, 0x80000180, 0x9);
|
||||
}
|
||||
IvFujiSuperAsm(syscall) {
|
||||
mainMips.cop0.cause.exCode = 0x8;
|
||||
// We need to directly handle these syscall, instead of mainMips.chPC(0x80000180);
|
||||
auto vm{redBox->openVm()};
|
||||
vm->dealWithSyscalls();
|
||||
redBox->leaveVm(vm);
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,10 @@
|
||||
namespace zenith::fuji {
|
||||
u32 MipsIVInterpreter::decMipsIvS(u32 opcode, InvokeOpInfo& decode) {
|
||||
switch (opcode & 0x3f) {
|
||||
case SpecialBreak: SWCached(iBreak);
|
||||
case SpecialXor: SWCached(ivXor);
|
||||
case SpecialSlt: SWCached(slt);
|
||||
case EeSpecialSyscall: SWCached(syscall);
|
||||
case SpecialBreak: SWCached(iBreak);
|
||||
case EeSpecialXor: SWCached(ivXor);
|
||||
case SpecialSlt: SWCached(slt);
|
||||
}
|
||||
return opcode & 0x3f;
|
||||
}
|
||||
@ -66,8 +67,8 @@ namespace zenith::fuji {
|
||||
case RegImmOpcodes:
|
||||
decMipsIvRegImm(opcode, decode);
|
||||
break;
|
||||
case Addi: SWCached(addi);
|
||||
case Slti: SWCached(slti);
|
||||
case Addi: SWCached(addi);
|
||||
case EeSlti: SWCached(slti);
|
||||
case CopOpcodes:
|
||||
decMipsIvCop0(opcode, decode);
|
||||
break;
|
||||
|
20
app/src/main/cpp/zenith/hle/syscall_gate.cpp
Normal file
20
app/src/main/cpp/zenith/hle/syscall_gate.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include <hle/syscall_gate.h>
|
||||
#include <console/emu_vm.h>
|
||||
|
||||
namespace zenith::hle {
|
||||
void SyscallDealer::hleResetEE(raw_reference<console::EmuVM> vm) {
|
||||
i32 resetParam{*vm->mips->gprAt<i32*>(Param0)};
|
||||
if (resetParam == 0) {}
|
||||
else if (resetParam == 1) {}
|
||||
}
|
||||
void SyscallDealer::doSyscall(SyscallOrigin origin, i16 sys) {
|
||||
auto vm{redBox->openVm()};
|
||||
if (origin == SysEmotionEngine) {
|
||||
switch (sys) {
|
||||
case 0x01: // void ResetEE(i32 resetFlag);
|
||||
hleResetEE(vm); break;
|
||||
}
|
||||
}
|
||||
redBox->leaveVm(vm);
|
||||
}
|
||||
}
|
27
app/src/main/cpp/zenith/hle/syscall_gate.h
Normal file
27
app/src/main/cpp/zenith/hle/syscall_gate.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/types.h>
|
||||
#include <console/backdoor.h>
|
||||
#include <eeiv/ee_info.h>
|
||||
namespace zenith::hle {
|
||||
enum CallParams {
|
||||
Return = eeiv::$v0,
|
||||
Param0 = eeiv::$a0,
|
||||
Param1 = eeiv::$a1,
|
||||
Param2 = eeiv::$a2,
|
||||
Param3 = eeiv::$a3,
|
||||
Param4 = eeiv::$t0,
|
||||
Param5 = eeiv::$t1
|
||||
};
|
||||
|
||||
enum SyscallOrigin {
|
||||
SysEmotionEngine,
|
||||
SysIop
|
||||
};
|
||||
class SyscallDealer {
|
||||
public:
|
||||
void doSyscall(SyscallOrigin origin, i16 sys);
|
||||
private:
|
||||
void hleResetEE(raw_reference<console::EmuVM> vm);
|
||||
};
|
||||
}
|
@ -47,4 +47,19 @@ namespace zenith::iop {
|
||||
ioPc += 4;
|
||||
return ioOpcode;
|
||||
}
|
||||
void IOMipsCore::handleException(u32 vec, u8 code) {
|
||||
cop.cause.code = code;
|
||||
if (onBranch)
|
||||
cop.ePC = ioPc - 4;
|
||||
else
|
||||
cop.ePC = ioPc;
|
||||
cop.cause.bd = onBranch;
|
||||
cop.status.ieo = cop.status.iep;
|
||||
cop.status.iep = cop.status.iec;
|
||||
cop.status.iec = false;
|
||||
|
||||
// We do this to offset PC being incremented
|
||||
ioPc = vec - 4;
|
||||
onBranch = false;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ namespace zenith::iop {
|
||||
u32 fetchByPC();
|
||||
|
||||
void intByINTC(bool isInt);
|
||||
void handleException(u32 vec, u8 code);
|
||||
|
||||
std::array<u32, 32> IOGPRs;
|
||||
std::array<IOPCache, 128> iCache;
|
||||
std::shared_ptr<mio::GlobalMemory> iopMem;
|
||||
@ -42,6 +44,8 @@ namespace zenith::iop {
|
||||
ioPc,
|
||||
cyclesToIO;
|
||||
IopCop cop;
|
||||
bool onBranch{false};
|
||||
|
||||
private:
|
||||
u8* iopPrivateAddrSolver(u32 address);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id("com.android.application") version "8.1.3" apply false
|
||||
id("com.android.library") version "8.1.3" apply false
|
||||
id("com.android.application") version "8.1.4" apply false
|
||||
id("com.android.library") version "8.1.4" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.8.20" apply false
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user