aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instruction32
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-05-26 17:49:21 -0300
committergdkchan <gab.dark.100@gmail.com>2018-05-26 17:50:47 -0300
commit9670c096e410add36314a247b77334c0c1d61256 (patch)
treedc66ff6966b5544ee78e45b571c187225f96c35d /ChocolArm64/Instruction32
parentcb1cf489f96b09872f8a9db41226c6f5d1654575 (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.cs7
-rw-r--r--ChocolArm64/Instruction32/A32InstInterpretFlow.cs70
-rw-r--r--ChocolArm64/Instruction32/A32InstInterpretHelper.cs65
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