diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-05-26 17:49:21 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-05-26 17:50:47 -0300 |
| commit | 9670c096e410add36314a247b77334c0c1d61256 (patch) | |
| tree | dc66ff6966b5544ee78e45b571c187225f96c35d /ChocolArm64/Instruction32 | |
| parent | cb1cf489f96b09872f8a9db41226c6f5d1654575 (diff) | |
Initial work to support AArch32 with a interpreter, plus nvmm stubs (not used for now)
Diffstat (limited to 'ChocolArm64/Instruction32')
| -rw-r--r-- | ChocolArm64/Instruction32/A32InstInterpretAlu.cs | 7 | ||||
| -rw-r--r-- | ChocolArm64/Instruction32/A32InstInterpretFlow.cs | 70 | ||||
| -rw-r--r-- | ChocolArm64/Instruction32/A32InstInterpretHelper.cs | 65 |
3 files changed, 142 insertions, 0 deletions
diff --git a/ChocolArm64/Instruction32/A32InstInterpretAlu.cs b/ChocolArm64/Instruction32/A32InstInterpretAlu.cs new file mode 100644 index 00000000..41b9d22a --- /dev/null +++ b/ChocolArm64/Instruction32/A32InstInterpretAlu.cs @@ -0,0 +1,7 @@ +namespace ChocolArm64.Instruction32 +{ + static partial class A32InstInterpret + { + + } +}
\ No newline at end of file diff --git a/ChocolArm64/Instruction32/A32InstInterpretFlow.cs b/ChocolArm64/Instruction32/A32InstInterpretFlow.cs new file mode 100644 index 00000000..223fd186 --- /dev/null +++ b/ChocolArm64/Instruction32/A32InstInterpretFlow.cs @@ -0,0 +1,70 @@ +using ChocolArm64.Decoder; +using ChocolArm64.Decoder32; +using ChocolArm64.Memory; +using ChocolArm64.State; + +using static ChocolArm64.Instruction32.A32InstInterpretHelper; + +namespace ChocolArm64.Instruction32 +{ + static partial class A32InstInterpret + { + public static void B(AThreadState State, AMemory Memory, AOpCode OpCode) + { + A32OpCodeBImmAl Op = (A32OpCodeBImmAl)OpCode; + + if (IsConditionTrue(State, Op.Cond)) + { + BranchWritePc(State, GetPc(State) + (uint)Op.Imm); + } + } + + public static void Bl(AThreadState State, AMemory Memory, AOpCode OpCode) + { + Blx(State, Memory, OpCode, false); + } + + public static void Blx(AThreadState State, AMemory Memory, AOpCode OpCode) + { + Blx(State, Memory, OpCode, true); + } + + public static void Blx(AThreadState State, AMemory Memory, AOpCode OpCode, bool X) + { + A32OpCodeBImmAl Op = (A32OpCodeBImmAl)OpCode; + + if (IsConditionTrue(State, Op.Cond)) + { + uint Pc = GetPc(State); + + if (State.Thumb) + { + State.R14 = Pc | 1; + } + else + { + State.R14 = Pc - 4U; + } + + if (X) + { + State.Thumb = !State.Thumb; + } + + if (!State.Thumb) + { + Pc &= ~3U; + } + + BranchWritePc(State, Pc + (uint)Op.Imm); + } + } + + private static void BranchWritePc(AThreadState State, uint Pc) + { + State.R15 = State.Thumb + ? Pc & ~1U + : Pc & ~3U; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Instruction32/A32InstInterpretHelper.cs b/ChocolArm64/Instruction32/A32InstInterpretHelper.cs new file mode 100644 index 00000000..9c3c098e --- /dev/null +++ b/ChocolArm64/Instruction32/A32InstInterpretHelper.cs @@ -0,0 +1,65 @@ +using ChocolArm64.Decoder; +using ChocolArm64.State; +using System; + +namespace ChocolArm64.Instruction32 +{ + static class A32InstInterpretHelper + { + public static bool IsConditionTrue(AThreadState State, ACond Cond) + { + switch (Cond) + { + case ACond.Eq: return State.Zero; + case ACond.Ne: return !State.Zero; + case ACond.Ge_Un: return State.Carry; + case ACond.Lt_Un: return !State.Carry; + case ACond.Mi: return State.Negative; + case ACond.Pl: return !State.Negative; + case ACond.Vs: return State.Overflow; + case ACond.Vc: return !State.Overflow; + case ACond.Gt_Un: return State.Carry && !State.Zero; + case ACond.Le_Un: return !State.Carry && State.Zero; + case ACond.Ge: return State.Negative == State.Overflow; + case ACond.Lt: return State.Negative != State.Overflow; + case ACond.Gt: return State.Negative == State.Overflow && !State.Zero; + case ACond.Le: return State.Negative != State.Overflow && State.Zero; + } + + return true; + } + + public unsafe static uint GetReg(AThreadState State, int Reg) + { + if ((uint)Reg > 15) + { + throw new ArgumentOutOfRangeException(nameof(Reg)); + } + + fixed (uint* Ptr = &State.R0) + { + return *(Ptr + Reg); + } + } + + public unsafe static void SetReg(AThreadState State, int Reg, uint Value) + { + if ((uint)Reg > 15) + { + throw new ArgumentOutOfRangeException(nameof(Reg)); + } + + fixed (uint* Ptr = &State.R0) + { + *(Ptr + Reg) = Value; + } + } + + public static uint GetPc(AThreadState State) + { + //Due to the old fetch-decode-execute pipeline of old ARM CPUs, + //the PC is 4 or 8 bytes (2 instructions) ahead of the current instruction. + return State.R15 + (State.Thumb ? 2U : 4U); + } + } +}
\ No newline at end of file |
