From 584148de0abf2b513425fe79113dd29d8bcb3bf5 Mon Sep 17 00:00:00 2001 From: Arthur Chan Date: Mon, 23 Jul 2018 09:27:57 +0800 Subject: [PATCH] Adding BLX_REG --- ChocolArm64/AOpCodeTable.cs | 1 + ChocolArm64/Decoder32/A32OpCodeBReg.cs | 14 +++++ .../Instruction32/A32InstInterpretFlow.cs | 56 ++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 ChocolArm64/Decoder32/A32OpCodeBReg.cs diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index 689e039237..c9b2b7576e 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -17,6 +17,7 @@ namespace ChocolArm64 SetA32("<<<<1010xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.B, typeof(A32OpCodeBImmAl)); SetA32("<<<<1011xxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Bl, typeof(A32OpCodeBImmAl)); SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", A32InstInterpret.Blx, typeof(A32OpCodeBImmAl)); + SetA32("<<<<000100101111111111110011xxxx", A32InstInterpret.Blx, typeof(A32OpCodeBReg)); #endregion #region "OpCode Table (AArch64)" diff --git a/ChocolArm64/Decoder32/A32OpCodeBReg.cs b/ChocolArm64/Decoder32/A32OpCodeBReg.cs new file mode 100644 index 0000000000..790e7e3946 --- /dev/null +++ b/ChocolArm64/Decoder32/A32OpCodeBReg.cs @@ -0,0 +1,14 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder32 +{ + class A32OpCodeBReg : A32OpCode + { + public int Rm { get; private set; } + + public A32OpCodeBReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rm = (OpCode >> 0) & 0xf; + } + } +} \ No newline at end of file diff --git a/ChocolArm64/Instruction32/A32InstInterpretFlow.cs b/ChocolArm64/Instruction32/A32InstInterpretFlow.cs index 223fd186ca..4f66234fa8 100644 --- a/ChocolArm64/Instruction32/A32InstInterpretFlow.cs +++ b/ChocolArm64/Instruction32/A32InstInterpretFlow.cs @@ -21,15 +21,23 @@ namespace ChocolArm64.Instruction32 public static void Bl(AThreadState State, AMemory Memory, AOpCode OpCode) { - Blx(State, Memory, OpCode, false); + Blx_Imm(State, Memory, OpCode, false); } public static void Blx(AThreadState State, AMemory Memory, AOpCode OpCode) { - Blx(State, Memory, OpCode, true); + switch (OpCode) + { + case A32OpCodeBImmAl Op: + Blx_Imm(State, Memory, Op, true); + break; + case A32OpCodeBReg Op: + Blx_Reg(State, Memory, Op); + break; + } } - public static void Blx(AThreadState State, AMemory Memory, AOpCode OpCode, bool X) + private static void Blx_Imm(AThreadState State, AMemory Memory, AOpCode OpCode, bool X) { A32OpCodeBImmAl Op = (A32OpCodeBImmAl)OpCode; @@ -60,11 +68,53 @@ namespace ChocolArm64.Instruction32 } } + private static void Blx_Reg(AThreadState State, AMemory Memory, AOpCode OpCode) + { + A32OpCodeBReg Op = (A32OpCodeBReg)OpCode; + + if (IsConditionTrue(State, Op.Cond)) + { + uint Pc = GetPc(State); + + if (State.Thumb) + { + State.R14 = (Pc - 2U) | 1; + } + else + { + State.R14 = Pc - 4U; + } + + BXWritePC(State, GetReg(State, Op.Rm)); + } + } + private static void BranchWritePc(AThreadState State, uint Pc) { State.R15 = State.Thumb ? Pc & ~1U : Pc & ~3U; } + + private static void BXWritePC(AThreadState State, uint Pc) + { + if ((Pc & 1U) == 1) + { + State.Thumb = true; + State.R15 = Pc & ~1U; + } + else + { + State.Thumb = false; + // For branches to an unaligned PC counter in A32 state, the processor takes the branch + // and does one of: + // * Forces the address to be aligned + // * Leaves the PC unaligned, meaning the target generates a PC Alignment fault. + if ((Pc & 2U) == 2 /*&& ConstrainUnpredictableBool()*/) + { + State.R15 = Pc & ~2U; + } + } + } } } \ No newline at end of file