Refactor NCE

This commit mainly just refactors NCE by adding spacing and fixing other minor errors. In addition, it adds comments to `nce/guest.h` and `nce/instructions.h`.
This commit is contained in:
◱ PixelyIon 2020-03-25 01:50:28 +05:30 committed by ◱ PixelyIon
parent 42d982c6fb
commit bbdd41a86c
6 changed files with 310 additions and 133 deletions

View File

@ -947,7 +947,10 @@
<inspection_tool class="GroovyAccessToStaticFieldLockedOnInstance" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyAccessibility" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyAssignabilityCheck" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyAssignmentCanBeOperatorAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyAssignmentCanBeOperatorAssignment" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ignoreLazyOperators" value="true" />
<option name="ignoreObscureOperators" value="false" />
</inspection_tool>
<inspection_tool class="GroovyAssignmentToForLoopParameter" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyAssignmentToMethodParameter" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyBreak" enabled="false" level="WARNING" enabled_by_default="false" />
@ -958,13 +961,19 @@
<inspection_tool class="GroovyConditionalWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyConstantConditional" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyConstantIfStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyConstantNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyConstantNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_regex" value="[A-Z\d]*" />
<option name="m_minLength" value="4" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="GroovyConstructorNamedArguments" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyContinue" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyContinueOrBreakFromFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyDivideByZero" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyDocCheck" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="GroovyDoubleCheckedLocking" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyDoubleCheckedLocking" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ignoreOnVolatileVariables" value="false" />
</inspection_tool>
<inspection_tool class="GroovyDoubleNegation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyDuplicateSwitchBranch" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyEmptyCatchBlock" enabled="false" level="WARNING" enabled_by_default="false" />
@ -975,12 +984,22 @@
<inspection_tool class="GroovyFallthrough" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyGStringKey" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyIfStatementWithIdenticalBranches" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyIfStatementWithTooManyBranches" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyIfStatementWithTooManyBranches" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="3" />
</inspection_tool>
<inspection_tool class="GroovyInArgumentCheck" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyInfiniteLoopStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyInfiniteRecursion" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyInstanceMethodNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyInstanceVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyInstanceMethodNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_regex" value="[a-z][A-Za-z\d]*" />
<option name="m_minLength" value="4" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="GroovyInstanceVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_regex" value="m_[a-z][A-Za-z\d]*" />
<option name="m_minLength" value="1" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="GroovyLabeledStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyListGetCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyListSetCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
@ -992,10 +1011,14 @@
<inspection_tool class="GroovyLoopStatementThatDoesntLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyMapGetCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyMapPutCanBeKeyedAccess" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyMethodParameterCount" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyMethodParameterCount" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="5" />
</inspection_tool>
<inspection_tool class="GroovyMethodWithMoreThanThreeNegations" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyMissingReturnStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyMultipleReturnPointsPerMethod" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyMultipleReturnPointsPerMethod" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="1" />
</inspection_tool>
<inspection_tool class="GroovyNegatedConditional" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyNegatedIf" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyNestedAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
@ -1005,12 +1028,26 @@
<inspection_tool class="GroovyNonShortCircuitBoolean" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyNotifyWhileNotSynchronized" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyOctalInteger" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyOverlyComplexArithmeticExpression" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyOverlyComplexBooleanExpression" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyOverlyComplexMethod" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyOverlyLongMethod" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyOverlyNestedMethod" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyParameterNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyOverlyComplexArithmeticExpression" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="3" />
</inspection_tool>
<inspection_tool class="GroovyOverlyComplexBooleanExpression" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="3" />
</inspection_tool>
<inspection_tool class="GroovyOverlyComplexMethod" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="10" />
</inspection_tool>
<inspection_tool class="GroovyOverlyLongMethod" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="30" />
</inspection_tool>
<inspection_tool class="GroovyOverlyNestedMethod" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_limit" value="5" />
</inspection_tool>
<inspection_tool class="GroovyParameterNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_regex" value="[a-z][A-Za-z\d]*" />
<option name="m_minLength" value="4" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="GroovyPointlessArithmetic" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyPointlessBoolean" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyPublicFieldAccessedInSynchronizedContext" enabled="false" level="WARNING" enabled_by_default="false" />
@ -1021,8 +1058,16 @@
<inspection_tool class="GroovyReturnFromClosureCanBeImplicit" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyReturnFromFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovySillyAssignment" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyStaticMethodNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyStaticVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyStaticMethodNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_regex" value="[a-z][A-Za-z\d]*" />
<option name="m_minLength" value="4" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="GroovyStaticVariableNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_regex" value="s_[a-z][A-Za-z\d]*" />
<option name="m_minLength" value="4" />
<option name="m_maxLength" value="32" />
</inspection_tool>
<inspection_tool class="GroovySwitchStatementWithNoDefault" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovySynchronizationOnNonFinalField" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovySynchronizationOnThis" enabled="false" level="WARNING" enabled_by_default="false" />
@ -1048,10 +1093,25 @@
<inspection_tool class="GroovyVariableNotAssigned" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="GroovyWaitCallNotInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyWaitWhileNotSynchronized" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyWhileLoopSpinsOnField" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GroovyWhileLoopSpinsOnField" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ignoreNonEmtpyLoops" value="false" />
</inspection_tool>
<inspection_tool class="Guava" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="HardCodedStringLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HardcodedFileSeparators" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="HardCodedStringLiteral" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ignoreForAssertStatements" value="true" />
<option name="ignoreForExceptionConstructors" value="true" />
<option name="ignoreForSpecifiedExceptionConstructors" value="" />
<option name="ignoreForJUnitAsserts" value="true" />
<option name="ignoreForClassReferences" value="true" />
<option name="ignoreForPropertyKeyReferences" value="true" />
<option name="ignoreForNonAlpha" value="true" />
<option name="ignoreAssignedToConstants" value="false" />
<option name="ignoreToString" value="false" />
<option name="nonNlsCommentPattern" value="NON-NLS" />
</inspection_tool>
<inspection_tool class="HardcodedFileSeparators" enabled="false" level="WARNING" enabled_by_default="false">
<option name="m_recognizeExampleMediaType" value="false" />
</inspection_tool>
<inspection_tool class="HardcodedLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="HasPlatformType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="HashCodeUsesNonFinalVariable" enabled="true" level="WARNING" enabled_by_default="true" />
@ -1146,7 +1206,7 @@
<inspection_tool class="IncrementDecrementUsedAsExpression" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="IndexOfReplaceableByContains" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InfiniteLoopStatement" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InfiniteRecursion" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InfiniteRecursion" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="InitializationIssue" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="InitializerIssues" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="InjectedReferences" enabled="true" level="ERROR" enabled_by_default="true" />
@ -1584,7 +1644,7 @@
<inspection_tool class="NumericToString" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OCDFA" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OCGlobalUnused" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OCInconsistentNaming" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="OCInconsistentNaming" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="OCLegacyObjCLiteral" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OCLoopDoesntUseConditionVariable" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="OCNotLocalizedString" enabled="true" level="WARNING" enabled_by_default="true" />
@ -1783,7 +1843,16 @@
<inspection_tool class="PyClassHasNoInitInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PyClassicStyleClassInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyComparisonWithNoneInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PyCompatibilityInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PyCompatibilityInspection" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ourVersions">
<value>
<list size="2">
<item index="0" class="java.lang.String" itemvalue="2.7" />
<item index="1" class="java.lang.String" itemvalue="3.8" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyDataclassInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyDecoratorInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyDefaultArgumentInspection" enabled="true" level="WARNING" enabled_by_default="true" />
@ -1874,7 +1943,7 @@
<inspection_tool class="RecursivePropertyAccessor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="RedundantArrayCreation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="RedundantAsync" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="RedundantCast" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="RedundantCast" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="RedundantClassCall" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="RedundantCollectionOperation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="RedundantCompanionReference" enabled="true" level="WARNING" enabled_by_default="true" />
@ -2081,8 +2150,8 @@
<inspection_tool class="SortModifiers" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="SortedCollectionWithNonComparableKeys" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SpellCheckingInspection" enabled="true" level="TYPO" enabled_by_default="true">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processCode" value="false" />
<option name="processLiterals" value="false" />
<option name="processComments" value="true" />
</inspection_tool>
<inspection_tool class="StandardVariableNames" enabled="true" level="WARNING" enabled_by_default="true" />
@ -2112,7 +2181,15 @@
<inspection_tool class="StringBufferReplaceableByString" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="StringBufferReplaceableByStringBuilder" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="StringBufferToStringInConcatenation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="StringConcatenation" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="StringConcatenation" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ignoreAsserts" value="false" />
<option name="ignoreSystemOuts" value="false" />
<option name="ignoreSystemErrs" value="false" />
<option name="ignoreThrowableArguments" value="false" />
<option name="ignoreConstantInitializers" value="false" />
<option name="ignoreInTestCode" value="false" />
<option name="ignoreInToString" value="false" />
</inspection_tool>
<inspection_tool class="StringConcatenationArgumentToLogCall" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="StringConcatenationInFormatCall" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="StringConcatenationInLoops" enabled="true" level="WARNING" enabled_by_default="true" />
@ -2465,5 +2542,17 @@
</value>
</option>
</inspection_tool>
<inspection_tool class="unused" enabled="false" level="WARNING" enabled_by_default="false">
<option name="LOCAL_VARIABLE" value="true" />
<option name="FIELD" value="true" />
<option name="METHOD" value="true" />
<option name="CLASS" value="true" />
<option name="PARAMETER" value="true" />
<option name="REPORT_PARAMETER_FOR_PUBLIC_METHODS" value="true" />
<option name="ADD_MAINS_TO_ENTRIES" value="true" />
<option name="ADD_APPLET_TO_ENTRIES" value="true" />
<option name="ADD_SERVLET_TO_ENTRIES" value="true" />
<option name="ADD_NONJAVA_TO_ENTRIES" value="true" />
</inspection_tool>
</profile>
</component>

View File

@ -7,7 +7,7 @@
bool Halt;
jobject Surface;
uint FaultCount;
skyline::GroupMutex jniMtx;
skyline::GroupMutex JniMtx;
void signalHandler(int signal) {
syslog(LOG_ERR, "Halting program due to signal: %s", strsignal(signal));
@ -56,18 +56,18 @@ extern "C" JNIEXPORT void Java_emu_skyline_GameActivity_executeRom(JNIEnv *env,
}
extern "C" JNIEXPORT void Java_emu_skyline_GameActivity_setHalt(JNIEnv *env, jobject instance, jboolean halt) {
jniMtx.lock(skyline::GroupMutex::Group::Group2);
JniMtx.lock(skyline::GroupMutex::Group::Group2);
Halt = halt;
jniMtx.unlock();
JniMtx.unlock();
}
extern "C" JNIEXPORT void Java_emu_skyline_GameActivity_setSurface(JNIEnv *env, jobject instance, jobject surface) {
jniMtx.lock(skyline::GroupMutex::Group::Group2);
JniMtx.lock(skyline::GroupMutex::Group::Group2);
if (!env->IsSameObject(Surface, nullptr))
env->DeleteGlobalRef(Surface);
if (!env->IsSameObject(surface, nullptr))
Surface = env->NewGlobalRef(surface);
else
Surface = surface;
jniMtx.unlock();
JniMtx.unlock();
}

View File

@ -3,32 +3,38 @@
#include "os.h"
#include "jvm.h"
#include "nce/guest.h"
#include "nce/instr.h"
#include "nce/instructions.h"
#include "kernel/svc.h"
#include "nce.h"
extern bool Halt;
extern jobject Surface;
extern skyline::GroupMutex jniMtx;
extern skyline::GroupMutex JniMtx;
namespace skyline {
void NCE::KernelThread(pid_t thread) {
try {
state.thread = state.process->threads.at(thread);
state.ctx = reinterpret_cast<ThreadContext *>(state.thread->ctxMemory->kernel.address);
while (true) {
asm("yield");
if (__predict_false(Halt))
break;
if (__predict_false(!Surface))
continue;
if (state.ctx->state == ThreadState::WaitKernel) {
std::lock_guard jniGd(jniMtx);
std::lock_guard jniGd(JniMtx);
if (__predict_false(Halt))
break;
if (__predict_false(!Surface))
continue;
const u16 svc = static_cast<const u16>(state.ctx->commandId);
try {
if (kernel::svc::SvcTable[svc]) {
state.logger->Debug("SVC called 0x{:X}", svc);
@ -39,10 +45,12 @@ namespace skyline {
} catch (const std::exception &e) {
throw exception("{} (SVC: 0x{:X})", e.what(), svc);
}
state.ctx->state = ThreadState::WaitRun;
} else if (__predict_false(state.ctx->state == ThreadState::GuestCrash)) {
state.logger->Warn("Thread with PID {} has crashed due to signal: {}", thread, strsignal(state.ctx->commandId));
ThreadTrace();
state.ctx->state = ThreadState::WaitRun;
break;
}
@ -52,12 +60,15 @@ namespace skyline {
} catch (...) {
state.logger->Error("An unknown exception has occurred");
}
if (!Halt) {
if (thread == state.process->pid) {
jniMtx.lock(GroupMutex::Group::Group2);
JniMtx.lock(GroupMutex::Group::Group2);
state.os->KillThread(thread);
Halt = true;
jniMtx.unlock();
JniMtx.unlock();
} else {
state.os->KillThread(thread);
}
@ -74,9 +85,11 @@ namespace skyline {
void NCE::Execute() {
try {
while (true) {
std::lock_guard guard(jniMtx);
std::lock_guard guard(JniMtx);
if (Halt)
break;
state.gpu->Loop();
}
} catch (const std::exception &e) {
@ -84,10 +97,11 @@ namespace skyline {
} catch (...) {
state.logger->Error("An unknown exception has occurred");
}
if (!Halt) {
jniMtx.lock(GroupMutex::Group::Group2);
JniMtx.lock(GroupMutex::Group::Group2);
Halt = true;
jniMtx.unlock();
JniMtx.unlock();
}
}
@ -100,10 +114,14 @@ namespace skyline {
void ExecuteFunctionCtx(ThreadCall call, Registers &funcRegs, ThreadContext *ctx) __attribute__ ((optnone)) {
ctx->commandId = static_cast<u32>(call);
Registers registers = ctx->registers;
while (ctx->state != ThreadState::WaitInit && ctx->state != ThreadState::WaitKernel);
ctx->registers = funcRegs;
ctx->state = ThreadState::WaitFunc;
while (ctx->state != ThreadState::WaitInit && ctx->state != ThreadState::WaitKernel);
funcRegs = ctx->registers;
ctx->registers = registers;
}
@ -115,6 +133,7 @@ namespace skyline {
void NCE::ExecuteFunction(ThreadCall call, Registers &funcRegs) {
if (state.process->status == kernel::type::KProcess::Status::Exiting)
throw exception("Executing function on Exiting process");
auto thread = state.thread ? state.thread : state.process->threads.at(state.process->pid);
ExecuteFunctionCtx(call, funcRegs, reinterpret_cast<ThreadContext *>(thread->ctxMemory->kernel.address));
}
@ -127,10 +146,12 @@ namespace skyline {
void NCE::StartThread(u64 entryArg, u32 handle, std::shared_ptr<kernel::type::KThread> &thread) {
auto ctx = reinterpret_cast<ThreadContext *>(thread->ctxMemory->kernel.address);
while (ctx->state != ThreadState::WaitInit);
ctx->tpidrroEl0 = thread->tls;
ctx->registers.x0 = entryArg;
ctx->registers.x1 = handle;
ctx->state = ThreadState::WaitRun;
state.logger->Debug("Starting kernel thread for guest thread: {}", thread->pid);
threadMap[thread->pid] = std::make_shared<std::thread>(&NCE::KernelThread, this, thread->pid);
}
@ -139,30 +160,40 @@ namespace skyline {
std::string raw;
std::string trace;
std::string regStr;
ctx = ctx ? ctx : state.ctx;
if (numHist) {
std::vector<u32> instrs(numHist);
u64 size = sizeof(u32) * numHist;
u64 offset = ctx->pc - size + (2 * sizeof(u32));
state.process->ReadMemory(instrs.data(), offset, size);
for (auto &instr : instrs) {
instr = __builtin_bswap32(instr);
if (offset == ctx->pc)
trace += fmt::format("\n-> 0x{:X} : 0x{:08X}", offset, instr);
else
trace += fmt::format("\n 0x{:X} : 0x{:08X}", offset, instr);
raw += fmt::format("{:08X}", instr);
offset += sizeof(u32);
}
}
if (ctx->faultAddress)
regStr += fmt::format("\nFault Address: 0x{:X}", ctx->faultAddress);
if (ctx->sp)
regStr += fmt::format("\nStack Pointer: 0x{:X}", ctx->sp);
for (u16 index = 0; index < constant::NumRegs - 1; index += 2) {
auto xStr = index < 10 ? " X" : "X";
regStr += fmt::format("\n{}{}: 0x{:<16X} {}{}: 0x{:X}", xStr, index, ctx->registers.regs[index], xStr, index + 1, ctx->registers.regs[index + 1]);
}
if (numHist) {
state.logger->Debug("Process Trace:{}", trace);
state.logger->Debug("Raw Instructions: 0x{}", raw);
@ -197,7 +228,7 @@ namespace skyline {
auto instrMrs = reinterpret_cast<instr::Mrs *>(address);
if (instrSvc->Verify()) {
instr::B bjunc(offset);
instr::B bJunc(offset);
constexpr u32 strLr = 0xF81F0FFE; // STR LR, [SP, #-16]!
offset += sizeof(strLr);
instr::BL bSvCtx(patchOffset - offset);
@ -217,7 +248,7 @@ namespace skyline {
instr::B bret(-offset + sizeof(u32));
offset += sizeof(bret);
*address = bjunc.raw;
*address = bJunc.raw;
patch.push_back(strLr);
patch.push_back(bSvCtx.raw);
for (auto &instr : movPc)
@ -229,7 +260,7 @@ namespace skyline {
patch.push_back(bret.raw);
} else if (instrMrs->Verify()) {
if (instrMrs->srcReg == constant::TpidrroEl0) {
instr::B bjunc(offset);
instr::B bJunc(offset);
u32 strX0{};
if (instrMrs->destReg != regs::X0) {
strX0 = 0xF81F0FE0; // STR X0, [SP, #-16]!
@ -250,7 +281,7 @@ namespace skyline {
instr::B bret(-offset + sizeof(u32));
offset += sizeof(bret);
*address = bjunc.raw;
*address = bJunc.raw;
if (strX0)
patch.push_back(strX0);
patch.push_back(mrsX0);
@ -262,7 +293,7 @@ namespace skyline {
patch.push_back(bret.raw);
} else if (frequency != constant::TegraX1Freq) {
if (instrMrs->srcReg == constant::CntpctEl0) {
instr::B bjunc(offset);
instr::B bJunc(offset);
offset += guest::rescaleClockSize;
instr::Ldr ldr(0xF94003E0); // LDR XOUT, [SP]
ldr.destReg = instrMrs->destReg;
@ -272,7 +303,7 @@ namespace skyline {
instr::B bret(-offset + sizeof(u32));
offset += sizeof(bret);
*address = bjunc.raw;
*address = bJunc.raw;
auto size = patch.size();
patch.resize(size + (guest::rescaleClockSize / sizeof(u32)));
std::memcpy(patch.data() + size, reinterpret_cast<void *>(&guest::RescaleClock), guest::rescaleClockSize);
@ -280,13 +311,13 @@ namespace skyline {
patch.push_back(addSp);
patch.push_back(bret.raw);
} else if (instrMrs->srcReg == constant::CntfrqEl0) {
instr::B bjunc(offset);
instr::B bJunc(offset);
auto movFreq = instr::MoveU32Reg(static_cast<regs::X>(instrMrs->destReg), constant::TegraX1Freq);
offset += sizeof(u32) * movFreq.size();
instr::B bret(-offset + sizeof(u32));
offset += sizeof(bret);
*address = bjunc.raw;
*address = bJunc.raw;
for (auto &instr : movFreq)
patch.push_back(instr);
patch.push_back(bret.raw);
@ -298,6 +329,7 @@ namespace skyline {
}
}
}
offset -= sizeof(u32);
patchOffset -= sizeof(u32);
}

View File

@ -1,7 +1,7 @@
#include <asm/siginfo.h>
#include <csignal>
#include <cstdlib>
#include <initializer_list> // This is used implicitly
#include <asm/siginfo.h>
#include "guest_common.h"
#define FORCE_INLINE __attribute__((always_inline)) inline // NOLINT(cppcoreguidelines-macro-usage)
@ -98,8 +98,10 @@ namespace skyline::guest {
void SvcHandler(u64 pc, u32 svc) {
volatile ThreadContext *ctx;
asm("MRS %0, TPIDR_EL0":"=r"(ctx));
ctx->pc = pc;
ctx->commandId = svc;
if (svc == 0xB) { // svcSleepThread
switch (ctx->registers.x0) {
case 0:
@ -119,6 +121,7 @@ namespace skyline::guest {
"LDR LR, [SP], #16":: : "x0", "x1", "x2", "x3", "x4", "x5", "x8");
break;
}
default: {
struct timespec spec = {
.tv_sec = static_cast<time_t>(ctx->registers.x0 / 1000000000),
@ -160,20 +163,25 @@ namespace skyline::guest {
"LDP X1, X2, [SP], #16"::"r"(ctx->registers.x0));
return;
}
while (true) {
ctx->state = ThreadState::WaitKernel;
while (ctx->state == ThreadState::WaitKernel);
if (ctx->state == ThreadState::WaitRun) {
break;
} else if (ctx->state == ThreadState::WaitFunc) {
if (ctx->commandId == static_cast<u32>(ThreadCall::Syscall)) {
SaveCtxStack();
LoadCtxTls();
asm("STR LR, [SP, #-16]!\n\t"
"MOV LR, SP\n\t"
"SVC #0\n\t"
"MOV SP, LR\n\t"
"LDR LR, [SP], #16");
SaveCtxTls();
LoadCtxStack();
} else if (ctx->commandId == static_cast<u32>(ThreadCall::Memcopy)) {
@ -181,11 +189,13 @@ namespace skyline::guest {
auto dest = reinterpret_cast<u8 *>(ctx->registers.x1);
auto size = ctx->registers.x2;
auto end = src + size;
while (src < end)
*(src++) = *(dest++);
} else if (ctx->commandId == static_cast<u32>(ThreadCall::Clone)) {
SaveCtxStack();
LoadCtxTls();
asm("STR LR, [SP, #-16]!\n\t"
"MOV LR, SP\n\t"
"SVC #0\n\t"
@ -225,25 +235,31 @@ namespace skyline::guest {
".parent:\n\t"
"MOV SP, LR\n\t"
"LDR LR, [SP], #16");
SaveCtxTls();
LoadCtxStack();
}
}
}
ctx->state = ThreadState::Running;
}
void SignalHandler(int signal, siginfo_t *info, ucontext_t *ucontext) {
volatile ThreadContext *ctx;
asm("MRS %0, TPIDR_EL0":"=r"(ctx));
for (u8 index = 0; index < 30; index++)
ctx->registers.regs[index] = ucontext->uc_mcontext.regs[index];
ctx->pc = ucontext->uc_mcontext.pc;
ctx->commandId = static_cast<u32>(signal);
ctx->faultAddress = ucontext->uc_mcontext.fault_address;
ctx->sp = ucontext->uc_mcontext.sp;
while (true) {
ctx->state = ThreadState::GuestCrash;
if (ctx->state == ThreadState::WaitRun)
exit(0);
}
@ -252,20 +268,24 @@ namespace skyline::guest {
void GuestEntry(u64 address) {
volatile ThreadContext *ctx;
asm("MRS %0, TPIDR_EL0":"=r"(ctx));
while (true) {
ctx->state = ThreadState::WaitInit;
while (ctx->state == ThreadState::WaitInit);
if (ctx->state == ThreadState::WaitRun) {
break;
} else if (ctx->state == ThreadState::WaitFunc) {
if (ctx->commandId == static_cast<u32>(ThreadCall::Syscall)) {
SaveCtxStack();
LoadCtxTls();
asm("STR LR, [SP, #-16]!\n\t"
"MOV LR, SP\n\t"
"SVC #0\n\t"
"MOV SP, LR\n\t"
"LDR LR, [SP], #16");
SaveCtxTls();
LoadCtxStack();
}
@ -274,17 +294,22 @@ namespace skyline::guest {
auto dest = reinterpret_cast<u8 *>(ctx->registers.x1);
auto size = ctx->registers.x2;
auto end = src + size;
while (src < end)
*(src++) = *(dest++);
}
}
struct sigaction sigact{
.sa_sigaction = reinterpret_cast<void (*)(int, struct siginfo *, void *)>(reinterpret_cast<void *>(SignalHandler)),
.sa_flags = SA_SIGINFO,
};
for (int signal : {SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV})
sigaction(signal, &sigact, nullptr);
ctx->state = ThreadState::Running;
asm("MOV LR, %0\n\t"
"MOV X0, %1\n\t"
"MOV X1, %2\n\t"
@ -317,6 +342,7 @@ namespace skyline::guest {
"MOV X28, XZR\n\t"
"MOV X29, XZR\n\t"
"RET"::"r"(address), "r"(ctx->registers.x0), "r"(ctx->registers.x1) : "x0", "x1", "lr");
__builtin_unreachable();
}
}

View File

@ -2,21 +2,41 @@
namespace skyline {
namespace guest {
constexpr size_t saveCtxSize = 20 * sizeof(u32);
constexpr size_t loadCtxSize = 20 * sizeof(u32);
constexpr size_t rescaleClockSize = 16 * sizeof(u32);
constexpr size_t saveCtxSize = 20 * sizeof(u32); //!< The size of the SaveCtx function in 32-bit ARMv8 instructions
constexpr size_t loadCtxSize = 20 * sizeof(u32); //!< The size of the LoadCtx function in 32-bit ARMv8 instructions
constexpr size_t rescaleClockSize = 16 * sizeof(u32); //!< The size of the RescaleClock function in 32-bit ARMv8 instructions
#ifdef NDEBUG
constexpr size_t svcHandlerSize = 225 * sizeof(u32);
constexpr size_t svcHandlerSize = 225 * sizeof(u32); //!< The size of the SvcHandler (Release) function in 32-bit ARMv8 instructions
#else
constexpr size_t svcHandlerSize = 400 * sizeof(u32);
constexpr size_t svcHandlerSize = 400 * sizeof(u32); //!< The size of the SvcHandler (Debug) function in 32-bit ARMv8 instructions
#endif
/**
* @brief This is the entry point for all guest threads
* @param address The address of the actual thread entry point
*/
void GuestEntry(u64 address);
/**
* @brief This saves the context from CPU registers into TLS
*/
extern "C" void SaveCtx(void);
/**
* @brief This loads the context from TLS into CPU registers
*/
extern "C" void LoadCtx(void);
/**
* @brief This rescales the clock to Tegra X1 levels and puts the output on stack
*/
extern "C" __noreturn void RescaleClock(void);
/**
* @brief This is used to handle all SVC calls
* @param pc The address of PC when the call was being done
* @param svc The SVC ID of the SVC being called
*/
void SvcHandler(u64 pc, u32 svc);
}
}

View File

@ -16,27 +16,27 @@ namespace skyline {
* @brief Creates a BRK instruction with a specific immediate value, used for generating BRK opcodes
* @param value The immediate value of the instruction
*/
explicit Brk(u16 value) {
sig0 = 0x0; // First 5 bits of a BRK instruction are 0
inline constexpr Brk(u16 value) {
sig0 = 0x0;
this->value = value;
sig1 = 0x6A1; // Last 11 bits of a BRK instruction stored as u16
sig1 = 0x6A1;
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid BRK instruction
*/
inline bool Verify() {
inline constexpr bool Verify() {
return (sig0 == 0x0 && sig1 == 0x6A1);
}
union {
struct {
u8 sig0 : 5;
u32 value : 16;
u16 sig1 : 11;
u8 sig0 : 5; //!< 5-bit signature (0x0)
u32 value : 16; //!< 16-bit immediate value
u16 sig1 : 11; //!< 11-bit signature (0x6A1)
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(Brk) == sizeof(u32));
@ -49,17 +49,17 @@ namespace skyline {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid SVC instruction
*/
inline bool Verify() {
inline constexpr bool Verify() {
return (sig0 == 0x1 && sig1 == 0x6A0);
}
union {
struct {
u8 sig0 : 5;
u32 value : 16;
u16 sig1 : 11;
u8 sig0 : 5; //!< 5-bit signature (0x0)
u32 value : 16; //!< 16-bit immediate value
u16 sig1 : 11; //!< 11-bit signature (0x6A1)
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(Svc) == sizeof(u32));
@ -73,27 +73,27 @@ namespace skyline {
* @param srcReg The source system register
* @param dstReg The destination Xn register
*/
Mrs(u32 srcReg, regs::X dstReg) {
inline constexpr Mrs(u32 srcReg, regs::X dstReg) {
this->srcReg = srcReg;
this->destReg = dstReg;
sig = 0xD53; // Last 12 bits of a MRS instruction stored as u16
sig = 0xD53;
}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MRS instruction
*/
inline bool Verify() {
inline constexpr bool Verify() {
return (sig == 0xD53);
}
union {
struct {
u8 destReg : 5;
u32 srcReg : 15;
u16 sig : 12;
u8 destReg : 5; //!< 5-bit destination register
u32 srcReg : 15; //!< 15-bit source register
u16 sig : 12; //!< 16-bit signature (0xD53)
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(Mrs) == sizeof(u32));
@ -107,7 +107,7 @@ namespace skyline {
* @brief Creates a B instruction with a specific offset
* @param offset The offset to encode in the instruction (Should be 32-bit aligned)
*/
explicit B(i64 offset) {
inline constexpr B(i64 offset) {
this->offset = static_cast<i32>(offset / 4);
sig = 0x5;
}
@ -116,7 +116,7 @@ namespace skyline {
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction
*/
inline i32 Offset() {
inline constexpr i32 Offset() {
return offset * 4;
}
@ -124,16 +124,16 @@ namespace skyline {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid Branch instruction
*/
inline bool Verify() {
inline constexpr bool Verify() {
return (sig == 0x5);
}
union {
struct {
i32 offset : 26;
u8 sig : 6;
i32 offset : 26; //!< 26-bit branch offset
u8 sig : 6; //!< 6-bit signature (0x5)
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(B) == sizeof(u32));
@ -147,7 +147,7 @@ namespace skyline {
* @brief Creates a BL instruction with a specific offset
* @param offset The offset to encode in the instruction (Should be 32-bit aligned)
*/
explicit BL(i64 offset) {
inline constexpr BL(i64 offset) {
this->offset = static_cast<i32>(offset / 4);
sig = 0x25;
}
@ -156,7 +156,7 @@ namespace skyline {
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction
*/
inline i32 Offset() {
inline constexpr i32 Offset() {
return offset * 4;
}
@ -164,16 +164,16 @@ namespace skyline {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid Branch Linked instruction
*/
inline bool Verify() {
return (sig == 0x85);
inline constexpr bool Verify() {
return (sig == 0x25);
}
union {
struct {
i32 offset : 26;
u8 sig : 6;
i32 offset : 26; //!< 26-bit branch offset
u8 sig : 6; //!< 6-bit signature (0x25)
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(BL) == sizeof(u32));
@ -189,7 +189,7 @@ namespace skyline {
* @param imm16 The 16-bit value to store
* @param shift The offset (in bits and 16-bit aligned) in the register to store the value at
*/
Movz(regs::X destReg, u16 imm16, u8 shift = 0) {
inline constexpr Movz(regs::X destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = static_cast<u8>(shift / 16);
@ -203,7 +203,7 @@ namespace skyline {
* @param imm16 The 16-bit value to store
* @param shift The offset (in bits and 16-bit aligned) in the register to store the value at
*/
Movz(regs::W destReg, u16 imm16, u8 shift = 0) {
inline constexpr Movz(regs::W destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = static_cast<u8>(shift / 16);
@ -215,7 +215,7 @@ namespace skyline {
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction
*/
inline u8 Shift() {
inline constexpr u8 Shift() {
return static_cast<u8>(hw * 16);
}
@ -223,19 +223,19 @@ namespace skyline {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVZ instruction
*/
inline bool Verify() {
inline constexpr bool Verify() {
return (sig == 0xA5);
}
union {
struct __attribute__((packed)) {
u8 destReg : 5;
u16 imm16 : 16;
u8 hw : 2;
u8 sig : 8;
u8 sf : 1;
u8 destReg : 5; //!< 5-bit destination register
u16 imm16 : 16; //!< 16-bit immediate value
u8 hw : 2; //!< 2-bit offset
u8 sig : 8; //!< 8-bit signature (0xA5)
u8 sf : 1; //!< 1-bit register type
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(Movz) == sizeof(u32));
@ -251,7 +251,7 @@ namespace skyline {
* @param imm16 The 16-bit value to store
* @param shift The offset (in bits and 16-bit aligned) in the register to store the value at
*/
Movk(regs::X destReg, u16 imm16, u8 shift = 0) {
inline constexpr Movk(regs::X destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = static_cast<u8>(shift / 16);
@ -265,7 +265,7 @@ namespace skyline {
* @param imm16 The 16-bit value to store
* @param shift The offset (in bits and 16-bit aligned) in the register to store the value at
*/
Movk(regs::W destReg, u16 imm16, u8 shift = 0) {
inline constexpr Movk(regs::W destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = static_cast<u8>(shift / 16);
@ -277,7 +277,7 @@ namespace skyline {
* @brief Returns the offset of the instruction
* @return The offset encoded within the instruction
*/
inline u8 Shift() {
inline constexpr u8 Shift() {
return static_cast<u8>(hw * 16);
}
@ -285,24 +285,29 @@ namespace skyline {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVK instruction
*/
inline bool Verify() {
inline constexpr bool Verify() {
return (sig == 0xE5);
}
union {
struct __attribute__((packed)) {
u8 destReg : 5;
u16 imm16 : 16;
u8 hw : 2;
u8 sig : 8;
u8 sf : 1;
u8 destReg : 5; //!< 5-bit destination register
u16 imm16 : 16; //!< 16-bit immediate value
u8 hw : 2; //!< 2-bit offset
u8 sig : 8; //!< 8-bit signature (0xA5)
u8 sf : 1; //!< 1-bit register type
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(Movk) == sizeof(u32));
const std::vector<u32> MoveU64Reg(regs::X destReg, u64 value) {
/**
* @param destReg The destination register of the operation
* @param value The 64-bit value to insert into the register
* @return A vector with the instructions to insert the value
*/
inline const std::vector<u32> MoveU64Reg(regs::X destReg, u64 value) {
union {
u64 val;
struct {
@ -328,7 +333,12 @@ namespace skyline {
return instr;
}
const std::vector<u32> MoveU32Reg(regs::X destReg, u32 value) {
/**
* @param destReg The destination register of the operation
* @param value The 32-bit value to insert into the register
* @return A vector with the instructions to insert the value
*/
inline const std::vector<u32> MoveU32Reg(regs::X destReg, u32 value) {
union {
u32 val;
struct {
@ -356,12 +366,12 @@ namespace skyline {
* @param destReg The destination Xn register to store the value in
* @param srcReg The source Xn register to retrieve the value from
*/
Mov(regs::X destReg, regs::X srcReg) {
inline constexpr Mov(regs::X destReg, regs::X srcReg) {
this->destReg = static_cast<u8>(destReg);
zeroReg = 0x1F;
sig0 = 0x1F;
imm6 = 0;
this->srcReg = static_cast<u8>(srcReg);
sig = 0x150;
sig1 = 0x150;
sf = 1;
}
@ -370,12 +380,12 @@ namespace skyline {
* @param destReg The destination Wn register to store the value in
* @param srcReg The source Wn register to retrieve the value from
*/
Mov(regs::W destReg, regs::W srcReg) {
inline constexpr Mov(regs::W destReg, regs::W srcReg) {
this->destReg = static_cast<u8>(destReg);
zeroReg = 0x1F;
sig0 = 0x1F;
imm6 = 0;
this->srcReg = static_cast<u8>(srcReg);
sig = 0x150;
sig1 = 0x150;
sf = 0;
}
@ -383,20 +393,20 @@ namespace skyline {
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid MOVZ instruction
*/
inline bool Verify() {
return (sig == 0x150);
inline constexpr bool Verify() {
return (sig0 == 0x1F) && (sig1 == 0x150);
}
union {
struct __attribute__((packed)) {
u8 destReg : 5;
u8 zeroReg : 5;
u8 imm6 : 6;
u8 srcReg : 5;
u16 sig : 10;
u8 sf : 1;
u8 destReg : 5; //!< 5-bit destination register
u8 sig0 : 5; //!< 5-bit signature (0x1F)
u8 imm6 : 6; //!< 6-bit immediate value
u8 srcReg : 5; //!< 5-bit source register
u16 sig1 : 10; //!< 10-bit signature (0x150)
u8 sf : 1; //!< 1-bit register type
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(Mov) == sizeof(u32));
@ -410,27 +420,27 @@ namespace skyline {
* @brief Creates a LDR (immediate) instruction
* @param raw The raw value of the whole instruction
*/
Ldr(u32 raw) : raw(raw) {}
inline constexpr Ldr(u32 raw) : raw(raw) {}
/**
* @brief Returns if the opcode is valid or not
* @return If the opcode represents a valid FCVTZU instruction
*/
inline bool Verify() {
inline constexpr bool Verify() {
return (sig0 == 0x0 && sig1 == 0x1CA && sig2 == 0x1);
}
union {
struct __attribute__((packed)) {
u8 destReg : 5;
u8 srcReg : 5;
u8 sig0 : 2;
u16 imm : 9;
u16 sig1 : 9;
u8 x : 1;
u8 sig2 : 1;
u8 destReg : 5; //!< 5-bit destination register
u8 srcReg : 5; //!< 5-bit source register
u8 sig0 : 2; //!< 2-bit signature (0x0)
u16 imm : 9; //!< 6-bit immediate value
u16 sig1 : 9; //!< 9-bit signature (0x1CA)
u8 sf : 1; //!< 1-bit register type
u8 sig2 : 1; //!< 1-bit signature (0x1)
};
u32 raw{};
u32 raw{}; //!< The raw value of the instruction
};
};
static_assert(sizeof(Ldr) == sizeof(u32));